Skip to content

Concurrent requests to SUNSUBCRIBE causes a race condition bug (ClientClosedError) #2685

Closed
@BrentLayne

Description

@BrentLayne

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions