From 2c3e569edfe5c4778ca4c53b4688a0cc2a7aa34f Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Tue, 7 Jun 2022 15:46:22 +0200 Subject: [PATCH 1/2] monitor liveness of beacons yet to start Signed-off-by: Kerry Archibald --- spec/unit/models/beacon.spec.ts | 38 ++++++++++++++++++++++++++++++++- src/models/beacon.ts | 7 ++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/spec/unit/models/beacon.spec.ts b/spec/unit/models/beacon.spec.ts index dc4058d1ce4..607a9b8c8f0 100644 --- a/spec/unit/models/beacon.spec.ts +++ b/spec/unit/models/beacon.spec.ts @@ -71,7 +71,7 @@ describe('Beacon', () => { const advanceDateAndTime = (ms: number) => { // bc liveness check uses Date.now we have to advance this mock - jest.spyOn(global.Date, 'now').mockReturnValue(now + ms); + jest.spyOn(global.Date, 'now').mockReturnValue(Date.now() + ms); // then advance time for the interval by the same amount jest.advanceTimersByTime(ms); }; @@ -231,6 +231,42 @@ describe('Beacon', () => { expect(emitSpy).not.toHaveBeenCalled(); }); + it('checks liveness of beacon at expected start time', () => { + // go forward in time to make beacon with timestamp in future + jest.spyOn(global.Date, 'now').mockReturnValue(now + HOUR_MS); + const futureBeaconEvent = makeBeaconInfoEvent( + userId, + roomId, + { + timeout: HOUR_MS * 3, + isLive: true, + }, + '$live123', + ); + // go back to now + jest.spyOn(global.Date, 'now').mockReturnValue(now); + + const beacon = new Beacon(futureBeaconEvent); + expect(beacon.isLive).toBeFalsy(); + const emitSpy = jest.spyOn(beacon, 'emit'); + + beacon.monitorLiveness(); + + // advance to the start timestamp of the beacon + advanceDateAndTime(HOUR_MS + 1); + + // beacon is in live period now + expect(emitSpy).toHaveBeenCalledTimes(1); + expect(emitSpy).toHaveBeenCalledWith(BeaconEvent.LivenessChange, true, beacon); + + // check the expiry monitor is still setup ok + // advance to the expiry + advanceDateAndTime(HOUR_MS * 3 + 100); + + expect(emitSpy).toHaveBeenCalledTimes(2); + expect(emitSpy).toHaveBeenCalledWith(BeaconEvent.LivenessChange, false, beacon); + }); + it('checks liveness of beacon at expected expiry time', () => { // live beacon was created an hour ago // and has a 3hr duration diff --git a/src/models/beacon.ts b/src/models/beacon.ts index a4f7694588b..e4ac544052f 100644 --- a/src/models/beacon.ts +++ b/src/models/beacon.ts @@ -135,6 +135,13 @@ export class Beacon extends TypedEventEmitter Date.now()) { + // beacon start timestamp is in the future + // check liveness again then + this.livenessWatchInterval = setInterval( + () => { this.monitorLiveness(); }, + this.beaconInfo?.timestamp - Date.now(), + ); } } From 934f0b0b1e482c85713918afe01b6c2df82efcce Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Tue, 7 Jun 2022 15:55:49 +0200 Subject: [PATCH 2/2] make watch interval a timeout instead Signed-off-by: Kerry Archibald --- spec/unit/models/beacon.spec.ts | 6 +++--- src/models/beacon.ts | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/unit/models/beacon.spec.ts b/spec/unit/models/beacon.spec.ts index 607a9b8c8f0..30052ae7ca1 100644 --- a/spec/unit/models/beacon.spec.ts +++ b/spec/unit/models/beacon.spec.ts @@ -224,7 +224,7 @@ describe('Beacon', () => { beacon.monitorLiveness(); // @ts-ignore - expect(beacon.livenessWatchInterval).toBeFalsy(); + expect(beacon.livenessWatchTimeout).toBeFalsy(); advanceDateAndTime(HOUR_MS * 2 + 1); // no emit @@ -289,12 +289,12 @@ describe('Beacon', () => { beacon.monitorLiveness(); // @ts-ignore - const oldMonitor = beacon.livenessWatchInterval; + const oldMonitor = beacon.livenessWatchTimeout; beacon.monitorLiveness(); // @ts-ignore - expect(beacon.livenessWatchInterval).not.toEqual(oldMonitor); + expect(beacon.livenessWatchTimeout).not.toEqual(oldMonitor); }); it('destroy kills liveness monitor and emits', () => { diff --git a/src/models/beacon.ts b/src/models/beacon.ts index e4ac544052f..05562574322 100644 --- a/src/models/beacon.ts +++ b/src/models/beacon.ts @@ -54,7 +54,7 @@ export class Beacon extends TypedEventEmitter; + private livenessWatchTimeout: ReturnType; private _latestLocationState: BeaconLocationState | undefined; constructor( @@ -109,8 +109,8 @@ export class Beacon extends TypedEventEmitter 1) { - this.livenessWatchInterval = setInterval( + this.livenessWatchTimeout = setTimeout( () => { this.monitorLiveness(); }, expiryInMs, ); @@ -138,7 +138,7 @@ export class Beacon extends TypedEventEmitter Date.now()) { // beacon start timestamp is in the future // check liveness again then - this.livenessWatchInterval = setInterval( + this.livenessWatchTimeout = setTimeout( () => { this.monitorLiveness(); }, this.beaconInfo?.timestamp - Date.now(), );