mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 22:23:33 +01:00
PadMessageHandler: Use a Map
for sessioninfos
Maps are a bit more flexible, have clearer semantics, and have a convenient `size` property.
This commit is contained in:
parent
14d4aadfe4
commit
eeead46437
2 changed files with 28 additions and 37 deletions
|
@ -810,15 +810,12 @@ exports.createDiffHTML = async (padID, startRev, endRev) => {
|
||||||
|
|
||||||
exports.getStats = async () => {
|
exports.getStats = async () => {
|
||||||
const sessionInfos = padMessageHandler.sessioninfos;
|
const sessionInfos = padMessageHandler.sessioninfos;
|
||||||
|
const map = function* (it, fn) { for (const i of it) yield fn(i); };
|
||||||
const sessionKeys = Object.keys(sessionInfos);
|
const activePads = new Set(map(sessionInfos.values(), ({padId}) => padId));
|
||||||
const activePads = new Set(Object.entries(sessionInfos).map((k) => k[1].padId));
|
|
||||||
|
|
||||||
const {padIDs} = await padManager.listAllPads();
|
const {padIDs} = await padManager.listAllPads();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalPads: padIDs.length,
|
totalPads: padIDs.length,
|
||||||
totalSessions: sessionKeys.length,
|
totalSessions: sessionInfos.size,
|
||||||
totalActivePads: activePads.size,
|
totalActivePads: activePads.size,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,13 +67,13 @@ exports.socketio = () => {
|
||||||
* - readonly: Whether the client has read-only access (true) or read/write access (false).
|
* - readonly: Whether the client has read-only access (true) or read/write access (false).
|
||||||
* - rev: The last revision that was sent to the client.
|
* - rev: The last revision that was sent to the client.
|
||||||
*/
|
*/
|
||||||
const sessioninfos = {};
|
const sessioninfos = new Map();
|
||||||
exports.sessioninfos = sessioninfos;
|
exports.sessioninfos = sessioninfos;
|
||||||
|
|
||||||
stats.gauge('totalUsers', () => Object.keys(socketio.sockets.sockets).length);
|
stats.gauge('totalUsers', () => Object.keys(socketio.sockets.sockets).length);
|
||||||
stats.gauge('activePads', () => {
|
stats.gauge('activePads', () => {
|
||||||
const padIds = new Set();
|
const padIds = new Set();
|
||||||
for (const {padId} of Object.values(sessioninfos)) {
|
for (const {padId} of sessioninfos.values()) {
|
||||||
if (!padId) continue;
|
if (!padId) continue;
|
||||||
padIds.add(padId);
|
padIds.add(padId);
|
||||||
}
|
}
|
||||||
|
@ -106,9 +106,7 @@ exports.setSocketIO = (socket_io) => {
|
||||||
*/
|
*/
|
||||||
exports.handleConnect = (socket) => {
|
exports.handleConnect = (socket) => {
|
||||||
stats.meter('connects').mark();
|
stats.meter('connects').mark();
|
||||||
|
sessioninfos.set(socket.id, {});
|
||||||
// Initialize sessioninfos for this new session
|
|
||||||
sessioninfos[socket.id] = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,9 +128,7 @@ exports.kickSessionsFromPad = (padID) => {
|
||||||
*/
|
*/
|
||||||
exports.handleDisconnect = async (socket) => {
|
exports.handleDisconnect = async (socket) => {
|
||||||
stats.meter('disconnects').mark();
|
stats.meter('disconnects').mark();
|
||||||
|
const session = sessioninfos.get(socket.id);
|
||||||
// save the padname of this session
|
|
||||||
const session = sessioninfos[socket.id];
|
|
||||||
|
|
||||||
// if this connection was already etablished with a handshake,
|
// if this connection was already etablished with a handshake,
|
||||||
// send a disconnect message to the others
|
// send a disconnect message to the others
|
||||||
|
@ -166,9 +162,7 @@ exports.handleDisconnect = async (socket) => {
|
||||||
// Allow plugins to hook into users leaving the pad
|
// Allow plugins to hook into users leaving the pad
|
||||||
hooks.callAll('userLeave', session);
|
hooks.callAll('userLeave', session);
|
||||||
}
|
}
|
||||||
|
sessioninfos.delete(socket.id);
|
||||||
// Delete the sessioninfos entrys of this session
|
|
||||||
delete sessioninfos[socket.id];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,7 +193,7 @@ exports.handleMessage = async (socket, message) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thisSession = sessioninfos[socket.id];
|
const thisSession = sessioninfos.get(socket.id);
|
||||||
|
|
||||||
if (!thisSession) {
|
if (!thisSession) {
|
||||||
messageLogger.warn('Dropped message from an unknown connection.');
|
messageLogger.warn('Dropped message from an unknown connection.');
|
||||||
|
@ -256,7 +250,7 @@ exports.handleMessage = async (socket, message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop the message if the client disconnected during the above processing.
|
// Drop the message if the client disconnected during the above processing.
|
||||||
if (sessioninfos[socket.id] !== thisSession) {
|
if (sessioninfos.get(socket.id) !== thisSession) {
|
||||||
messageLogger.warn('Dropping message from a connection that has gone away.');
|
messageLogger.warn('Dropping message from a connection that has gone away.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +295,7 @@ exports.handleMessage = async (socket, message) => {
|
||||||
* @param message the message from the client
|
* @param message the message from the client
|
||||||
*/
|
*/
|
||||||
const handleSaveRevisionMessage = async (socket, message) => {
|
const handleSaveRevisionMessage = async (socket, message) => {
|
||||||
const {padId, author: authorId} = sessioninfos[socket.id];
|
const {padId, author: authorId} = sessioninfos.get(socket.id);
|
||||||
const pad = await padManager.getPad(padId);
|
const pad = await padManager.getPad(padId);
|
||||||
await pad.addSavedRevision(pad.head, authorId);
|
await pad.addSavedRevision(pad.head, authorId);
|
||||||
};
|
};
|
||||||
|
@ -351,7 +345,7 @@ exports.handleCustomMessage = (padID, msgString) => {
|
||||||
const handleChatMessage = async (socket, message) => {
|
const handleChatMessage = async (socket, message) => {
|
||||||
const time = Date.now();
|
const time = Date.now();
|
||||||
const text = message.data.text;
|
const text = message.data.text;
|
||||||
const {padId, author: authorId} = sessioninfos[socket.id];
|
const {padId, author: authorId} = sessioninfos.get(socket.id);
|
||||||
await exports.sendChatMessageToPadClients(time, authorId, text, padId);
|
await exports.sendChatMessageToPadClients(time, authorId, text, padId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -409,7 +403,7 @@ const handleGetChatMessages = async (socket, message) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const padId = sessioninfos[socket.id].padId;
|
const {padId} = sessioninfos.get(socket.id);
|
||||||
const pad = await padManager.getPad(padId);
|
const pad = await padManager.getPad(padId);
|
||||||
|
|
||||||
const chatMessages = await pad.getChatMessages(start, end);
|
const chatMessages = await pad.getChatMessages(start, end);
|
||||||
|
@ -442,11 +436,11 @@ const handleSuggestUserName = (socket, message) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const padId = sessioninfos[socket.id].padId;
|
const {padId} = sessioninfos.get(socket.id);
|
||||||
|
|
||||||
// search the author and send him this message
|
// search the author and send him this message
|
||||||
_getRoomSockets(padId).forEach((socket) => {
|
_getRoomSockets(padId).forEach((socket) => {
|
||||||
const session = sessioninfos[socket.id];
|
const session = sessioninfos.get(socket.id);
|
||||||
if (session && session.author === message.data.payload.unnamedId) {
|
if (session && session.author === message.data.payload.unnamedId) {
|
||||||
socket.json.send(message);
|
socket.json.send(message);
|
||||||
}
|
}
|
||||||
|
@ -472,7 +466,7 @@ const handleUserInfoUpdate = async (socket, message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that we have a valid session and author to update.
|
// Check that we have a valid session and author to update.
|
||||||
const session = sessioninfos[socket.id];
|
const session = sessioninfos.get(socket.id);
|
||||||
if (!session || !session.author || !session.padId) {
|
if (!session || !session.author || !session.padId) {
|
||||||
messageLogger.warn(`Dropped message, USERINFO_UPDATE Session not ready.${message.data}`);
|
messageLogger.warn(`Dropped message, USERINFO_UPDATE Session not ready.${message.data}`);
|
||||||
return;
|
return;
|
||||||
|
@ -554,7 +548,7 @@ const handleUserChanges = async (socket, message) => {
|
||||||
|
|
||||||
// The client might disconnect between our callbacks. We should still
|
// The client might disconnect between our callbacks. We should still
|
||||||
// finish processing the changeset, so keep a reference to the session.
|
// finish processing the changeset, so keep a reference to the session.
|
||||||
const thisSession = sessioninfos[socket.id];
|
const thisSession = sessioninfos.get(socket.id);
|
||||||
|
|
||||||
// TODO: this might happen with other messages too => find one place to copy the session
|
// TODO: this might happen with other messages too => find one place to copy the session
|
||||||
// and always use the copy. atm a message will be ignored if the session is gone even
|
// and always use the copy. atm a message will be ignored if the session is gone even
|
||||||
|
@ -716,7 +710,7 @@ exports.updatePadClients = async (pad) => {
|
||||||
const revCache = {};
|
const revCache = {};
|
||||||
|
|
||||||
await Promise.all(roomSockets.map(async (socket) => {
|
await Promise.all(roomSockets.map(async (socket) => {
|
||||||
const sessioninfo = sessioninfos[socket.id];
|
const sessioninfo = sessioninfos.get(socket.id);
|
||||||
// The user might have disconnected since _getRoomSockets() was called.
|
// The user might have disconnected since _getRoomSockets() was called.
|
||||||
if (sessioninfo == null) return;
|
if (sessioninfo == null) return;
|
||||||
|
|
||||||
|
@ -811,7 +805,7 @@ const _correctMarkersInPad = (atext, apool) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSwitchToPad = async (socket, message, _authorID) => {
|
const handleSwitchToPad = async (socket, message, _authorID) => {
|
||||||
const currentSessionInfo = sessioninfos[socket.id];
|
const currentSessionInfo = sessioninfos.get(socket.id);
|
||||||
const padId = currentSessionInfo.padId;
|
const padId = currentSessionInfo.padId;
|
||||||
|
|
||||||
// Check permissions for the new pad.
|
// Check permissions for the new pad.
|
||||||
|
@ -830,20 +824,20 @@ const handleSwitchToPad = async (socket, message, _authorID) => {
|
||||||
assert(authorID === currentSessionInfo.author);
|
assert(authorID === currentSessionInfo.author);
|
||||||
|
|
||||||
// Check if the connection dropped during the access check.
|
// Check if the connection dropped during the access check.
|
||||||
if (sessioninfos[socket.id] !== currentSessionInfo) return;
|
if (sessioninfos.get(socket.id) !== currentSessionInfo) return;
|
||||||
|
|
||||||
// clear the session and leave the room
|
// clear the session and leave the room
|
||||||
_getRoomSockets(padId).forEach((socket) => {
|
_getRoomSockets(padId).forEach((socket) => {
|
||||||
const sinfo = sessioninfos[socket.id];
|
const sinfo = sessioninfos.get(socket.id);
|
||||||
if (sinfo && sinfo.author === currentSessionInfo.author) {
|
if (sinfo && sinfo.author === currentSessionInfo.author) {
|
||||||
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
||||||
sessioninfos[socket.id] = {};
|
sessioninfos.set(socket.id, {});
|
||||||
socket.leave(padId);
|
socket.leave(padId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// start up the new pad
|
// start up the new pad
|
||||||
const newSessionInfo = sessioninfos[socket.id];
|
const newSessionInfo = sessioninfos.get(socket.id);
|
||||||
createSessionInfoAuth(newSessionInfo, message);
|
createSessionInfoAuth(newSessionInfo, message);
|
||||||
await handleClientReady(socket, message, authorID);
|
await handleClientReady(socket, message, authorID);
|
||||||
};
|
};
|
||||||
|
@ -927,17 +921,17 @@ const handleClientReady = async (socket, message, authorID) => {
|
||||||
// glue the clientVars together, send them and tell the other clients that a new one is there
|
// glue the clientVars together, send them and tell the other clients that a new one is there
|
||||||
|
|
||||||
// Check that the client is still here. It might have disconnected between callbacks.
|
// Check that the client is still here. It might have disconnected between callbacks.
|
||||||
const sessionInfo = sessioninfos[socket.id];
|
const sessionInfo = sessioninfos.get(socket.id);
|
||||||
if (sessionInfo == null) return;
|
if (sessionInfo == null) return;
|
||||||
|
|
||||||
// Check if this author is already on the pad, if yes, kick the other sessions!
|
// Check if this author is already on the pad, if yes, kick the other sessions!
|
||||||
const roomSockets = _getRoomSockets(pad.id);
|
const roomSockets = _getRoomSockets(pad.id);
|
||||||
|
|
||||||
for (const socket of roomSockets) {
|
for (const socket of roomSockets) {
|
||||||
const sinfo = sessioninfos[socket.id];
|
const sinfo = sessioninfos.get(socket.id);
|
||||||
if (sinfo && sinfo.author === authorID) {
|
if (sinfo && sinfo.author === authorID) {
|
||||||
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
||||||
sessioninfos[socket.id] = {};
|
sessioninfos.set(socket.id, {});
|
||||||
socket.leave(padIds.padId);
|
socket.leave(padIds.padId);
|
||||||
socket.json.send({disconnect: 'userdup'});
|
socket.json.send({disconnect: 'userdup'});
|
||||||
}
|
}
|
||||||
|
@ -1151,7 +1145,7 @@ const handleClientReady = async (socket, message, authorID) => {
|
||||||
|
|
||||||
// Since sessioninfos might change while being enumerated, check if the
|
// Since sessioninfos might change while being enumerated, check if the
|
||||||
// sessionID is still assigned to a valid session
|
// sessionID is still assigned to a valid session
|
||||||
const sessionInfo = sessioninfos[roomSocket.id];
|
const sessionInfo = sessioninfos.get(roomSocket.id);
|
||||||
if (sessionInfo == null) return;
|
if (sessionInfo == null) return;
|
||||||
|
|
||||||
// get the authorname & colorId
|
// get the authorname & colorId
|
||||||
|
@ -1433,7 +1427,7 @@ exports.padUsers = async (padID) => {
|
||||||
|
|
||||||
// iterate over all clients (in parallel)
|
// iterate over all clients (in parallel)
|
||||||
await Promise.all(_getRoomSockets(padID).map(async (roomSocket) => {
|
await Promise.all(_getRoomSockets(padID).map(async (roomSocket) => {
|
||||||
const s = sessioninfos[roomSocket.id];
|
const s = sessioninfos.get(roomSocket.id);
|
||||||
if (s) {
|
if (s) {
|
||||||
const author = await authorManager.getAuthor(s.author);
|
const author = await authorManager.getAuthor(s.author);
|
||||||
// Fixes: https://github.com/ether/etherpad-lite/issues/4120
|
// Fixes: https://github.com/ether/etherpad-lite/issues/4120
|
||||||
|
|
Loading…
Reference in a new issue