Fix #1870: TypeError in PubSub #2016
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Fix race that causes #1870.
The root cause of that issue is a race in updating PubSubState that causes the parser to be in string mode instead of buffer mode when a PubSub 'message' event arrives from the server in the same data chunk as the 'subscribe' reply arrives.
The sequence of events triggering the issue:
.subscribe()
on the client objectRedisCommandsQueue.parseResponse
returnReply
with the reply 'subscribe'. This goes to this line:node-redis/packages/client/lib/client/commands-queue.ts
Line 135 in ac7d50c
shiftWaitingForReply
removes the 'subscribe' message fromthis.#waitingForReply
, then calls#setReturnBuffers
. Sincethis.#waitingForReply
is now empty andthis.#pubSubState.subscribed
hasn't been updated yet, it turns buffer mode off (switches to string mode)shiftWaitingForReply
returns,.resolve()
gets called here:node-redis/packages/client/lib/client/commands-queue.ts
Line 135 in ac7d50c
this.#pubSubState.subscribed
to 1 here:node-redis/packages/client/lib/client/commands-queue.ts
Line 305 in ac7d50c
returnReply
again with the reply 'message', but it's now in string mode, so thisBuffer.equals()
call throws:node-redis/packages/client/lib/client/commands-queue.ts
Line 115 in ac7d50c
If the 'subscribe' and 'message' replies come in separate chunks, the 'message' reply will turn buffer mode back on through this line, preventing the problem:
node-redis/packages/client/lib/client/commands-queue.ts
Line 377 in ac7d50c
The fix is to also enable buffer mode on the parser in
setReturnBuffers
ifthis.#pubSubState.subscribing
is nonzero, which avoids this race. As far as I can tell this is correct behavior.I have added a test which passes reliably with this patch, and (on my machine) fails without the patch. Since it is testing for a race, it may sometimes pass even without this patch.
Checklist
npm test
pass with this change (including linting)?