import { backoff } from "./time"; export class InvalidateSync { private _invalidated = false; private _invalidatedDouble = false; private _stopped = false; private _command: () => Promise; private _pendings: (() => void)[] = []; constructor(command: () => Promise) { this._command = command; } invalidate() { if (this._stopped) { return; } if (!this._invalidated) { this._invalidated = true; this._invalidatedDouble = false; this._doSync(); } else { if (!this._invalidatedDouble) { this._invalidatedDouble = true; } } } async invalidateAndAwait() { if (this._stopped) { return; } await new Promise(resolve => { this._pendings.push(resolve); this.invalidate(); }); } stop() { if (this._stopped) { return; } this._notifyPendings(); this._stopped = true; } private _notifyPendings = () => { for (let pending of this._pendings) { pending(); } this._pendings = []; } private _doSync = async () => { await backoff(async () => { if (this._stopped) { return; } await this._command(); }); if (this._stopped) { this._notifyPendings(); return; } if (this._invalidatedDouble) { this._invalidatedDouble = false; this._doSync(); } else { this._invalidated = false; this._notifyPendings(); } } }