Context
api-server/job-persistence.ts implements a write-serialization mutex using a manually chained Promise:
let writeLockPromise: Promise<void> = Promise.resolve();
const prev = writeLockPromise;
writeLockPromise = new Promise<void>((resolve) => { release = resolve; });
await prev;
Concern
Under rapid, sustained bursts of write operations, this pattern creates a deeply nested chain of Promise references. While V8 GCs resolved Promises efficiently, a heavily saturated queue under peak load could contribute to memory pressure. The MAX_STORED_JOBS cap limits real-world severity, but the pattern is non-idiomatic and harder to reason about than a standard mutex.
Suggested Fix
Replace the manual chain with async-mutex:
import { Mutex } from "async-mutex";
const writeMutex = new Mutex();
async function saveJobs(modifier: (storage: JobStorage) => void): Promise<void> {
await writeMutex.runExclusive(async () => {
// ... existing write logic
});
}
Priority
Low — no observed impact, theoretical risk only. Safe to address in a follow-up refactor after the async fs/promises migration is stable.
Related
Identified during code review of PR #126 (feat/notion-api-service).