-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor TrueTime class to improve synchronization logic #51
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,28 @@ | ||
/* eslint-disable no-restricted-syntax */ | ||
export class TrueTime { | ||
#clientStartTime: number; | ||
#initialDrift: number; | ||
|
||
#serverTime?: number; | ||
|
||
#synced = false; | ||
#synced: number | undefined; | ||
|
||
#url: URL; | ||
|
||
constructor(url: string) { | ||
this.#url = new URL(url); | ||
this.#clientStartTime = performance.now(); | ||
this.#initialDrift = Math.abs( | ||
Date.now() - (this.timeOrigin() + this.#clientStartTime), | ||
); | ||
} | ||
|
||
currentDrift() { | ||
return Math.abs(Date.now() - (this.timeOrigin() + performance.now())); | ||
} | ||
|
||
driftDiff() { | ||
return Math.abs(this.#initialDrift - this.currentDrift()); | ||
} | ||
|
||
now(highResTimeStamp: DOMHighResTimeStamp = performance.now()): number { | ||
|
@@ -27,26 +40,42 @@ export class TrueTime { | |
); | ||
} | ||
|
||
async setServerTime() { | ||
try { | ||
const response = await fetch(this.#url); | ||
|
||
if (response.ok && response.headers.has('date')) { | ||
this.#serverTime = new Date(response.headers.get('date')!).getTime(); | ||
// eslint-disable-next-line no-restricted-syntax | ||
this.#synced = Date.now(); | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
|
||
/** | ||
* Use this method to synchronize time with the server. | ||
* | ||
* @param url - server url | ||
*/ | ||
async synchronize() { | ||
if (this.#synced) { | ||
// Synchronize at max once every 1 000 000 miliseconds | ||
// eslint-disable-next-line no-restricted-syntax | ||
if ( | ||
(this.#synced && Math.abs(this.#synced - Date.now()) < 1_000_000) || | ||
(this.#synced && | ||
Math.abs(this.#initialDrift - this.currentDrift()) < 1_000) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This "feels" like it is getting complicated, are we sure there are any benefits to not just replacing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then we'd have to re-implement performance.mark() with Date.now too... :/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it is a bit unfortunate that that is mixed in here, makes this more complex than it should be :-( Might need to think a bit how we can avoid that.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I solved it in the other PR by setting |
||
) { | ||
return; | ||
} | ||
|
||
try { | ||
const response = await fetch(this.#url); | ||
return this.setServerTime(); | ||
} | ||
|
||
if (response.ok && response.headers.has('date')) { | ||
this.#serverTime = new Date(response.headers.get('date')!).getTime(); | ||
this.#synced = true; | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
// Just exported to be able to mock from test. | ||
timeOrigin() { | ||
return performance.timeOrigin; | ||
} | ||
|
||
timestamp(markName: string, detail?: string): number | undefined { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this should be allowed to run more than once, I can't see how it can work if not also setting
clientStartTime
?