Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
1.6 kB · 53 lines
TypeScript
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354/** Serializes versioned writes without replacing edits made during a request. */export class BoardSaveQueue<T extends { version: number }> { private revision = 0; private savedRevision = 0; private pending: Promise<void> | null = null; value: T; error: Error | null = null;
constructor( initial: T, private readonly write: (value: T) => Promise<T>, private readonly notify: () => void, private readonly onSaved: (value: T) => void, ) { this.value = initial; }
get dirty() { return this.revision !== this.savedRevision; } get saving() { return this.pending !== null; }
update(value: T) { this.value = { ...value, version: this.value.version }; this.revision += 1; this.error = null; this.notify(); }
flush(): Promise<void> { if (this.pending) return this.pending; if (!this.dirty) return Promise.resolve(); this.error = null; // Defer execution so even a synchronous transport throw sees pending set. this.pending = Promise.resolve().then(async () => { while (this.dirty) { const revision = this.revision; const saved = await this.write(this.value); this.savedRevision = revision; this.value = revision === this.revision ? saved : { ...this.value, version: saved.version }; this.onSaved(saved); } }).catch((error: unknown) => { this.error = error instanceof Error ? error : new Error(String(error)); throw this.error; }).finally(() => { this.pending = null; this.notify(); }); this.notify(); return this.pending; }}