http-api: prevent double-processing of events

In reconnect scenarios (or wonky network situations) we may receive
events we had already heard. Here we make sure to drop those.

Also simplifies the getEventId() logic.
This commit is contained in:
fang 2022-07-15 23:17:54 +02:00
parent 5f1371f4a2
commit 529e3fd77f
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972

View File

@ -28,11 +28,13 @@ export class Urbit {
private uid: string = `${Math.floor(Date.now() / 1000)}-${hexString(6)}`;
/**
* Last Event ID is an auto-updated index of which events have been sent over this channel
* lastEventId is an auto-updated index of which events have been *sent* over this channel.
* lastHeardEventId is the latest event we have heard back about.
* lastAcknowledgedEventId is the latest event we have sent an ack for.
*/
private lastEventId: number = 0;
private lastAcknowledgedEventId: number = 0;
private lastHeardEventId: number = -1;
private lastAcknowledgedEventId: number = -1;
/**
* SSE Client is null for now; we don't want to start polling until it the channel exists
@ -236,6 +238,13 @@ export class Urbit {
}
if (!event.id) return;
const eventId = parseInt(event.id, 10);
if (eventId <= this.lastHeardEventId) {
console.log('dropping old or out-of-order event', {
eventId, lastHeard: this.lastHeardEventId
});
return;
}
this.lastHeardEventId = eventId;
if (eventId - this.lastAcknowledgedEventId > 20) {
this.ack(eventId);
}
@ -320,7 +329,8 @@ export class Urbit {
this.abort = new AbortController();
this.uid = `${Math.floor(Date.now() / 1000)}-${hexString(6)}`;
this.lastEventId = 0;
this.lastAcknowledgedEventId = 0;
this.lastHeardEventId = -1;
this.lastAcknowledgedEventId = -1;
this.outstandingSubscriptions = new Map();
this.outstandingPokes = new Map();
this.sseClientInitialized = false;
@ -330,8 +340,7 @@ export class Urbit {
* Autoincrements the next event ID for the appropriate channel.
*/
private getEventId(): number {
this.lastEventId = Number(this.lastEventId) + 1;
return this.lastEventId;
return ++this.lastEventId;
}
/**