Skip to content

Commit 0c0eb00

Browse files
walde1024darrachequesne
authored andcommitted
fix: add timeout method to remote socket (#4558)
The RemoteSocket interface, which is returned when the client is connected on another Socket.IO server of the cluster, was lacking the `timeout()` method. Syntax: ```js const sockets = await io.fetchSockets(); for (const socket of sockets) { if (someCondition) { socket.timeout(1000).emit("some-event", (err) => { if (err) { // the client did not acknowledge the event in the given delay } }); } } ``` Related: #4595
1 parent f8640d9 commit 0c0eb00

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

lib/broadcast-operator.ts

+47-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
EventNames,
88
EventsMap,
99
TypedEventBroadcaster,
10+
DecorateAcknowledgements,
1011
DecorateAcknowledgementsWithTimeoutAndMultipleResponses,
1112
AllButLast,
1213
Last,
@@ -20,7 +21,9 @@ export class BroadcastOperator<EmitEvents extends EventsMap, SocketData>
2021
private readonly adapter: Adapter,
2122
private readonly rooms: Set<Room> = new Set<Room>(),
2223
private readonly exceptRooms: Set<Room> = new Set<Room>(),
23-
private readonly flags: BroadcastFlags = {}
24+
private readonly flags: BroadcastFlags & {
25+
expectSingleResponse?: boolean;
26+
} = {}
2427
) {}
2528

2629
/**
@@ -232,7 +235,10 @@ export class BroadcastOperator<EmitEvents extends EventsMap, SocketData>
232235

233236
const timer = setTimeout(() => {
234237
timedOut = true;
235-
ack.apply(this, [new Error("operation has timed out"), responses]);
238+
ack.apply(this, [
239+
new Error("operation has timed out"),
240+
this.flags.expectSingleResponse ? null : responses,
241+
]);
236242
}, this.flags.timeout);
237243

238244
let expectedServerCount = -1;
@@ -246,7 +252,10 @@ export class BroadcastOperator<EmitEvents extends EventsMap, SocketData>
246252
responses.length === expectedClientCount
247253
) {
248254
clearTimeout(timer);
249-
ack.apply(this, [null, responses]);
255+
ack.apply(this, [
256+
null,
257+
this.flags.expectSingleResponse ? null : responses,
258+
]);
250259
}
251260
};
252261

@@ -476,10 +485,44 @@ export class RemoteSocket<EmitEvents extends EventsMap, SocketData>
476485
this.data = details.data;
477486
this.operator = new BroadcastOperator<EmitEvents, SocketData>(
478487
adapter,
479-
new Set([this.id])
488+
new Set([this.id]),
489+
new Set(),
490+
{
491+
expectSingleResponse: true, // so that remoteSocket.emit() with acknowledgement behaves like socket.emit()
492+
}
480493
);
481494
}
482495

496+
/**
497+
* Adds a timeout in milliseconds for the next operation.
498+
*
499+
* @example
500+
* const sockets = await io.fetchSockets();
501+
*
502+
* for (const socket of sockets) {
503+
* if (someCondition) {
504+
* socket.timeout(1000).emit("some-event", (err) => {
505+
* if (err) {
506+
* // the client did not acknowledge the event in the given delay
507+
* }
508+
* });
509+
* }
510+
* }
511+
*
512+
* // note: if possible, using a room instead of looping over all sockets is preferable
513+
* io.timeout(1000).to(someConditionRoom).emit("some-event", (err, responses) => {
514+
* // ...
515+
* });
516+
*
517+
* @param timeout
518+
*/
519+
public timeout(timeout: number) {
520+
return this.operator.timeout(timeout) as BroadcastOperator<
521+
DecorateAcknowledgements<EmitEvents>,
522+
SocketData
523+
>;
524+
}
525+
483526
public emit<Ev extends EventNames<EmitEvents>>(
484527
ev: Ev,
485528
...args: EventParams<EmitEvents, Ev>

0 commit comments

Comments
 (0)