@@ -18,10 +18,10 @@ import {
18
18
MATCH_CONFIRMED ,
19
19
MATCH_TIMEOUT ,
20
20
MATCH_REQUESTED ,
21
- MATCH_ERROR ,
22
21
EXCEPTION ,
23
22
} from './match.event' ;
24
- import { CANCEL_MATCH , FIND_MATCH } from './match.message' ;
23
+ import { CANCEL_MATCH , CONFIRM_MATCH , FIND_MATCH } from './match.message' ;
24
+ import { v4 as uuidv4 } from 'uuid' ;
25
25
26
26
@WebSocketGateway ( {
27
27
namespace : '/match' ,
@@ -35,6 +35,15 @@ import { CANCEL_MATCH, FIND_MATCH } from './match.message';
35
35
export class MatchGateway implements OnGatewayInit {
36
36
@WebSocketServer ( ) server : Server ;
37
37
private userSockets : Map < string , string > = new Map ( ) ;
38
+ private matchConfirmations : Map <
39
+ string ,
40
+ {
41
+ user1 : string ;
42
+ user2 : string ;
43
+ user1Confirmed : boolean ;
44
+ user2Confirmed : boolean ;
45
+ }
46
+ > = new Map ( ) ;
38
47
39
48
constructor (
40
49
@Inject ( 'MATCHING_SERVICE' ) private matchingClient : ClientProxy ,
@@ -45,7 +54,9 @@ export class MatchGateway implements OnGatewayInit {
45
54
afterInit ( ) {
46
55
// Subscribe to Redis Pub/Sub for match notifications
47
56
this . redisService . subscribeToMatchEvents ( ( matchedUsers ) => {
48
- this . notifyUsersWithMatch ( matchedUsers ) ;
57
+ const matchId = this . generateMatchId ( ) ; // Generate matchId
58
+ this . notifyUsersMatchFound ( matchId , matchedUsers ) ; // Notify users of match with matchId
59
+ this . trackMatchConfirmation ( matchId , matchedUsers ) ; // Track match confirmation
49
60
} ) ;
50
61
51
62
this . redisService . subscribeToTimeoutEvents ( ( timedOutUsers ) => {
@@ -63,7 +74,7 @@ export class MatchGateway implements OnGatewayInit {
63
74
! payload . selectedTopic ||
64
75
! payload . selectedDifficulty
65
76
) {
66
- client . emit ( EXCEPTION , 'Invalid match request payload .' ) ;
77
+ client . emit ( EXCEPTION , 'Invalid payload for match request.' ) ;
67
78
return ;
68
79
}
69
80
@@ -95,10 +106,7 @@ export class MatchGateway implements OnGatewayInit {
95
106
@MessageBody ( ) payload : { userId : string } ,
96
107
) {
97
108
if ( ! payload . userId ) {
98
- client . emit (
99
- EXCEPTION ,
100
- 'Invalid userId. Please check your payload and try again.' ,
101
- ) ;
109
+ client . emit ( EXCEPTION , 'Invalid userId.' ) ;
102
110
return ;
103
111
}
104
112
@@ -125,36 +133,45 @@ export class MatchGateway implements OnGatewayInit {
125
133
}
126
134
}
127
135
128
- // Notify both matched users via WebSocket
129
- notifyUsersWithMatch ( matchedUsers : string [ ] ) {
130
- const [ user1 , user2 ] = matchedUsers ;
131
- const user1SocketId = this . getUserSocketId ( user1 ) ;
132
- const user2SocketId = this . getUserSocketId ( user2 ) ;
133
- if ( user1SocketId && user2SocketId ) {
134
- this . server . to ( user1SocketId ) . emit ( MATCH_FOUND , {
135
- message : `You have been matched with user ${ user2 } ` ,
136
- matchedUserId : user2 ,
137
- } ) ;
138
- this . server . to ( user2SocketId ) . emit ( MATCH_FOUND , {
139
- message : `You have been matched with user ${ user1 } ` ,
140
- matchedUserId : user1 ,
141
- } ) ;
136
+ @SubscribeMessage ( CONFIRM_MATCH )
137
+ async handleConfirmMatch (
138
+ @ConnectedSocket ( ) client : Socket ,
139
+ @MessageBody ( ) payload : { userId : string ; matchId : string } ,
140
+ ) {
141
+ if ( ! payload . userId || ! payload . matchId ) {
142
+ client . emit ( EXCEPTION , 'Invalid message payload for match confirmation.' ) ;
143
+ return ;
142
144
}
143
- }
144
145
145
- notifyUsersWithTimeout ( timedOutUsers : string [ ] ) {
146
- timedOutUsers . forEach ( ( user ) => {
147
- const socketId = this . getUserSocketId ( user ) ;
148
- if ( socketId ) {
149
- this . server . to ( socketId ) . emit ( MATCH_TIMEOUT , {
150
- message : `You have been timed out.` ,
151
- timedOutUserId : user ,
152
- } ) ;
153
- }
154
- } ) ;
146
+ const { userId, matchId } = payload ;
147
+ if ( ! this . validateUserId ( client , userId ) ) {
148
+ return ;
149
+ }
150
+
151
+ // Get the confirmation state of the users
152
+ const confirmationState = this . matchConfirmations . get ( matchId ) ;
153
+ if ( ! confirmationState ) {
154
+ client . emit ( EXCEPTION , 'Invalid Match Id.' ) ;
155
+ return ;
156
+ }
157
+
158
+ // Checks which user is confirming the match
159
+ if ( confirmationState . user1 === payload . userId ) {
160
+ confirmationState . user1Confirmed = true ;
161
+ } else if ( confirmationState . user2 === payload . userId ) {
162
+ confirmationState . user2Confirmed = true ;
163
+ } else {
164
+ client . emit ( EXCEPTION , 'Invalid userId for this match.' ) ;
165
+ return ;
166
+ }
167
+
168
+ // Check if both users have confirmed
169
+ if ( confirmationState . user1Confirmed && confirmationState . user2Confirmed ) {
170
+ this . notifyUsersMatchConfirmed ( payload . matchId , confirmationState ) ;
171
+ }
155
172
}
156
173
157
- async handleConnection ( @ConnectedSocket ( ) client : Socket ) {
174
+ async handleConnect ( @ConnectedSocket ( ) client : Socket ) {
158
175
const id = client . handshake . query . userId as string ;
159
176
160
177
if ( ! id ) {
@@ -183,10 +200,8 @@ export class MatchGateway implements OnGatewayInit {
183
200
return ;
184
201
}
185
202
186
- if ( id ) {
187
- this . userSockets . set ( id as string , client . id ) ;
188
- console . log ( `User ${ id } connected with socket ID ${ client . id } ` ) ;
189
- }
203
+ this . userSockets . set ( id as string , client . id ) ;
204
+ console . log ( `User ${ id } connected with socket ID ${ client . id } ` ) ;
190
205
} catch ( error ) {
191
206
this . emitExceptionAndDisconnect ( client , error . message ) ;
192
207
return ;
@@ -230,6 +245,73 @@ export class MatchGateway implements OnGatewayInit {
230
245
}
231
246
}
232
247
248
+ trackMatchConfirmation ( matchId : string , matchedUsers : string [ ] ) {
249
+ const confirmationState = {
250
+ user1 : matchedUsers [ 0 ] ,
251
+ user2 : matchedUsers [ 1 ] ,
252
+ user1Confirmed : false ,
253
+ user2Confirmed : false ,
254
+ } ;
255
+
256
+ this . matchConfirmations . set ( matchId , confirmationState ) ;
257
+ }
258
+
259
+ notifyUsersMatchFound ( matchId : string , matchedUsers : string [ ] ) {
260
+ const [ user1 , user2 ] = matchedUsers ;
261
+ const user1SocketId = this . getUserSocketId ( user1 ) ;
262
+ const user2SocketId = this . getUserSocketId ( user2 ) ;
263
+ if ( user1SocketId && user2SocketId ) {
264
+ this . server . to ( user1SocketId ) . emit ( MATCH_FOUND , {
265
+ message : `You have been matched with user ${ user2 } ` ,
266
+ matchId,
267
+ } ) ;
268
+ this . server . to ( user2SocketId ) . emit ( MATCH_FOUND , {
269
+ message : `You have been matched with user ${ user1 } ` ,
270
+ matchId,
271
+ } ) ;
272
+ }
273
+ }
274
+
275
+ notifyUsersWithTimeout ( timedOutUsers : string [ ] ) {
276
+ timedOutUsers . forEach ( ( user ) => {
277
+ const socketId = this . getUserSocketId ( user ) ;
278
+ if ( socketId ) {
279
+ this . server . to ( socketId ) . emit ( MATCH_TIMEOUT , {
280
+ message : `You have been timed out.` ,
281
+ timedOutUserId : user ,
282
+ } ) ;
283
+ }
284
+ } ) ;
285
+ }
286
+
287
+ notifyUsersMatchConfirmed ( matchId : string , confirmationState : any ) {
288
+ const user1SocketId = this . getUserSocketId ( confirmationState . user1 ) ;
289
+ const user2SocketId = this . getUserSocketId ( confirmationState . user2 ) ;
290
+
291
+ const sessionId = this . generateSessionId ( ) ; // TODO - To be substituted with collab-service method in next MS
292
+
293
+ if ( user1SocketId && user2SocketId ) {
294
+ this . server . to ( user1SocketId ) . emit ( MATCH_CONFIRMED , {
295
+ message : 'Both users have confirmed the match.' ,
296
+ sessionId,
297
+ } ) ;
298
+ this . server . to ( user2SocketId ) . emit ( MATCH_CONFIRMED , {
299
+ message : 'Both users have confirmed the match.' ,
300
+ sessionId,
301
+ } ) ;
302
+ }
303
+
304
+ this . matchConfirmations . delete ( matchId ) ;
305
+ }
306
+
307
+ private generateMatchId ( ) : string {
308
+ return uuidv4 ( ) ;
309
+ }
310
+
311
+ private generateSessionId ( ) : string {
312
+ return uuidv4 ( ) ;
313
+ }
314
+
233
315
private getUserSocketId ( userId : string ) : string | undefined {
234
316
return this . userSockets . get ( userId ) ;
235
317
}
0 commit comments