Description
Description
Bug description
Making concurrent requests to SUNSUBSCRIBE
causes one or more of the requests to throw the ClientClosedError
Why is this happening?
This bug is caused by a race condition due to how the executeShardedUnsubscribeCommand function works:
- The function awaits multiple async calls
- THEN the function calls
client.disconnect()
Every time the executeShardedUnsubscribeCommand
function encounters an await
, function execution is paused and the javascript thread begins to process the other concurrent requests to SUNBSUBSCRIBE
. As a result, the requests to SUNSUBSCRIBE
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 the ClientClosedError
being thrown
What is the expected behaviour?
I can make concurrent requests to SUNSUBSCRIBE
and all the requests resolve with no errors thrown
Steps to reproduce
Run the below script to reproduce the race condition bug:
import { createCluster } from 'redis'
const client = createCluster({ rootNodes });
await client.connect();
const onMessage = () => {};
await client.sSubscribe('test', onMessage);
await client.sSubscribe('test2', onMessage);
try {
// concurrent requests to sUnsubscribe are racing against each other to disconnect the socket
await Promise.all([
client.sUnsubscribe('test', onMessage),
client.sUnsubscribe('test2', onMessage),
]);
} catch (error) {
// this log statement logs the ClientClosedError
console.log('*** error ***', error);
}
Node.js Version
18.18.2
Redis Server Version
7.0.7
Node Redis Version
4.6.7
Platform
macOS
Logs
No response