项目文件夹

文件
wehub-resource-sync 98e40dac97
CLI Smoke Test / smoke-test-linux (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-linux (24) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (24) (push) Has been cancelled
Expo App TypeScript typecheck / typecheck (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:40:49 +08:00

164 行
3.9 KiB
TypeScript

import { backoff } from "@/utils/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();
});
}
async awaitQueue() {
if (this._stopped || (!this._invalidated && this._pendings.length === 0)) {
return;
}
await new Promise<void>(resolve => {
this._pendings.push(resolve);
});
}
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();
}
}
}
export class ValueSync<T> {
private _latestValue: T | undefined;
private _hasValue = false;
private _processing = false;
private _stopped = false;
private _command: (value: T) => Promise<void>;
private _pendings: (() => void)[] = [];
constructor(command: (value: T) => Promise<void>) {
this._command = command;
}
setValue(value: T) {
if (this._stopped) {
return;
}
this._latestValue = value;
this._hasValue = true;
if (!this._processing) {
this._processing = true;
this._doSync();
}
}
async setValueAndAwait(value: T) {
if (this._stopped) {
return;
}
await new Promise<void>(resolve => {
this._pendings.push(resolve);
this.setValue(value);
});
}
async awaitQueue() {
if (this._stopped || (!this._processing && this._pendings.length === 0)) {
return;
}
await new Promise<void>(resolve => {
this._pendings.push(resolve);
});
}
stop() {
if (this._stopped) {
return;
}
this._notifyPendings();
this._stopped = true;
}
private _notifyPendings = () => {
for (let pending of this._pendings) {
pending();
}
this._pendings = [];
}
private _doSync = async () => {
while (this._hasValue && !this._stopped) {
const value = this._latestValue!;
this._hasValue = false;
await backoff(async () => {
if (this._stopped) {
return;
}
await this._command(value);
});
if (this._stopped) {
this._notifyPendings();
return;
}
}
this._processing = false;
this._notifyPendings();
}
}