@@ -4,14 +4,67 @@ const Logger = require("./utils/logger"); // Import the logger
44const PORT = process . env . PORT || 3000 ;
55const io = new Server ( Number ( PORT ) , { cors : { origin : "*" } } ) ;
66
7- const services = new Map ( ) ; // Stores connected services
7+ const services = new Map ( ) ; // Stores connected services (serviceName -> { socketId, lastHeartbeat })
88const pendingRequests = new Map ( ) ; // Stores pending requests (requestId -> senderSocketId)
99
1010const logger = new Logger ( process . env . LOG_LEVEL || "debug" ) ; // Initialize logger
1111
12+ /*
13+ Socket.io Middleware Setup
14+
15+ Socket.io Middleware to handle Duplicate Client Service Registration.
16+
17+ This middleware will check if a service is already registered with the same name.
18+ If so, it will reject the new connection request, log a warning and pass an error to the client.
19+ Error Structure: {
20+ code: "DUPLICATE_SERVICE_REGISTRATION",
21+ content: "Duplicate Service Registration Name! A service with the same name is already registered."
22+ }
23+
24+ Otherwise, it will proceed with the connection.
25+
26+ This is to prevent multiple instances of the same service from connecting to the hub.
27+ The hub will only keep the one connection for each service.
28+ */
29+ io . use ( ( socket , next ) => {
30+ const serviceName = socket . handshake . query . serviceName ;
31+
32+ // If the service is already registered, reject the connection and pass an error to the client
33+ if ( services . has ( serviceName ) ) {
34+ logger . warn (
35+ `Duplicate service registration attempt: ${ serviceName } from Socket ID: ${ socket . id } `
36+ ) ;
37+
38+ const error = new Error ( "DUPLICATE_SERVICE_REGISTRATION" ) ;
39+ error . data = {
40+ code : "DUPLICATE_SERVICE_REGISTRATION" ,
41+ content :
42+ "Duplicate Service Registration Name! A service with the same name is already registered." ,
43+ } ;
44+
45+ // Set a flag to indicate that the connection was rejected
46+ socket . rejected = true ;
47+
48+ next ( error ) ;
49+ }
50+
51+ // If the service is not registered, proceed with the connection
52+ next ( ) ;
53+ } ) ;
54+
1255// Handle new connections
1356io . on ( "connection" , ( socket ) => {
1457 const serviceName = socket . handshake . query . serviceName ;
58+
59+ // If the connection was rejected by the middleware, close the connection
60+ if ( socket . rejected ) {
61+ logger . warn (
62+ `Connection rejected for duplicate service registration: ${ serviceName } from Socket ID: ${ socket . id } `
63+ ) ;
64+ socket . disconnect ( true ) ;
65+ return ;
66+ }
67+
1568 logger . info ( `${ serviceName } connected: ${ socket . id } ` ) ;
1669
1770 // Register the service
@@ -37,7 +90,6 @@ io.on("connection", (socket) => {
3790 // Notify the sender that the target service was not found
3891 logger . warn ( `Service "${ targetService } " not found` ) ;
3992
40- // socket.emit("response", { id: payload.id, error: `Service "${targetService}" not found` });
4193 socket . emit ( "response" , {
4294 id : payload . id ,
4395 // error: `Service "${targetService}" not found`, // This was causing a crash in the client response handler because it was expecting a "data" key
@@ -73,8 +125,11 @@ io.on("connection", (socket) => {
73125
74126 // Handle disconnections
75127 socket . on ( "disconnect" , ( ) => {
76- services . delete ( serviceName ) ;
77- logger . info ( `${ serviceName } disconnected: ${ socket . id } ` ) ;
128+ // Only remove the service if the connection was not rejected
129+ if ( ! socket . rejected ) {
130+ services . delete ( serviceName ) ;
131+ logger . info ( `${ serviceName } disconnected: ${ socket . id } ` ) ;
132+ }
78133 } ) ;
79134} ) ;
80135
@@ -84,7 +139,14 @@ setInterval(() => {
84139 for ( const [ serviceName , data ] of services ) {
85140 if ( now - data . lastHeartbeat > 15000 ) {
86141 services . delete ( serviceName ) ;
87- logger . info ( `Removed inactive service: ${ serviceName } ` ) ;
142+
143+ // Disconnect the inactive service socket
144+ const inactiveServiceSocket = io . sockets . sockets . get ( data . socketId ) ; // Disconnect the socket
145+ inactiveServiceSocket . disconnect ( true ) ;
146+
147+ logger . info (
148+ `Removed inactive service: ${ serviceName } with Socket ID: ${ inactiveServiceSocket . id } `
149+ ) ;
88150 }
89151 }
90152} , 5000 ) ;
0 commit comments