@@ -53,16 +53,6 @@ interface PubSubListeners {
53
53
54
54
type PubSubListenersMap = Map < string , PubSubListeners > ;
55
55
56
- interface PubSubState {
57
- subscribing : number ;
58
- subscribed : number ;
59
- unsubscribing : number ;
60
- listeners : {
61
- channels : PubSubListenersMap ;
62
- patterns : PubSubListenersMap ;
63
- } ;
64
- }
65
-
66
56
export default class RedisCommandsQueue {
67
57
static #flushQueue< T extends CommandWaitingForReply > ( queue : LinkedList < T > , err : Error ) : void {
68
58
while ( queue . length ) {
@@ -98,7 +88,16 @@ export default class RedisCommandsQueue {
98
88
99
89
readonly #waitingForReply = new LinkedList < CommandWaitingForReply > ( ) ;
100
90
101
- #pubSubState: PubSubState | undefined ;
91
+ readonly #pubSubState = {
92
+ isActive : false ,
93
+ subscribing : 0 ,
94
+ subscribed : 0 ,
95
+ unsubscribing : 0 ,
96
+ listeners : {
97
+ channels : new Map ( ) ,
98
+ patterns : new Map ( )
99
+ }
100
+ } ;
102
101
103
102
static readonly #PUB_SUB_MESSAGES = {
104
103
message : Buffer . from ( 'message' ) ,
@@ -111,7 +110,7 @@ export default class RedisCommandsQueue {
111
110
112
111
readonly #parser = new RedisParser ( {
113
112
returnReply : ( reply : unknown ) => {
114
- if ( this . #pubSubState && Array . isArray ( reply ) ) {
113
+ if ( this . #pubSubState. isActive && Array . isArray ( reply ) ) {
115
114
if ( RedisCommandsQueue . #PUB_SUB_MESSAGES. message . equals ( reply [ 0 ] ) ) {
116
115
return RedisCommandsQueue . #emitPubSubMessage(
117
116
this . #pubSubState. listeners . channels ,
@@ -150,7 +149,7 @@ export default class RedisCommandsQueue {
150
149
}
151
150
152
151
addCommand < T = RedisCommandRawReply > ( args : RedisCommandArguments , options ?: QueueCommandOptions ) : Promise < T > {
153
- if ( this . #pubSubState && ! options ?. ignorePubSubMode ) {
152
+ if ( this . #pubSubState. isActive && ! options ?. ignorePubSubMode ) {
154
153
return Promise . reject ( new Error ( 'Cannot send commands in PubSub mode' ) ) ;
155
154
} else if ( this . #maxLength && this . #waitingToBeSent. length + this . #waitingForReply. length >= this . #maxLength) {
156
155
return Promise . reject ( new Error ( 'The queue is full' ) ) ;
@@ -190,27 +189,16 @@ export default class RedisCommandsQueue {
190
189
} ) ;
191
190
}
192
191
193
- #initiatePubSubState( ) : PubSubState {
194
- return this . #pubSubState ??= {
195
- subscribed : 0 ,
196
- subscribing : 0 ,
197
- unsubscribing : 0 ,
198
- listeners : {
199
- channels : new Map ( ) ,
200
- patterns : new Map ( )
201
- }
202
- } ;
203
- }
204
-
205
192
subscribe < T extends boolean > (
206
193
command : PubSubSubscribeCommands ,
207
194
channels : RedisCommandArgument | Array < RedisCommandArgument > ,
208
195
listener : PubSubListener < T > ,
209
196
returnBuffers ?: T
210
197
) : Promise < void > {
211
- const pubSubState = this . #initiatePubSubState( ) ,
212
- channelsToSubscribe : Array < RedisCommandArgument > = [ ] ,
213
- listenersMap = command === PubSubSubscribeCommands . SUBSCRIBE ? pubSubState . listeners . channels : pubSubState . listeners . patterns ;
198
+ const channelsToSubscribe : Array < RedisCommandArgument > = [ ] ,
199
+ listenersMap = command === PubSubSubscribeCommands . SUBSCRIBE ?
200
+ this . #pubSubState. listeners . channels :
201
+ this . #pubSubState. listeners . patterns ;
214
202
for ( const channel of ( Array . isArray ( channels ) ? channels : [ channels ] ) ) {
215
203
const channelString = typeof channel === 'string' ? channel : channel . toString ( ) ;
216
204
let listeners = listenersMap . get ( channelString ) ;
@@ -230,6 +218,7 @@ export default class RedisCommandsQueue {
230
218
if ( ! channelsToSubscribe . length ) {
231
219
return Promise . resolve ( ) ;
232
220
}
221
+
233
222
return this . #pushPubSubCommand( command , channelsToSubscribe ) ;
234
223
}
235
224
@@ -239,10 +228,6 @@ export default class RedisCommandsQueue {
239
228
listener ?: PubSubListener < T > ,
240
229
returnBuffers ?: T
241
230
) : Promise < void > {
242
- if ( ! this . #pubSubState) {
243
- return Promise . resolve ( ) ;
244
- }
245
-
246
231
const listeners = command === PubSubUnsubscribeCommands . UNSUBSCRIBE ?
247
232
this . #pubSubState. listeners . channels :
248
233
this . #pubSubState. listeners . patterns ;
@@ -280,8 +265,7 @@ export default class RedisCommandsQueue {
280
265
281
266
#pushPubSubCommand( command : PubSubSubscribeCommands | PubSubUnsubscribeCommands , channels : number | Array < RedisCommandArgument > ) : Promise < void > {
282
267
return new Promise ( ( resolve , reject ) => {
283
- const pubSubState = this . #initiatePubSubState( ) ,
284
- isSubscribe = command === PubSubSubscribeCommands . SUBSCRIBE || command === PubSubSubscribeCommands . PSUBSCRIBE ,
268
+ const isSubscribe = command === PubSubSubscribeCommands . SUBSCRIBE || command === PubSubSubscribeCommands . PSUBSCRIBE ,
285
269
inProgressKey = isSubscribe ? 'subscribing' : 'unsubscribing' ,
286
270
commandArgs : Array < RedisCommandArgument > = [ command ] ;
287
271
@@ -293,38 +277,42 @@ export default class RedisCommandsQueue {
293
277
channelsCounter = channels . length ;
294
278
}
295
279
296
- pubSubState [ inProgressKey ] += channelsCounter ;
280
+ this . #pubSubState. isActive = true ;
281
+ this . #pubSubState[ inProgressKey ] += channelsCounter ;
297
282
298
283
this . #waitingToBeSent. push ( {
299
284
args : commandArgs ,
300
285
channelsCounter,
301
286
returnBuffers : true ,
302
287
resolve : ( ) => {
303
- pubSubState [ inProgressKey ] -= channelsCounter ;
304
- if ( isSubscribe ) {
305
- pubSubState . subscribed += channelsCounter ;
306
- } else {
307
- pubSubState . subscribed -= channelsCounter ;
308
- if ( ! pubSubState . subscribed && ! pubSubState . subscribing && ! pubSubState . subscribed ) {
309
- this . #pubSubState = undefined ;
310
- }
311
- }
288
+ this . #pubSubState[ inProgressKey ] -= channelsCounter ;
289
+ this . #pubSubState. subscribed += channelsCounter * ( isSubscribe ? 1 : - 1 ) ;
290
+ this . #updatePubSubActiveState( ) ;
312
291
resolve ( ) ;
313
292
} ,
314
293
reject : err => {
315
- pubSubState [ inProgressKey ] -= channelsCounter * ( isSubscribe ? 1 : - 1 ) ;
294
+ this . #pubSubState[ inProgressKey ] -= channelsCounter * ( isSubscribe ? 1 : - 1 ) ;
295
+ this . #updatePubSubActiveState( ) ;
316
296
reject ( err ) ;
317
297
}
318
298
} ) ;
319
299
} ) ;
320
300
}
321
301
322
- resubscribe ( ) : Promise < any > | undefined {
323
- if ( ! this . #pubSubState) {
324
- return ;
302
+ #updatePubSubActiveState( ) : void {
303
+ if (
304
+ ! this . #pubSubState. subscribed &&
305
+ ! this . #pubSubState. subscribing &&
306
+ ! this . #pubSubState. subscribed
307
+ ) {
308
+ this . #pubSubState. isActive = false ;
325
309
}
310
+ }
326
311
312
+ resubscribe ( ) : Promise < any > | undefined {
327
313
this . #pubSubState. subscribed = 0 ;
314
+ this . #pubSubState. subscribing = 0 ;
315
+ this . #pubSubState. unsubscribing = 0 ;
328
316
329
317
const promises = [ ] ,
330
318
{ channels, patterns } = this . #pubSubState. listeners ;
@@ -369,8 +357,7 @@ export default class RedisCommandsQueue {
369
357
#setReturnBuffers( ) {
370
358
this . #parser. setReturnBuffers (
371
359
! ! this . #waitingForReply. head ?. value . returnBuffers ||
372
- ! ! this . #pubSubState?. subscribed ||
373
- ! ! this . #pubSubState?. subscribing
360
+ ! ! this . #pubSubState. isActive
374
361
) ;
375
362
}
376
363
@@ -390,6 +377,7 @@ export default class RedisCommandsQueue {
390
377
}
391
378
392
379
flushWaitingForReply ( err : Error ) : void {
380
+ this . #parser. reset ( ) ;
393
381
RedisCommandsQueue . #flushQueue( this . #waitingForReply, err ) ;
394
382
395
383
if ( ! this . #chainInExecution) return ;
0 commit comments