@@ -4,14 +4,67 @@ const Logger = require("./utils/logger"); // Import the logger
4
4
const PORT = process . env . PORT || 3000 ;
5
5
const io = new Server ( Number ( PORT ) , { cors : { origin : "*" } } ) ;
6
6
7
- const services = new Map ( ) ; // Stores connected services
7
+ const services = new Map ( ) ; // Stores connected services (serviceName -> { socketId, lastHeartbeat })
8
8
const pendingRequests = new Map ( ) ; // Stores pending requests (requestId -> senderSocketId)
9
9
10
10
const logger = new Logger ( process . env . LOG_LEVEL || "debug" ) ; // Initialize logger
11
11
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
+
12
55
// Handle new connections
13
56
io . on ( "connection" , ( socket ) => {
14
57
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
+
15
68
logger . info ( `${ serviceName } connected: ${ socket . id } ` ) ;
16
69
17
70
// Register the service
@@ -37,7 +90,6 @@ io.on("connection", (socket) => {
37
90
// Notify the sender that the target service was not found
38
91
logger . warn ( `Service "${ targetService } " not found` ) ;
39
92
40
- // socket.emit("response", { id: payload.id, error: `Service "${targetService}" not found` });
41
93
socket . emit ( "response" , {
42
94
id : payload . id ,
43
95
// 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) => {
73
125
74
126
// Handle disconnections
75
127
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
+ }
78
133
} ) ;
79
134
} ) ;
80
135
@@ -84,7 +139,14 @@ setInterval(() => {
84
139
for ( const [ serviceName , data ] of services ) {
85
140
if ( now - data . lastHeartbeat > 15000 ) {
86
141
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
+ ) ;
88
150
}
89
151
}
90
152
} , 5000 ) ;
0 commit comments