feature/IO-2967-Better-Refetch-Handling - Bug fixes and hardening
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -192,7 +192,7 @@ const main = async () => {
|
|||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
|
|
||||||
const { pubClient, ioRedis } = await applySocketIO(server, app);
|
const { pubClient, ioRedis } = await applySocketIO(server, app);
|
||||||
const api = applyRedisHelpers(pubClient, app);
|
const api = applyRedisHelpers(pubClient, app, logger);
|
||||||
const ioHelpers = applyIOHelpers(app, api, ioRedis, logger);
|
const ioHelpers = applyIOHelpers(app, api, ioRedis, logger);
|
||||||
|
|
||||||
// Legacy Socket Events
|
// Legacy Socket Events
|
||||||
@@ -211,11 +211,9 @@ const main = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
try {
|
main().catch((error) => {
|
||||||
main();
|
|
||||||
} catch (error) {
|
|
||||||
logger.log(`Main-API-Error: Something was not caught in the application.`, "error", "api", null, {
|
logger.log(`Main-API-Error: Something was not caught in the application.`, "error", "api", null, {
|
||||||
error: error.message,
|
error: error.message,
|
||||||
errorjson: JSON.stringify(error)
|
errorjson: JSON.stringify(error)
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|||||||
@@ -1,48 +1,71 @@
|
|||||||
|
const logger = require("./logger");
|
||||||
/**
|
/**
|
||||||
* Apply Redis helper functions
|
* Apply Redis helper functions
|
||||||
* @param pubClient
|
* @param pubClient
|
||||||
* @param app
|
* @param app
|
||||||
*/
|
*/
|
||||||
const applyRedisHelpers = (pubClient, app) => {
|
const applyRedisHelpers = (pubClient, app, logger) => {
|
||||||
// Store session data in Redis
|
// Store session data in Redis
|
||||||
const setSessionData = async (socketId, key, value) => {
|
const setSessionData = async (socketId, key, value) => {
|
||||||
await pubClient.hSet(`socket:${socketId}`, key, JSON.stringify(value)); // Use Redis pubClient
|
try {
|
||||||
|
await pubClient.hSet(`socket:${socketId}`, key, JSON.stringify(value)); // Use Redis pubClient
|
||||||
|
} catch (error) {
|
||||||
|
logger.log(`Error Setting Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve session data from Redis
|
// Retrieve session data from Redis
|
||||||
const getSessionData = async (socketId, key) => {
|
const getSessionData = async (socketId, key) => {
|
||||||
const data = await pubClient.hGet(`socket:${socketId}`, key);
|
try {
|
||||||
return data ? JSON.parse(data) : null;
|
const data = await pubClient.hGet(`socket:${socketId}`, key);
|
||||||
|
return data ? JSON.parse(data) : null;
|
||||||
|
} catch (error) {
|
||||||
|
logger.log(`Error Getting Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clear session data from Redis
|
// Clear session data from Redis
|
||||||
const clearSessionData = async (socketId) => {
|
const clearSessionData = async (socketId) => {
|
||||||
await pubClient.del(`socket:${socketId}`);
|
try {
|
||||||
|
await pubClient.del(`socket:${socketId}`);
|
||||||
|
} catch (error) {
|
||||||
|
logger.log(`Error Clearing Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store multiple session data in Redis
|
// Store multiple session data in Redis
|
||||||
const setMultipleSessionData = async (socketId, keyValues) => {
|
const setMultipleSessionData = async (socketId, keyValues) => {
|
||||||
// keyValues is expected to be an object { key1: value1, key2: value2, ... }
|
try {
|
||||||
const entries = Object.entries(keyValues).map(([key, value]) => [key, JSON.stringify(value)]);
|
// keyValues is expected to be an object { key1: value1, key2: value2, ... }
|
||||||
await pubClient.hSet(`socket:${socketId}`, ...entries.flat());
|
const entries = Object.entries(keyValues).map(([key, value]) => [key, JSON.stringify(value)]);
|
||||||
|
await pubClient.hSet(`socket:${socketId}`, ...entries.flat());
|
||||||
|
} catch (error) {
|
||||||
|
logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve multiple session data from Redis
|
// Retrieve multiple session data from Redis
|
||||||
const getMultipleSessionData = async (socketId, keys) => {
|
const getMultipleSessionData = async (socketId, keys) => {
|
||||||
const data = await pubClient.hmGet(`socket:${socketId}`, keys);
|
try {
|
||||||
// Redis returns an object with null values for missing keys, so we parse the non-null ones
|
const data = await pubClient.hmGet(`socket:${socketId}`, keys);
|
||||||
return Object.fromEntries(keys.map((key, index) => [key, data[index] ? JSON.parse(data[index]) : null]));
|
// Redis returns an object with null values for missing keys, so we parse the non-null ones
|
||||||
|
return Object.fromEntries(keys.map((key, index) => [key, data[index] ? JSON.parse(data[index]) : null]));
|
||||||
|
} catch (error) {
|
||||||
|
logger.log(`Error Getting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setMultipleFromArraySessionData = async (socketId, keyValueArray) => {
|
const setMultipleFromArraySessionData = async (socketId, keyValueArray) => {
|
||||||
// Use Redis multi/pipeline to batch the commands
|
try {
|
||||||
const multi = pubClient.multi();
|
// Use Redis multi/pipeline to batch the commands
|
||||||
|
const multi = pubClient.multi();
|
||||||
keyValueArray.forEach(([key, value]) => {
|
keyValueArray.forEach(([key, value]) => {
|
||||||
multi.hSet(`socket:${socketId}`, key, JSON.stringify(value));
|
multi.hSet(`socket:${socketId}`, key, JSON.stringify(value));
|
||||||
});
|
});
|
||||||
|
await multi.exec(); // Execute all queued commands
|
||||||
await multi.exec(); // Execute all queued commands
|
} catch (error) {
|
||||||
|
logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to add an item to the end of the Redis list
|
// Helper function to add an item to the end of the Redis list
|
||||||
@@ -50,7 +73,7 @@ const applyRedisHelpers = (pubClient, app) => {
|
|||||||
try {
|
try {
|
||||||
await pubClient.rPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
await pubClient.rPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error adding item to the end of the list for socket ${socketId}:`, error);
|
logger.log(`Error adding item to the end of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,7 +82,7 @@ const applyRedisHelpers = (pubClient, app) => {
|
|||||||
try {
|
try {
|
||||||
await pubClient.lPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
await pubClient.lPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error adding item to the beginning of the list for socket ${socketId}:`, error);
|
logger.log(`Error adding item to the beginning of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,33 +91,33 @@ const applyRedisHelpers = (pubClient, app) => {
|
|||||||
try {
|
try {
|
||||||
await pubClient.del(`socket:${socketId}:${key}`);
|
await pubClient.del(`socket:${socketId}:${key}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error clearing list for socket ${socketId}:`, error);
|
logger.log(`Error clearing list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add methods to manage room users
|
// Add methods to manage room users
|
||||||
const addUserToRoom = async (bodyshopUUID, user) => {
|
const addUserToRoom = async (room, user) => {
|
||||||
try {
|
try {
|
||||||
await pubClient.sAdd(`bodyshopRoom:${bodyshopUUID}`, JSON.stringify(user));
|
await pubClient.sAdd(room, JSON.stringify(user));
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error(`Error adding user to room: ${bodyshopUUID}`);
|
logger.log(`Error adding user to room ${room}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeUserFromRoom = async (bodyshopUUID, user) => {
|
const removeUserFromRoom = async (room, user) => {
|
||||||
try {
|
try {
|
||||||
await pubClient.sRem(`bodyshopRoom:${bodyshopUUID}`, JSON.stringify(user));
|
await pubClient.sRem(room, JSON.stringify(user));
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error(`Error remove user from room: ${bodyshopUUID}`);
|
logger.log(`Error removing user to room ${room}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUsersInRoom = async (bodyshopUUID) => {
|
const getUsersInRoom = async (room) => {
|
||||||
try {
|
try {
|
||||||
const users = await pubClient.sMembers(`bodyshopRoom:${bodyshopUUID}`);
|
const users = await pubClient.sMembers(room);
|
||||||
return users.map((user) => JSON.parse(user));
|
return users.map((user) => JSON.parse(user));
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error(`Error getUsersInRoom: ${bodyshopUUID}`);
|
logger.log(`Error getting users in room ${room}: ${error}`, "ERROR", "redis");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ const redisSocketEvents = (io, { addUserToRoom, getUsersInRoom, removeUserFromRo
|
|||||||
try {
|
try {
|
||||||
const room = getBodyshopRoom(bodyshopUUID);
|
const room = getBodyshopRoom(bodyshopUUID);
|
||||||
socket.join(room);
|
socket.join(room);
|
||||||
await addUserToRoom(room, { uid: socket.user.uid, email: socket.user.email });
|
await addUserToRoom(room, { uid: socket.user.uid, email: socket.user.email, socket: socket.id });
|
||||||
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
|
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${room}`);
|
||||||
|
|
||||||
// Notify all users in the room about the updated user list
|
// Notify all users in the room about the updated user list
|
||||||
const usersInRoom = await getUsersInRoom(room);
|
const usersInRoom = await getUsersInRoom(room);
|
||||||
@@ -79,13 +79,8 @@ const redisSocketEvents = (io, { addUserToRoom, getUsersInRoom, removeUserFromRo
|
|||||||
|
|
||||||
// Get all rooms the socket is part of
|
// Get all rooms the socket is part of
|
||||||
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
||||||
|
for (const room of rooms) {
|
||||||
for (const bodyshopRoom of rooms) {
|
await removeUserFromRoom(room, { uid: socket.user.uid, email: socket.user.email, socket: socket.id });
|
||||||
await removeUserFromRoom(bodyshopRoom, { uid: socket.user.uid, email: socket.user.email });
|
|
||||||
|
|
||||||
// Notify all users in the room about the updated user list
|
|
||||||
const usersInRoom = await getUsersInRoom(bodyshopRoom);
|
|
||||||
io.to(bodyshopRoom).emit("room-users-updated", usersInRoom);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createLogEvent(socket, "ERROR", `Error getting room: ${error}`);
|
createLogEvent(socket, "ERROR", `Error getting room: ${error}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user