OpenGlass/sources/utils/invalidateSync.ts

74 lines
1.7 KiB
TypeScript

import { backoff } from "./time";
export class InvalidateSync {
private _invalidated = false;
private _invalidatedDouble = false;
private _stopped = false;
private _command: () => Promise<void>;
private _pendings: (() => void)[] = [];
constructor(command: () => Promise<void>) {
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<void>(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();
}
}
}