fix(progresses): prevent duplicate progress documents via atomic create (#1158) - #2607
fix(progresses): prevent duplicate progress documents via atomic create (#1158)#2607JSap0914 wants to merge 1 commit into
Conversation
…ealDevSquad#1158) createProgressDocument used a check-then-add sequence: it queried for an existing progress document for the day and, if none was found, called progressesCollection.add() with an auto-generated id. Two requests made within the same second could both observe an empty result and each insert a document, producing the duplicates reported in RealDevSquad#1158. Derive a deterministic document id from the uniqueness key (type + user/task + day) and insert with an atomic create(), which fails with ALREADY_EXISTS when a document for that key already exists. Concurrent creates for the same day can therefore never both succeed; the loser is surfaced as the existing 409 Conflict. Add unit regression tests covering the concurrent race (exactly one document persists) and the sequential duplicate case.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Summary by CodeRabbit
WalkthroughProgress creation now derives deterministic daily document IDs and uses atomic Firestore creation. Existing-document conflicts become 409 errors, with tests covering concurrent and sequential duplicate attempts. ChangesProgress creation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant RequestA
participant RequestB
participant Firestore
RequestA->>Firestore: Create deterministic progress document
RequestB->>Firestore: Create deterministic progress document
Firestore-->>RequestA: Creation succeeds
Firestore-->>RequestB: Already-exists error mapped to 409 Conflict
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Issue Ticket Number
Closes #1158
Description
createProgressDocumentcreated duplicate documents in theprogressescollection under concurrent load. It used a check-then-add sequence: query for an existing progress document for the current day and, if none was found, callprogressesCollection.add()with an auto-generated id. Two requests made within the same second can both observe an empty result and each insert a document, producing the duplicates reported in #1158.Fix: derive a deterministic document id from the uniqueness key (
type+ user/task id + day timestamp) and insert with an atomiccreate(). Firestore'screate()fails withALREADY_EXISTSwhen a document with that id already exists, so concurrent creates for the same user/task and day can never both succeed. The losing request is surfaced as the existing409 Conflict(... Progress for the day has already been created.), preserving current API behaviour. The pre-write query check is retained as a fast path.Regression tests added in
test/unit/models/progresses.test.js:createProgressDocumentcalls for the same user/day viaPromise.allSettledand asserts exactly one document persists (one fulfilled, one409);409and leaves a single document.Documentation Updated?
Under Feature Flag
Database Changes
New progress documents now use a deterministic id (
type:id:date) instead of an auto-generated id. Existing documents are unaffected; reads are by query, not by id.Breaking Changes
Test Coverage
Focused unit run against the Firestore emulator: