diff --git a/packages/server/src/server/workspace-registry.ts b/packages/server/src/server/workspace-registry.ts index 99af40927..8ee034183 100644 --- a/packages/server/src/server/workspace-registry.ts +++ b/packages/server/src/server/workspace-registry.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { promises as fs } from 'node:fs' import path from 'node:path' @@ -62,6 +63,7 @@ class FileBackedRegistry { private readonly getId: (record: TRecord) => string private loaded = false private readonly cache = new Map() + private persistQueue: Promise = Promise.resolve() constructor(options: { filePath: string @@ -103,7 +105,7 @@ class FileBackedRegistry { await this.load() const parsed = this.schema.parse(record) this.cache.set(this.getId(parsed), parsed) - await this.persist() + await this.enqueuePersist() } async archive(id: string, archivedAt: string): Promise { @@ -118,7 +120,7 @@ class FileBackedRegistry { archivedAt, }) this.cache.set(id, next) - await this.persist() + await this.enqueuePersist() } async remove(id: string): Promise { @@ -126,7 +128,7 @@ class FileBackedRegistry { if (!this.cache.delete(id)) { return } - await this.persist() + await this.enqueuePersist() } private async load(): Promise { @@ -153,10 +155,16 @@ class FileBackedRegistry { private async persist(): Promise { const records = Array.from(this.cache.values()) await fs.mkdir(path.dirname(this.filePath), { recursive: true }) - const tempPath = `${this.filePath}.${process.pid}.${Date.now()}.tmp` + const tempPath = `${this.filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp` await fs.writeFile(tempPath, JSON.stringify(records, null, 2), 'utf8') await fs.rename(tempPath, this.filePath) } + + private async enqueuePersist(): Promise { + const nextPersist = this.persistQueue.then(() => this.persist()) + this.persistQueue = nextPersist.catch(() => {}) + await nextPersist + } } export class FileBackedProjectRegistry