You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
8.1 KiB
275 lines
8.1 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.Adapter = void 0; |
|
const events_1 = require("events"); |
|
class Adapter extends events_1.EventEmitter { |
|
/** |
|
* In-memory adapter constructor. |
|
* |
|
* @param {Namespace} nsp |
|
*/ |
|
constructor(nsp) { |
|
super(); |
|
this.nsp = nsp; |
|
this.rooms = new Map(); |
|
this.sids = new Map(); |
|
this.encoder = nsp.server.encoder; |
|
} |
|
/** |
|
* To be overridden |
|
*/ |
|
init() { } |
|
/** |
|
* To be overridden |
|
*/ |
|
close() { } |
|
/** |
|
* Returns the number of Socket.IO servers in the cluster |
|
* |
|
* @public |
|
*/ |
|
serverCount() { |
|
return Promise.resolve(1); |
|
} |
|
/** |
|
* Adds a socket to a list of room. |
|
* |
|
* @param {SocketId} id the socket id |
|
* @param {Set<Room>} rooms a set of rooms |
|
* @public |
|
*/ |
|
addAll(id, rooms) { |
|
if (!this.sids.has(id)) { |
|
this.sids.set(id, new Set()); |
|
} |
|
for (const room of rooms) { |
|
this.sids.get(id).add(room); |
|
if (!this.rooms.has(room)) { |
|
this.rooms.set(room, new Set()); |
|
this.emit("create-room", room); |
|
} |
|
if (!this.rooms.get(room).has(id)) { |
|
this.rooms.get(room).add(id); |
|
this.emit("join-room", room, id); |
|
} |
|
} |
|
} |
|
/** |
|
* Removes a socket from a room. |
|
* |
|
* @param {SocketId} id the socket id |
|
* @param {Room} room the room name |
|
*/ |
|
del(id, room) { |
|
if (this.sids.has(id)) { |
|
this.sids.get(id).delete(room); |
|
} |
|
this._del(room, id); |
|
} |
|
_del(room, id) { |
|
const _room = this.rooms.get(room); |
|
if (_room != null) { |
|
const deleted = _room.delete(id); |
|
if (deleted) { |
|
this.emit("leave-room", room, id); |
|
} |
|
if (_room.size === 0 && this.rooms.delete(room)) { |
|
this.emit("delete-room", room); |
|
} |
|
} |
|
} |
|
/** |
|
* Removes a socket from all rooms it's joined. |
|
* |
|
* @param {SocketId} id the socket id |
|
*/ |
|
delAll(id) { |
|
if (!this.sids.has(id)) { |
|
return; |
|
} |
|
for (const room of this.sids.get(id)) { |
|
this._del(room, id); |
|
} |
|
this.sids.delete(id); |
|
} |
|
/** |
|
* Broadcasts a packet. |
|
* |
|
* Options: |
|
* - `flags` {Object} flags for this packet |
|
* - `except` {Array} sids that should be excluded |
|
* - `rooms` {Array} list of rooms to broadcast to |
|
* |
|
* @param {Object} packet the packet object |
|
* @param {Object} opts the options |
|
* @public |
|
*/ |
|
broadcast(packet, opts) { |
|
const flags = opts.flags || {}; |
|
const packetOpts = { |
|
preEncoded: true, |
|
volatile: flags.volatile, |
|
compress: flags.compress |
|
}; |
|
packet.nsp = this.nsp.name; |
|
const encodedPackets = this.encoder.encode(packet); |
|
this.apply(opts, socket => { |
|
if (typeof socket.notifyOutgoingListeners === "function") { |
|
socket.notifyOutgoingListeners(packet); |
|
} |
|
socket.client.writeToEngine(encodedPackets, packetOpts); |
|
}); |
|
} |
|
/** |
|
* Broadcasts a packet and expects multiple acknowledgements. |
|
* |
|
* Options: |
|
* - `flags` {Object} flags for this packet |
|
* - `except` {Array} sids that should be excluded |
|
* - `rooms` {Array} list of rooms to broadcast to |
|
* |
|
* @param {Object} packet the packet object |
|
* @param {Object} opts the options |
|
* @param clientCountCallback - the number of clients that received the packet |
|
* @param ack - the callback that will be called for each client response |
|
* |
|
* @public |
|
*/ |
|
broadcastWithAck(packet, opts, clientCountCallback, ack) { |
|
const flags = opts.flags || {}; |
|
const packetOpts = { |
|
preEncoded: true, |
|
volatile: flags.volatile, |
|
compress: flags.compress |
|
}; |
|
packet.nsp = this.nsp.name; |
|
// we can use the same id for each packet, since the _ids counter is common (no duplicate) |
|
packet.id = this.nsp._ids++; |
|
const encodedPackets = this.encoder.encode(packet); |
|
let clientCount = 0; |
|
this.apply(opts, socket => { |
|
// track the total number of acknowledgements that are expected |
|
clientCount++; |
|
// call the ack callback for each client response |
|
socket.acks.set(packet.id, ack); |
|
if (typeof socket.notifyOutgoingListeners === "function") { |
|
socket.notifyOutgoingListeners(packet); |
|
} |
|
socket.client.writeToEngine(encodedPackets, packetOpts); |
|
}); |
|
clientCountCallback(clientCount); |
|
} |
|
/** |
|
* Gets a list of sockets by sid. |
|
* |
|
* @param {Set<Room>} rooms the explicit set of rooms to check. |
|
*/ |
|
sockets(rooms) { |
|
const sids = new Set(); |
|
this.apply({ rooms }, socket => { |
|
sids.add(socket.id); |
|
}); |
|
return Promise.resolve(sids); |
|
} |
|
/** |
|
* Gets the list of rooms a given socket has joined. |
|
* |
|
* @param {SocketId} id the socket id |
|
*/ |
|
socketRooms(id) { |
|
return this.sids.get(id); |
|
} |
|
/** |
|
* Returns the matching socket instances |
|
* |
|
* @param opts - the filters to apply |
|
*/ |
|
fetchSockets(opts) { |
|
const sockets = []; |
|
this.apply(opts, socket => { |
|
sockets.push(socket); |
|
}); |
|
return Promise.resolve(sockets); |
|
} |
|
/** |
|
* Makes the matching socket instances join the specified rooms |
|
* |
|
* @param opts - the filters to apply |
|
* @param rooms - the rooms to join |
|
*/ |
|
addSockets(opts, rooms) { |
|
this.apply(opts, socket => { |
|
socket.join(rooms); |
|
}); |
|
} |
|
/** |
|
* Makes the matching socket instances leave the specified rooms |
|
* |
|
* @param opts - the filters to apply |
|
* @param rooms - the rooms to leave |
|
*/ |
|
delSockets(opts, rooms) { |
|
this.apply(opts, socket => { |
|
rooms.forEach(room => socket.leave(room)); |
|
}); |
|
} |
|
/** |
|
* Makes the matching socket instances disconnect |
|
* |
|
* @param opts - the filters to apply |
|
* @param close - whether to close the underlying connection |
|
*/ |
|
disconnectSockets(opts, close) { |
|
this.apply(opts, socket => { |
|
socket.disconnect(close); |
|
}); |
|
} |
|
apply(opts, callback) { |
|
const rooms = opts.rooms; |
|
const except = this.computeExceptSids(opts.except); |
|
if (rooms.size) { |
|
const ids = new Set(); |
|
for (const room of rooms) { |
|
if (!this.rooms.has(room)) |
|
continue; |
|
for (const id of this.rooms.get(room)) { |
|
if (ids.has(id) || except.has(id)) |
|
continue; |
|
const socket = this.nsp.sockets.get(id); |
|
if (socket) { |
|
callback(socket); |
|
ids.add(id); |
|
} |
|
} |
|
} |
|
} |
|
else { |
|
for (const [id] of this.sids) { |
|
if (except.has(id)) |
|
continue; |
|
const socket = this.nsp.sockets.get(id); |
|
if (socket) |
|
callback(socket); |
|
} |
|
} |
|
} |
|
computeExceptSids(exceptRooms) { |
|
const exceptSids = new Set(); |
|
if (exceptRooms && exceptRooms.size > 0) { |
|
for (const room of exceptRooms) { |
|
if (this.rooms.has(room)) { |
|
this.rooms.get(room).forEach(sid => exceptSids.add(sid)); |
|
} |
|
} |
|
} |
|
return exceptSids; |
|
} |
|
/** |
|
* Send a packet to the other Socket.IO servers in the cluster |
|
* @param packet - an array of arguments, which may include an acknowledgement callback at the end |
|
*/ |
|
serverSideEmit(packet) { |
|
console.warn("this adapter does not support the serverSideEmit() functionality"); |
|
} |
|
} |
|
exports.Adapter = Adapter;
|
|
|