-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Concurrent requests to SUNSUBCRIBE
causes a race condition bug (ClientClosedError
)
#2685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think the fix might be as simple as adding a check for i.e. the function definition should be changed to be the following: async executeShardedUnsubscribeCommand(
channel: string,
unsubscribe: (client: RedisClientType<M, F, S>) => Promise<void>
): Promise<void> {
const { master } = this.slots[calculateSlot(channel)];
if (!master.pubSubClient) return Promise.resolve();
const client = await master.pubSubClient;
await unsubscribe(client);
// NEW: Confirm that the client.isOpen before disconnecting
if (!client.isPubSubActive && client.isOpen) {
await client.disconnect();
master.pubSubClient = undefined;
}
} With this change, I no longer see an error |
Also worth noting that cluster |
@BrentLayne Good catch! Want to open a PR (preferably with a test)? Or you prefer I'll take it from here? |
@leibale I should have a PR up shortly! |
fixed in #2687 |
Description
Bug description
Making concurrent requests to
SUNSUBSCRIBE
causes one or more of the requests to throw the ClientClosedErrorWhy is this happening?
This bug is caused by a race condition due to how the executeShardedUnsubscribeCommand function works:
client.disconnect()
Every time the
executeShardedUnsubscribeCommand
function encounters anawait
, function execution is paused and the javascript thread begins to process the other concurrent requests toSUNBSUBSCRIBE
. As a result, the requests toSUNSUBSCRIBE
are now racing against each other.The request that 'wins' this race will call
disconnect()
first and disconnect the socket. The subsequent requests will try to disconnect the socket again, resulting in theClientClosedError
being thrownWhat is the expected behaviour?
I can make concurrent requests to
SUNSUBSCRIBE
and all the requests resolve with no errors thrownSteps to reproduce
Run the below script to reproduce the race condition bug:
Node.js Version
18.18.2
Redis Server Version
7.0.7
Node Redis Version
4.6.7
Platform
macOS
Logs
No response
The text was updated successfully, but these errors were encountered: