diff --git a/packages/socket.io/lib/broadcast-operator.ts b/packages/socket.io/lib/broadcast-operator.ts index 6a229dae..ca7eccf2 100644 --- a/packages/socket.io/lib/broadcast-operator.ts +++ b/packages/socket.io/lib/broadcast-operator.ts @@ -13,6 +13,9 @@ import type { FirstNonErrorArg, EventNamesWithError, } from "./typed-events"; +import debugModule from "debug"; + +const debug = debugModule("socket.io:broadcast-operator"); export class BroadcastOperator implements TypedEventBroadcaster @@ -235,6 +238,17 @@ export class BroadcastOperator const timer = setTimeout(() => { timedOut = true; + + debug("operation has timed out"); + // @ts-expect-error + const packetId = packet.id; + + if (packetId !== undefined) { + this.adapter.nsp.sockets.forEach((socket) => { + socket.acks.delete(packetId); + }); + } + ack.apply(this, [ new Error("operation has timed out"), this.flags.expectSingleResponse ? null : responses, @@ -246,6 +260,13 @@ export class BroadcastOperator let expectedClientCount = 0; const checkCompleteness = () => { + debug( + "responses: servers: %d / %d ; clients: %d / %d", + actualServerCount, + expectedServerCount, + responses.length, + expectedClientCount, + ); if ( !timedOut && expectedServerCount === actualServerCount && diff --git a/packages/socket.io/test/messaging-many.ts b/packages/socket.io/test/messaging-many.ts index 0a518150..87407a2f 100644 --- a/packages/socket.io/test/messaging-many.ts +++ b/packages/socket.io/test/messaging-many.ts @@ -534,6 +534,11 @@ describe("messaging many", () => { // @ts-ignore expect(err.responses).to.contain(1, 2); + for (const [, serverSocket] of io.of("/").sockets) { + // @ts-ignore accessing private acks map to verify cleanup + expect(serverSocket.acks.size).to.be(0); + } + success(done, io, socket1, socket2, socket3); } });