Compare commits
1 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74d95e7cbb |
@@ -219,7 +219,7 @@ export function JobsExportAllButton({
|
||||
};
|
||||
|
||||
return (
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || jobIds?.length > 10}>
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
||||
{t("jobs.actions.exportselected")}
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -200,7 +200,7 @@ export function PayableExportAll({
|
||||
);
|
||||
|
||||
return (
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || billids?.length > 10}>
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
||||
{t("jobs.actions.exportselected")}
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -180,7 +180,7 @@ export function PaymentsExportAllButton({
|
||||
};
|
||||
|
||||
return (
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || paymentIds?.length > 10}>
|
||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
||||
{t("jobs.actions.exportselected")}
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -23,9 +23,6 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
|
||||
const fired = useRef(false);
|
||||
const client = useApolloClient();
|
||||
const { socket } = useContext(SocketContext); // Get the socket from context
|
||||
const reconnectTimeout = useRef(null); // To store the reconnect timeout
|
||||
const disconnectTime = useRef(null); // To track disconnection time
|
||||
const acceptableReconnectTime = 2000; // 2 seconds threshold
|
||||
|
||||
const {
|
||||
treatments: { Websocket_Production }
|
||||
@@ -129,44 +126,19 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
|
||||
}
|
||||
};
|
||||
|
||||
const handleDisconnect = () => {
|
||||
// Capture the disconnection time
|
||||
disconnectTime.current = Date.now();
|
||||
};
|
||||
|
||||
const handleReconnect = () => {
|
||||
const reconnectTime = Date.now();
|
||||
const disconnectionDuration = reconnectTime - disconnectTime.current;
|
||||
|
||||
// Only refetch if disconnection was longer than the acceptable reconnect time
|
||||
if (disconnectionDuration >= acceptableReconnectTime) {
|
||||
if (!reconnectTimeout.current) {
|
||||
reconnectTimeout.current = setTimeout(() => {
|
||||
const randomDelay = Math.floor(Math.random() * (30000 - 10000 + 1)) + 10000; // Random delay between 10 and 30 seconds
|
||||
setTimeout(() => {
|
||||
if (refetch) refetch().catch((err) => console.error(`Issue `));
|
||||
reconnectTimeout.current = null; // Clear the timeout reference after refetch
|
||||
}, randomDelay);
|
||||
}, acceptableReconnectTime);
|
||||
}
|
||||
}
|
||||
//If we were disconnected from the board, we missed stuff. We need to refresh it entirely.
|
||||
if (refetch) refetch();
|
||||
};
|
||||
|
||||
// Listen for 'job-changed', 'disconnect', and 'connect' events
|
||||
// Listen for 'job-changed' events
|
||||
socket.on("production-job-updated", handleJobUpdates);
|
||||
socket.on("disconnect", handleDisconnect);
|
||||
socket.on("connect", handleReconnect);
|
||||
|
||||
socket.on("reconnect", handleReconnect);
|
||||
// Clean up on unmount or when dependencies change
|
||||
return () => {
|
||||
socket.off("production-job-updated", handleJobUpdates);
|
||||
socket.off("disconnect", handleDisconnect);
|
||||
socket.off("connect", handleReconnect);
|
||||
if (reconnectTimeout.current) {
|
||||
clearTimeout(reconnectTimeout.current);
|
||||
}
|
||||
socket.off("reconnect", handleReconnect);
|
||||
};
|
||||
}, [subscriptionEnabled, socket, bodyshop, client, refetch]);
|
||||
}, [subscriptionEnabled, socket, bodyshop, data, client, refetch]);
|
||||
|
||||
const filteredAssociationSettings = useMemo(() => {
|
||||
return associationSettings?.associations[0] || null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useApolloClient, useQuery, useSubscription } from "@apollo/client";
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
QUERY_EXACT_JOB_IN_PRODUCTION,
|
||||
QUERY_EXACT_JOBS_IN_PRODUCTION,
|
||||
@@ -16,10 +16,6 @@ export default function ProductionListTableContainer({ bodyshop, subscriptionTyp
|
||||
const client = useApolloClient();
|
||||
const { socket } = useContext(SocketContext);
|
||||
const [joblist, setJoblist] = useState([]);
|
||||
const reconnectTimeout = useRef(null); // To store the reconnect timeout
|
||||
const disconnectTime = useRef(null); // To store the time of disconnection
|
||||
|
||||
const acceptableReconnectTime = 2000; // 2 seconds threshold
|
||||
|
||||
// Get Split treatment
|
||||
const {
|
||||
@@ -132,47 +128,18 @@ export default function ProductionListTableContainer({ bodyshop, subscriptionTyp
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDisconnect = () => {
|
||||
// Capture the time when the disconnection happens
|
||||
disconnectTime.current = Date.now();
|
||||
};
|
||||
|
||||
const handleReconnect = () => {
|
||||
// Calculate how long the disconnection lasted
|
||||
const reconnectTime = Date.now();
|
||||
const disconnectionDuration = reconnectTime - disconnectTime.current;
|
||||
|
||||
// If disconnection lasted less than acceptable reconnect time, do nothing
|
||||
if (disconnectionDuration < acceptableReconnectTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule a refetch with a random delay between 10 and 30 seconds
|
||||
if (!reconnectTimeout.current) {
|
||||
reconnectTimeout.current = setTimeout(() => {
|
||||
const randomDelay = Math.floor(Math.random() * (30000 - 10000 + 1)) + 10000; // Random delay between 10 and 30 seconds
|
||||
setTimeout(() => {
|
||||
if (refetch) refetch();
|
||||
reconnectTimeout.current = null; // Clear the timeout reference after refetch
|
||||
}, randomDelay);
|
||||
}, acceptableReconnectTime);
|
||||
}
|
||||
//If we were disconnected from the board, we missed stuff. We need to refresh it entirely.
|
||||
if (refetch) refetch();
|
||||
};
|
||||
|
||||
// Listen for 'production-job-updated', 'disconnect', and 'connect' events
|
||||
// Listen for 'production-job-updated' events
|
||||
socket.on("production-job-updated", handleJobUpdates);
|
||||
socket.on("disconnect", handleDisconnect);
|
||||
socket.on("connect", handleReconnect);
|
||||
socket.on("reconnect", handleReconnect);
|
||||
|
||||
// Clean up on unmount or when dependencies change
|
||||
return () => {
|
||||
socket.off("production-job-updated", handleJobUpdates);
|
||||
socket.off("disconnect", handleDisconnect);
|
||||
socket.off("connect", handleReconnect);
|
||||
if (reconnectTimeout.current) {
|
||||
clearTimeout(reconnectTimeout.current);
|
||||
}
|
||||
socket.off("reconnect", handleReconnect);
|
||||
};
|
||||
}, [subscriptionEnabled, socket, bodyshop, client, refetch]);
|
||||
|
||||
@@ -184,7 +151,6 @@ export default function ProductionListTableContainer({ bodyshop, subscriptionTyp
|
||||
fetchPolicy: "network-only"
|
||||
});
|
||||
};
|
||||
|
||||
const getUpdatedJobsData = (jobIds) => {
|
||||
client.query({
|
||||
query: QUERY_EXACT_JOBS_IN_PRODUCTION,
|
||||
|
||||
21
server.js
21
server.js
@@ -10,7 +10,7 @@ const { createClient } = require("redis");
|
||||
const { createAdapter } = require("@socket.io/redis-adapter");
|
||||
const logger = require("./server/utils/logger");
|
||||
const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents");
|
||||
const { instrument } = require("@socket.io/admin-ui");
|
||||
const { instrument, RedisStore } = require("@socket.io/admin-ui");
|
||||
|
||||
const { isString, isEmpty } = require("lodash");
|
||||
const applyRedisHelpers = require("./server/utils/redisHelpers");
|
||||
@@ -63,8 +63,13 @@ const applyMiddleware = (app) => {
|
||||
app.use(cookieParser());
|
||||
app.use(bodyParser.json({ limit: "50mb" }));
|
||||
app.use(bodyParser.urlencoded({ limit: "50mb", extended: true }));
|
||||
app.use(cors({ credentials: true, exposedHeaders: ["set-cookie"] }));
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin: SOCKETIO_CORS_ORIGIN,
|
||||
credentials: true,
|
||||
exposedHeaders: ["set-cookie"]
|
||||
})
|
||||
);
|
||||
// Helper middleware
|
||||
app.use((req, res, next) => {
|
||||
req.logger = logger;
|
||||
@@ -187,7 +192,7 @@ const main = async () => {
|
||||
const server = http.createServer(app);
|
||||
|
||||
const { pubClient, ioRedis } = await applySocketIO(server, app);
|
||||
const api = applyRedisHelpers(pubClient, app, logger);
|
||||
const api = applyRedisHelpers(pubClient, app);
|
||||
const ioHelpers = applyIOHelpers(app, api, ioRedis, logger);
|
||||
|
||||
// Legacy Socket Events
|
||||
@@ -206,11 +211,11 @@ const main = async () => {
|
||||
};
|
||||
|
||||
// Start server
|
||||
main().catch((error) => {
|
||||
try {
|
||||
main();
|
||||
} catch (error) {
|
||||
logger.log(`Main-API-Error: Something was not caught in the application.`, "error", "api", null, {
|
||||
error: error.message,
|
||||
errorjson: JSON.stringify(error)
|
||||
});
|
||||
// Note: If we want the app to crash on all uncaught async operations, we would
|
||||
// need to put a `process.exit(1);` here
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const logger = require("../utils/logger");
|
||||
const client = require("../graphql-client/graphql-client").client;
|
||||
const queries = require("../graphql-client/queries");
|
||||
const generateEmailTemplate = require("./generateTemplate");
|
||||
const moment = require("moment");
|
||||
const moment = require("moment-timezone");
|
||||
const { taskEmailQueue } = require("./tasksEmailsQueue");
|
||||
|
||||
const ses = new aws.SES({
|
||||
@@ -108,12 +108,13 @@ const getEndpoints = (bodyshop) =>
|
||||
: "https://romeonline.io"
|
||||
});
|
||||
|
||||
const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId) => {
|
||||
const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId, dateLine) => {
|
||||
const endPoints = getEndpoints(bodyshop);
|
||||
return {
|
||||
header: title,
|
||||
subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatPriority(priority)} ${formatDate(dueDate)}`,
|
||||
body: `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()}<br>${description ? description.concat("<br>") : ""}<a href="${endPoints}/manage/tasks/alltasks?taskid=${taskId}">View this task.</a>`
|
||||
body: `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()}<br>${description ? description.concat("<br>") : ""}<a href="${endPoints}/manage/tasks/alltasks?taskid=${taskId}">View this task.</a>`,
|
||||
dateLine
|
||||
};
|
||||
};
|
||||
|
||||
@@ -178,6 +179,8 @@ const taskAssignedEmail = async (req, res) => {
|
||||
id: newTask.id
|
||||
});
|
||||
|
||||
const dateLine = moment().tz(tasks_by_pk.bodyshop.timezone).format("M/DD/YYYY @ hh:mm a");
|
||||
|
||||
sendMail(
|
||||
"assigned",
|
||||
tasks_by_pk.assigned_to_employee.user_email,
|
||||
@@ -190,7 +193,8 @@ const taskAssignedEmail = async (req, res) => {
|
||||
newTask.due_date,
|
||||
tasks_by_pk.bodyshop,
|
||||
tasks_by_pk.job,
|
||||
newTask.id
|
||||
newTask.id,
|
||||
dateLine
|
||||
)
|
||||
),
|
||||
null,
|
||||
@@ -247,7 +251,7 @@ const tasksRemindEmail = async (req, res) => {
|
||||
const fromEmails = InstanceManager({
|
||||
imex: "ImEX Online <noreply@imex.online>",
|
||||
rome:
|
||||
tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager"
|
||||
tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager"
|
||||
? "ProManager <noreply@promanager.web-est.com>"
|
||||
: "Rome Online <noreply@romeonline.io>"
|
||||
});
|
||||
@@ -259,6 +263,8 @@ const tasksRemindEmail = async (req, res) => {
|
||||
|
||||
const taskIds = groupedTasks[recipient.email].map((task) => task.id);
|
||||
|
||||
const dateLine = moment().tz(tasksRequest?.tasks[0].bodyshop.timezone).format("M/DD/YYYY @ hh:mm a");
|
||||
|
||||
// There is only the one email to send to this author.
|
||||
if (recipient.count === 1) {
|
||||
const onlyTask = groupedTasks[recipient.email][0];
|
||||
@@ -274,7 +280,8 @@ const tasksRemindEmail = async (req, res) => {
|
||||
onlyTask.due_date,
|
||||
onlyTask.bodyshop,
|
||||
onlyTask.job,
|
||||
onlyTask.id
|
||||
onlyTask.id,
|
||||
dateLine
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -283,7 +290,7 @@ const tasksRemindEmail = async (req, res) => {
|
||||
const endPoints = InstanceManager({
|
||||
imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online",
|
||||
rome:
|
||||
tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager"
|
||||
tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager"
|
||||
? process.env?.NODE_ENV === "test"
|
||||
? "https//test.promanager.web-est.com"
|
||||
: "https://promanager.web-est.com"
|
||||
@@ -297,6 +304,7 @@ const tasksRemindEmail = async (req, res) => {
|
||||
emailData.html = generateEmailTemplate({
|
||||
header: `${allTasks.length} Tasks require your attention`,
|
||||
subHeader: `Please click on the Tasks below to view the Task.`,
|
||||
dateLine,
|
||||
body: `<ul>
|
||||
${allTasks
|
||||
.map((task) =>
|
||||
|
||||
@@ -2489,6 +2489,7 @@ exports.QUERY_REMIND_TASKS = `
|
||||
bodyshop {
|
||||
shopname
|
||||
convenient_company
|
||||
timezone
|
||||
}
|
||||
bodyshopid
|
||||
}
|
||||
@@ -2512,6 +2513,7 @@ query QUERY_TASK_BY_ID($id: uuid!) {
|
||||
bodyshop{
|
||||
shopname
|
||||
convenient_company
|
||||
timezone
|
||||
}
|
||||
job{
|
||||
ro_number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const applyIOHelpers = (app, api, io, logger) => {
|
||||
const getBodyshopRoom = (bodyshopID) => `bodyshop-broadcast-room:${bodyshopID}`;
|
||||
const getBodyshopRoom = (bodyshopID) => `broadcast-room-${bodyshopID}`;
|
||||
|
||||
const ioHelpersAPI = {
|
||||
getBodyshopRoom
|
||||
|
||||
@@ -1,71 +1,48 @@
|
||||
const logger = require("./logger");
|
||||
/**
|
||||
* Apply Redis helper functions
|
||||
* @param pubClient
|
||||
* @param app
|
||||
*/
|
||||
const applyRedisHelpers = (pubClient, app, logger) => {
|
||||
const applyRedisHelpers = (pubClient, app) => {
|
||||
// Store session data in Redis
|
||||
const setSessionData = async (socketId, key, value) => {
|
||||
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");
|
||||
}
|
||||
await pubClient.hSet(`socket:${socketId}`, key, JSON.stringify(value)); // Use Redis pubClient
|
||||
};
|
||||
|
||||
// Retrieve session data from Redis
|
||||
const getSessionData = async (socketId, key) => {
|
||||
try {
|
||||
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");
|
||||
}
|
||||
const data = await pubClient.hGet(`socket:${socketId}`, key);
|
||||
return data ? JSON.parse(data) : null;
|
||||
};
|
||||
|
||||
// Clear session data from Redis
|
||||
const clearSessionData = async (socketId) => {
|
||||
try {
|
||||
await pubClient.del(`socket:${socketId}`);
|
||||
} catch (error) {
|
||||
logger.log(`Error Clearing Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||
}
|
||||
await pubClient.del(`socket:${socketId}`);
|
||||
};
|
||||
|
||||
// Store multiple session data in Redis
|
||||
const setMultipleSessionData = async (socketId, keyValues) => {
|
||||
try {
|
||||
// keyValues is expected to be an object { key1: value1, key2: value2, ... }
|
||||
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");
|
||||
}
|
||||
// keyValues is expected to be an object { key1: value1, key2: value2, ... }
|
||||
const entries = Object.entries(keyValues).map(([key, value]) => [key, JSON.stringify(value)]);
|
||||
await pubClient.hSet(`socket:${socketId}`, ...entries.flat());
|
||||
};
|
||||
|
||||
// Retrieve multiple session data from Redis
|
||||
const getMultipleSessionData = async (socketId, keys) => {
|
||||
try {
|
||||
const data = await pubClient.hmGet(`socket:${socketId}`, keys);
|
||||
// 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 data = await pubClient.hmGet(`socket:${socketId}`, keys);
|
||||
// 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]));
|
||||
};
|
||||
|
||||
const setMultipleFromArraySessionData = async (socketId, keyValueArray) => {
|
||||
try {
|
||||
// Use Redis multi/pipeline to batch the commands
|
||||
const multi = pubClient.multi();
|
||||
keyValueArray.forEach(([key, value]) => {
|
||||
multi.hSet(`socket:${socketId}`, key, JSON.stringify(value));
|
||||
});
|
||||
await multi.exec(); // Execute all queued commands
|
||||
} catch (error) {
|
||||
logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||
}
|
||||
// Use Redis multi/pipeline to batch the commands
|
||||
const multi = pubClient.multi();
|
||||
|
||||
keyValueArray.forEach(([key, value]) => {
|
||||
multi.hSet(`socket:${socketId}`, key, JSON.stringify(value));
|
||||
});
|
||||
|
||||
await multi.exec(); // Execute all queued commands
|
||||
};
|
||||
|
||||
// Helper function to add an item to the end of the Redis list
|
||||
@@ -73,7 +50,7 @@ const applyRedisHelpers = (pubClient, app, logger) => {
|
||||
try {
|
||||
await pubClient.rPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
||||
} catch (error) {
|
||||
logger.log(`Error adding item to the end of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||
console.error(`Error adding item to the end of the list for socket ${socketId}:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -82,7 +59,7 @@ const applyRedisHelpers = (pubClient, app, logger) => {
|
||||
try {
|
||||
await pubClient.lPush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
|
||||
} catch (error) {
|
||||
logger.log(`Error adding item to the beginning of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||
console.error(`Error adding item to the beginning of the list for socket ${socketId}:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,33 +68,33 @@ const applyRedisHelpers = (pubClient, app, logger) => {
|
||||
try {
|
||||
await pubClient.del(`socket:${socketId}:${key}`);
|
||||
} catch (error) {
|
||||
logger.log(`Error clearing list for socket ${socketId}: ${error}`, "ERROR", "redis");
|
||||
console.error(`Error clearing list for socket ${socketId}:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
// Add methods to manage room users
|
||||
const addUserToRoom = async (room, user) => {
|
||||
const addUserToRoom = async (bodyshopUUID, user) => {
|
||||
try {
|
||||
await pubClient.sAdd(room, JSON.stringify(user));
|
||||
} catch (error) {
|
||||
logger.log(`Error adding user to room ${room}: ${error}`, "ERROR", "redis");
|
||||
await pubClient.sAdd(`bodyshopRoom:${bodyshopUUID}`, JSON.stringify(user));
|
||||
} catch (err) {
|
||||
console.error(`Error adding user to room: ${bodyshopUUID}`);
|
||||
}
|
||||
};
|
||||
|
||||
const removeUserFromRoom = async (room, user) => {
|
||||
const removeUserFromRoom = async (bodyshopUUID, user) => {
|
||||
try {
|
||||
await pubClient.sRem(room, JSON.stringify(user));
|
||||
} catch (error) {
|
||||
logger.log(`Error removing user to room ${room}: ${error}`, "ERROR", "redis");
|
||||
await pubClient.sRem(`bodyshopRoom:${bodyshopUUID}`, JSON.stringify(user));
|
||||
} catch (err) {
|
||||
console.error(`Error remove user from room: ${bodyshopUUID}`);
|
||||
}
|
||||
};
|
||||
|
||||
const getUsersInRoom = async (room) => {
|
||||
const getUsersInRoom = async (bodyshopUUID) => {
|
||||
try {
|
||||
const users = await pubClient.sMembers(room);
|
||||
const users = await pubClient.sMembers(`bodyshopRoom:${bodyshopUUID}`);
|
||||
return users.map((user) => JSON.parse(user));
|
||||
} catch (error) {
|
||||
logger.log(`Error getting users in room ${room}: ${error}`, "ERROR", "redis");
|
||||
} catch (err) {
|
||||
console.error(`Error getUsersInRoom: ${bodyshopUUID}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -30,67 +30,52 @@ const redisSocketEvents = (io, { addUserToRoom, getUsersInRoom, removeUserFromRo
|
||||
// Room management and broadcasting events
|
||||
function registerRoomAndBroadcastEvents(socket) {
|
||||
socket.on("join-bodyshop-room", async (bodyshopUUID) => {
|
||||
try {
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
socket.join(room);
|
||||
await addUserToRoom(room, { uid: socket.user.uid, email: socket.user.email, socket: socket.id });
|
||||
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${room}`);
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
socket.join(room);
|
||||
await addUserToRoom(room, { uid: socket.user.uid, email: socket.user.email });
|
||||
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
|
||||
|
||||
// Notify all users in the room about the updated user list
|
||||
const usersInRoom = await getUsersInRoom(room);
|
||||
io.to(room).emit("room-users-updated", usersInRoom);
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error joining room: ${error}`);
|
||||
}
|
||||
// Notify all users in the room about the updated user list
|
||||
const usersInRoom = await getUsersInRoom(bodyshopUUID);
|
||||
io.to(room).emit("room-users-updated", usersInRoom);
|
||||
});
|
||||
|
||||
socket.on("leave-bodyshop-room", async (bodyshopUUID) => {
|
||||
try {
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
socket.leave(room);
|
||||
createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${room}`);
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error joining room: ${error}`);
|
||||
}
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
socket.leave(room);
|
||||
createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${room}`);
|
||||
});
|
||||
|
||||
socket.on("get-room-users", async (bodyshopUUID, callback) => {
|
||||
try {
|
||||
const usersInRoom = await getUsersInRoom(getBodyshopRoom(bodyshopUUID));
|
||||
callback(usersInRoom);
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error getting room: ${error}`);
|
||||
}
|
||||
const usersInRoom = await getUsersInRoom(getBodyshopRoom(bodyshopUUID));
|
||||
callback(usersInRoom);
|
||||
});
|
||||
|
||||
socket.on("broadcast-to-bodyshop", async (bodyshopUUID, message) => {
|
||||
try {
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
io.to(room).emit("bodyshop-message", message);
|
||||
createLogEvent(socket, "INFO", `Broadcast message to bodyshop ${room}`);
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error getting room: ${error}`);
|
||||
}
|
||||
const room = getBodyshopRoom(bodyshopUUID);
|
||||
io.to(room).emit("bodyshop-message", message);
|
||||
createLogEvent(socket, "INFO", `Broadcast message to bodyshop ${room}`);
|
||||
});
|
||||
|
||||
socket.on("disconnect", async () => {
|
||||
try {
|
||||
createLogEvent(socket, "DEBUG", `User disconnected.`);
|
||||
createLogEvent(socket, "DEBUG", `User disconnected.`);
|
||||
|
||||
// Get all rooms the socket is part of
|
||||
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
||||
for (const room of rooms) {
|
||||
await removeUserFromRoom(room, { uid: socket.user.uid, email: socket.user.email, socket: socket.id });
|
||||
}
|
||||
} catch (error) {
|
||||
createLogEvent(socket, "ERROR", `Error getting room: ${error}`);
|
||||
// Get all rooms the socket is part of
|
||||
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
|
||||
|
||||
for (const bodyshopRoom of rooms) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Register all socket events for a given socket connection
|
||||
function registerSocketEvents(socket) {
|
||||
createLogEvent(socket, "DEBUG", `Registering RedisIO Socket Events.`);
|
||||
createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);
|
||||
|
||||
// Register room and broadcasting events
|
||||
registerRoomAndBroadcastEvents(socket);
|
||||
|
||||
Reference in New Issue
Block a user