@@ -34,13 +34,17 @@ export interface ShardedRedisAdapterOptions {
3434 * The default value, useful when some rooms have a low number of clients (so only a few Socket.IO servers are notified).
3535 *
3636 * Only public rooms (i.e. not related to a particular Socket ID) are taken in account, because:
37- *
3837 * - a lot of connected clients would mean a lot of subscription/unsubscription
3938 * - the Socket ID attribute is ephemeral
4039 *
40+ * - "dynamic-private"
41+ *
42+ * Like "dynamic" but creates separate channels for private rooms as well. Useful when there is lots of 1:1 communication
43+ * via socket.emit() calls.
44+ *
4145 * @default "dynamic"
4246 */
43- subscriptionMode ?: "static" | "dynamic" ;
47+ subscriptionMode ?: "static" | "dynamic" | "dynamic-private" ;
4448}
4549
4650/**
@@ -89,17 +93,18 @@ class ShardedRedisAdapter extends ClusterAdapter {
8993 SSUBSCRIBE ( this . subClient , this . channel , handler ) ;
9094 SSUBSCRIBE ( this . subClient , this . responseChannel , handler ) ;
9195
92- if ( this . opts . subscriptionMode === "dynamic" ) {
96+ if (
97+ this . opts . subscriptionMode === "dynamic" ||
98+ this . opts . subscriptionMode === "dynamic-private"
99+ ) {
93100 this . on ( "create-room" , ( room ) => {
94- const isPublicRoom = ! this . sids . has ( room ) ;
95- if ( isPublicRoom ) {
101+ if ( this . shouldUseASeparateNamespace ( room ) ) {
96102 SSUBSCRIBE ( this . subClient , this . dynamicChannel ( room ) , handler ) ;
97103 }
98104 } ) ;
99105
100106 this . on ( "delete-room" , ( room ) => {
101- const isPublicRoom = ! this . sids . has ( room ) ;
102- if ( isPublicRoom ) {
107+ if ( this . shouldUseASeparateNamespace ( room ) ) {
103108 SUNSUBSCRIBE ( this . subClient , this . dynamicChannel ( room ) ) ;
104109 }
105110 } ) ;
@@ -109,10 +114,12 @@ class ShardedRedisAdapter extends ClusterAdapter {
109114 override close ( ) : Promise < void > | void {
110115 const channels = [ this . channel , this . responseChannel ] ;
111116
112- if ( this . opts . subscriptionMode === "dynamic" ) {
117+ if (
118+ this . opts . subscriptionMode === "dynamic" ||
119+ this . opts . subscriptionMode === "dynamic-private"
120+ ) {
113121 this . rooms . forEach ( ( _sids , room ) => {
114- const isPublicRoom = ! this . sids . has ( room ) ;
115- if ( isPublicRoom ) {
122+ if ( this . shouldUseASeparateNamespace ( room ) ) {
116123 channels . push ( this . dynamicChannel ( room ) ) ;
117124 }
118125 } ) ;
@@ -136,11 +143,13 @@ class ShardedRedisAdapter extends ClusterAdapter {
136143 // broadcast with ack can not use a dynamic channel, because the serverCount() method return the number of all
137144 // servers, not only the ones where the given room exists
138145 const useDynamicChannel =
139- this . opts . subscriptionMode === "dynamic" &&
140146 message . type === MessageType . BROADCAST &&
141147 message . data . requestId === undefined &&
142148 message . data . opts . rooms . length === 1 &&
143- ! looksLikeASocketId ( message . data . opts . rooms [ 0 ] ) ;
149+ ( ( this . opts . subscriptionMode === "dynamic" &&
150+ ! looksLikeASocketId ( message . data . opts . rooms [ 0 ] ) ) ||
151+ this . opts . subscriptionMode === "dynamic-private" ) ;
152+
144153 if ( useDynamicChannel ) {
145154 return this . dynamicChannel ( message . data . opts . rooms [ 0 ] ) ;
146155 } else {
@@ -204,4 +213,13 @@ class ShardedRedisAdapter extends ClusterAdapter {
204213 override serverCount ( ) : Promise < number > {
205214 return PUBSUB ( this . pubClient , "SHARDNUMSUB" , this . channel ) ;
206215 }
216+
217+ private shouldUseASeparateNamespace ( room : string ) : boolean {
218+ const isPublicRoom = ! this . sids . has ( room ) ;
219+
220+ return (
221+ ( this . opts . subscriptionMode === "dynamic" && isPublicRoom ) ||
222+ this . opts . subscriptionMode === "dynamic-private"
223+ ) ;
224+ }
207225}
0 commit comments