@@ -17,6 +17,7 @@ enum RequestType {
17
17
REMOTE_LEAVE = 3 ,
18
18
REMOTE_DISCONNECT = 4 ,
19
19
REMOTE_FETCH = 5 ,
20
+ SERVER_SIDE_EMIT = 6 ,
20
21
}
21
22
22
23
interface Request {
@@ -300,6 +301,37 @@ export class RedisAdapter extends Adapter {
300
301
this . pubClient . publish ( this . responseChannel , response ) ;
301
302
break ;
302
303
304
+ case RequestType . SERVER_SIDE_EMIT :
305
+ if ( request . uid === this . uid ) {
306
+ debug ( "ignore same uid" ) ;
307
+ return ;
308
+ }
309
+ const withAck = request . requestId !== undefined ;
310
+ if ( ! withAck ) {
311
+ this . nsp . _onServerSideEmit ( request . data ) ;
312
+ return ;
313
+ }
314
+ let called = false ;
315
+ const callback = ( arg ) => {
316
+ // only one argument is expected
317
+ if ( called ) {
318
+ return ;
319
+ }
320
+ called = true ;
321
+ debug ( "calling acknowledgement with %j" , arg ) ;
322
+ this . pubClient . publish (
323
+ this . responseChannel ,
324
+ JSON . stringify ( {
325
+ type : RequestType . SERVER_SIDE_EMIT ,
326
+ requestId : request . requestId ,
327
+ data : arg ,
328
+ } )
329
+ ) ;
330
+ } ;
331
+ request . data . push ( callback ) ;
332
+ this . nsp . _onServerSideEmit ( request . data ) ;
333
+ break ;
334
+
303
335
default :
304
336
debug ( "ignoring unknown request type: %s" , request . type ) ;
305
337
}
@@ -381,6 +413,23 @@ export class RedisAdapter extends Adapter {
381
413
this . requests . delete ( requestId ) ;
382
414
break ;
383
415
416
+ case RequestType . SERVER_SIDE_EMIT :
417
+ request . responses . push ( response . data ) ;
418
+
419
+ debug (
420
+ "serverSideEmit: got %d responses out of %d" ,
421
+ request . responses . length ,
422
+ request . numSub
423
+ ) ;
424
+ if ( request . responses . length === request . numSub ) {
425
+ clearTimeout ( request . timeout ) ;
426
+ if ( request . resolve ) {
427
+ request . resolve ( null , request . responses ) ;
428
+ }
429
+ this . requests . delete ( requestId ) ;
430
+ }
431
+ break ;
432
+
384
433
default :
385
434
debug ( "ignoring unknown request type: %s" , request . type ) ;
386
435
}
@@ -733,6 +782,67 @@ export class RedisAdapter extends Adapter {
733
782
this . pubClient . publish ( this . requestChannel , request ) ;
734
783
}
735
784
785
+ public serverSideEmit ( packet : any [ ] ) : void {
786
+ const withAck = typeof packet [ packet . length - 1 ] === "function" ;
787
+
788
+ if ( withAck ) {
789
+ this . serverSideEmitWithAck ( packet ) . catch ( ( ) => {
790
+ // ignore errors
791
+ } ) ;
792
+ return ;
793
+ }
794
+
795
+ const request = JSON . stringify ( {
796
+ uid : this . uid ,
797
+ type : RequestType . SERVER_SIDE_EMIT ,
798
+ data : packet ,
799
+ } ) ;
800
+
801
+ this . pubClient . publish ( this . requestChannel , request ) ;
802
+ }
803
+
804
+ private async serverSideEmitWithAck ( packet : any [ ] ) {
805
+ const ack = packet . pop ( ) ;
806
+ const numSub = ( await this . getNumSub ( ) ) - 1 ; // ignore self
807
+
808
+ debug ( 'waiting for %d responses to "serverSideEmit" request' , numSub ) ;
809
+
810
+ if ( numSub <= 0 ) {
811
+ return ack ( null , [ ] ) ;
812
+ }
813
+
814
+ const requestId = uid2 ( 6 ) ;
815
+ const request = JSON . stringify ( {
816
+ uid : this . uid ,
817
+ requestId, // the presence of this attribute defines whether an acknowledgement is needed
818
+ type : RequestType . SERVER_SIDE_EMIT ,
819
+ data : packet ,
820
+ } ) ;
821
+
822
+ const timeout = setTimeout ( ( ) => {
823
+ const storedRequest = this . requests . get ( requestId ) ;
824
+ if ( storedRequest ) {
825
+ ack (
826
+ new Error (
827
+ `timeout reached: only ${ storedRequest . responses . length } responses received out of ${ storedRequest . numSub } `
828
+ ) ,
829
+ storedRequest . responses
830
+ ) ;
831
+ this . requests . delete ( requestId ) ;
832
+ }
833
+ } , this . requestsTimeout ) ;
834
+
835
+ this . requests . set ( requestId , {
836
+ type : RequestType . SERVER_SIDE_EMIT ,
837
+ numSub,
838
+ timeout,
839
+ resolve : ack ,
840
+ responses : [ ] ,
841
+ } ) ;
842
+
843
+ this . pubClient . publish ( this . requestChannel , request ) ;
844
+ }
845
+
736
846
/**
737
847
* Get the number of subscribers of the request channel
738
848
*
0 commit comments