@@ -53,16 +53,6 @@ interface PubSubListeners {
5353
5454type PubSubListenersMap = Map < string , PubSubListeners > ;
5555
56- interface PubSubState {
57- subscribing : number ;
58- subscribed : number ;
59- unsubscribing : number ;
60- listeners : {
61- channels : PubSubListenersMap ;
62- patterns : PubSubListenersMap ;
63- } ;
64- }
65-
6656export default class RedisCommandsQueue {
6757 static #flushQueue< T extends CommandWaitingForReply > ( queue : LinkedList < T > , err : Error ) : void {
6858 while ( queue . length ) {
@@ -98,7 +88,16 @@ export default class RedisCommandsQueue {
9888
9989 readonly #waitingForReply = new LinkedList < CommandWaitingForReply > ( ) ;
10090
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+ } ;
102101
103102 static readonly #PUB_SUB_MESSAGES = {
104103 message : Buffer . from ( 'message' ) ,
@@ -111,7 +110,7 @@ export default class RedisCommandsQueue {
111110
112111 readonly #parser = new RedisParser ( {
113112 returnReply : ( reply : unknown ) => {
114- if ( this . #pubSubState && Array . isArray ( reply ) ) {
113+ if ( this . #pubSubState. isActive && Array . isArray ( reply ) ) {
115114 if ( RedisCommandsQueue . #PUB_SUB_MESSAGES. message . equals ( reply [ 0 ] ) ) {
116115 return RedisCommandsQueue . #emitPubSubMessage(
117116 this . #pubSubState. listeners . channels ,
@@ -150,7 +149,7 @@ export default class RedisCommandsQueue {
150149 }
151150
152151 addCommand < T = RedisCommandRawReply > ( args : RedisCommandArguments , options ?: QueueCommandOptions ) : Promise < T > {
153- if ( this . #pubSubState && ! options ?. ignorePubSubMode ) {
152+ if ( this . #pubSubState. isActive && ! options ?. ignorePubSubMode ) {
154153 return Promise . reject ( new Error ( 'Cannot send commands in PubSub mode' ) ) ;
155154 } else if ( this . #maxLength && this . #waitingToBeSent. length + this . #waitingForReply. length >= this . #maxLength) {
156155 return Promise . reject ( new Error ( 'The queue is full' ) ) ;
@@ -190,27 +189,16 @@ export default class RedisCommandsQueue {
190189 } ) ;
191190 }
192191
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-
205192 subscribe < T extends boolean > (
206193 command : PubSubSubscribeCommands ,
207194 channels : RedisCommandArgument | Array < RedisCommandArgument > ,
208195 listener : PubSubListener < T > ,
209196 returnBuffers ?: T
210197 ) : 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 ;
214202 for ( const channel of ( Array . isArray ( channels ) ? channels : [ channels ] ) ) {
215203 const channelString = typeof channel === 'string' ? channel : channel . toString ( ) ;
216204 let listeners = listenersMap . get ( channelString ) ;
@@ -230,6 +218,7 @@ export default class RedisCommandsQueue {
230218 if ( ! channelsToSubscribe . length ) {
231219 return Promise . resolve ( ) ;
232220 }
221+
233222 return this . #pushPubSubCommand( command , channelsToSubscribe ) ;
234223 }
235224
@@ -239,10 +228,6 @@ export default class RedisCommandsQueue {
239228 listener ?: PubSubListener < T > ,
240229 returnBuffers ?: T
241230 ) : Promise < void > {
242- if ( ! this . #pubSubState) {
243- return Promise . resolve ( ) ;
244- }
245-
246231 const listeners = command === PubSubUnsubscribeCommands . UNSUBSCRIBE ?
247232 this . #pubSubState. listeners . channels :
248233 this . #pubSubState. listeners . patterns ;
@@ -280,8 +265,7 @@ export default class RedisCommandsQueue {
280265
281266 #pushPubSubCommand( command : PubSubSubscribeCommands | PubSubUnsubscribeCommands , channels : number | Array < RedisCommandArgument > ) : Promise < void > {
282267 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 ,
285269 inProgressKey = isSubscribe ? 'subscribing' : 'unsubscribing' ,
286270 commandArgs : Array < RedisCommandArgument > = [ command ] ;
287271
@@ -293,38 +277,42 @@ export default class RedisCommandsQueue {
293277 channelsCounter = channels . length ;
294278 }
295279
296- pubSubState [ inProgressKey ] += channelsCounter ;
280+ this . #pubSubState. isActive = true ;
281+ this . #pubSubState[ inProgressKey ] += channelsCounter ;
297282
298283 this . #waitingToBeSent. push ( {
299284 args : commandArgs ,
300285 channelsCounter,
301286 returnBuffers : true ,
302287 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( ) ;
312291 resolve ( ) ;
313292 } ,
314293 reject : err => {
315- pubSubState [ inProgressKey ] -= channelsCounter * ( isSubscribe ? 1 : - 1 ) ;
294+ this . #pubSubState[ inProgressKey ] -= channelsCounter * ( isSubscribe ? 1 : - 1 ) ;
295+ this . #updatePubSubActiveState( ) ;
316296 reject ( err ) ;
317297 }
318298 } ) ;
319299 } ) ;
320300 }
321301
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 ;
325309 }
310+ }
326311
312+ resubscribe ( ) : Promise < any > | undefined {
327313 this . #pubSubState. subscribed = 0 ;
314+ this . #pubSubState. subscribing = 0 ;
315+ this . #pubSubState. unsubscribing = 0 ;
328316
329317 const promises = [ ] ,
330318 { channels, patterns } = this . #pubSubState. listeners ;
@@ -369,8 +357,7 @@ export default class RedisCommandsQueue {
369357 #setReturnBuffers( ) {
370358 this . #parser. setReturnBuffers (
371359 ! ! this . #waitingForReply. head ?. value . returnBuffers ||
372- ! ! this . #pubSubState?. subscribed ||
373- ! ! this . #pubSubState?. subscribing
360+ ! ! this . #pubSubState. isActive
374361 ) ;
375362 }
376363
@@ -390,6 +377,7 @@ export default class RedisCommandsQueue {
390377 }
391378
392379 flushWaitingForReply ( err : Error ) : void {
380+ this . #parser. reset ( ) ;
393381 RedisCommandsQueue . #flushQueue( this . #waitingForReply, err ) ;
394382
395383 if ( ! this . #chainInExecution) return ;
0 commit comments