Skip to content

Commit

Permalink
feat: add volatile events
Browse files Browse the repository at this point in the history
A volatile packet will be dropped if:

- the socket is not connected
- the low-level transport is not ready (for example, a HTTP POST request is already pending)

Syntax:

```js
socket.volatile.emit("volatile event", "might or might not be sent");
```
  • Loading branch information
darrachequesne committed Oct 17, 2020
1 parent b600e78 commit 7ddad2c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 3 deletions.
32 changes: 29 additions & 3 deletions lib/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const RESERVED_EVENTS = {
removeListener: 1,
};

interface Flags {
compress?: boolean;
volatile?: boolean;
}

export class Socket extends Emitter {
public readonly io: Manager;

Expand All @@ -42,7 +47,7 @@ export class Socket extends Emitter {
private acks: object = {};
private receiveBuffer: Array<any> = [];
private sendBuffer: Array<any> = [];
private flags: any = {};
private flags: Flags = {};
private subs: Array<any>;

/**
Expand Down Expand Up @@ -136,7 +141,7 @@ export class Socket extends Emitter {
};

packet.options = {};
packet.options.compress = !this.flags || false !== this.flags.compress;
packet.options.compress = this.flags.compress !== false;

// event ack callback
if ("function" === typeof args[args.length - 1]) {
Expand All @@ -145,7 +150,16 @@ export class Socket extends Emitter {
packet.id = this.ids++;
}

if (this.connected) {
const isTransportWritable =
this.io.engine &&
this.io.engine.transport &&
this.io.engine.transport.writable;

const discardPacket =
this.flags.volatile && (!isTransportWritable || !this.connected);
if (discardPacket) {
debug("discard packet as the transport is not currently writable");
} else if (this.connected) {
this.packet(packet);
} else {
this.sendBuffer.push(packet);
Expand Down Expand Up @@ -406,4 +420,16 @@ export class Socket extends Emitter {
this.flags.compress = compress;
return this;
}

/**
* Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
* ready to send messages.
*
* @returns {Socket} self
* @public
*/
public get volatile(): Socket {
this.flags.volatile = true;
return this;
}
}
44 changes: 44 additions & 0 deletions test/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,48 @@ describe("socket", function () {
/"disconnecting" is a reserved event name/
);
});

describe("volatile packets", () => {
it("should discard a volatile packet when the socket is not connected", (done) => {
const socket = io({ forceNew: true, autoConnect: false });

socket.volatile.emit("getId", () => {
done(new Error("should not happen"));
});

socket.emit("getId", () => {
socket.disconnect();
done();
});

socket.connect();
});

it("should discard a volatile packet when the pipe is not ready", (done) => {
const socket = io({ forceNew: true });

socket.on("connect", () => {
socket.emit("getId", () => {
socket.disconnect();
done();
});

socket.volatile.emit("getId", () => {
done(new Error("should not happen"));
});
});
});

it("should send a volatile packet when the socket is connected and the pipe is ready", (done) => {
const socket = io({ forceNew: true });

const interval = setInterval(() => {
socket.volatile.emit("getId", () => {
clearInterval(interval);
socket.disconnect();
done();
});
}, 200);
});
});
});

0 comments on commit 7ddad2c

Please sign in to comment.