style(13-03): apply Prettier formatting across repo
Mechanical reformat — no logic changes. 398 files changed, 19125 insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc (singleQuote:true, semi:true, tabWidth:2, trailingComma:all, printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
phase: 03-event-write-back-pwa-install
|
||||
plan: "11"
|
||||
plan: '11'
|
||||
subsystem: api-broker
|
||||
tags: [tdd, gap-closure, outbox-worker, concurrency-guard, etag, durability, calDAV]
|
||||
dependency_graph:
|
||||
@@ -16,25 +16,25 @@ dependency_graph:
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "TDD RED→GREEN per task"
|
||||
- "DB sibling-status query pattern for durable inter-row ordering"
|
||||
- "Module-level boolean drain guard for single-process deployment"
|
||||
- 'TDD RED→GREEN per task'
|
||||
- 'DB sibling-status query pattern for durable inter-row ordering'
|
||||
- 'Module-level boolean drain guard for single-process deployment'
|
||||
- "Symbol.for('drizzle:Name') for safe Drizzle table identification in tests (JSON.stringify circular)"
|
||||
- "vi.resetAllMocks() instead of vi.clearAllMocks() when mockImplementationOnce queues must be purged"
|
||||
- "Per-table mockWhere functions (mockWherePending vs mockWhereCalEvents) to isolate select mocks"
|
||||
- 'vi.resetAllMocks() instead of vi.clearAllMocks() when mockImplementationOnce queues must be purged'
|
||||
- 'Per-table mockWhere functions (mockWherePending vs mockWhereCalEvents) to isolate select mocks'
|
||||
key_files:
|
||||
modified:
|
||||
- apps/api/src/broker/outboxWorker.ts
|
||||
- apps/api/tests/broker/outboxWorker.test.ts
|
||||
key_decisions:
|
||||
- "CR-04 durable gate uses DB sibling-status query (not in-memory Set) so create-before-delete ordering holds across drain cycles; in-batch fast path retained as optimization"
|
||||
- 'CR-04 durable gate uses DB sibling-status query (not in-memory Set) so create-before-delete ordering holds across drain cycles; in-batch fast path retained as optimization'
|
||||
- "CR-05 isDraining guard is explicitly documented as single-process-only; multi-replica deployments would need DB row-claim (UPDATE WHERE status='pending' with affected-rows check)"
|
||||
- "WR-02 fresh etag reads calendarEvents at dispatch time, not calendarOutbox enqueue time; D-08 conflict detection preserved — genuine external changes update calendarEvents.etag differently from any queued row"
|
||||
- 'WR-02 fresh etag reads calendarEvents at dispatch time, not calendarOutbox enqueue time; D-08 conflict detection preserved — genuine external changes update calendarEvents.etag differently from any queued row'
|
||||
- "mockFromFn updated to use Symbol.for('drizzle:Name') to identify Drizzle tables — JSON.stringify throws CircularReference on all MySqlTable instances"
|
||||
- "All beforeEach blocks switched to vi.resetAllMocks() to prevent unconsumed mockImplementationOnce calls bleeding into subsequent tests"
|
||||
- 'All beforeEach blocks switched to vi.resetAllMocks() to prevent unconsumed mockImplementationOnce calls bleeding into subsequent tests'
|
||||
requirements-completed: [CAL-05, CAL-06]
|
||||
duration: 30min
|
||||
completed: "2026-06-05"
|
||||
completed: '2026-06-05'
|
||||
---
|
||||
|
||||
# Phase 03 Plan 11: Outbox Durability and Etag Fix Summary
|
||||
@@ -81,6 +81,7 @@ Each task was committed atomically:
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] Drizzle table identification using JSON.stringify throws CircularReference**
|
||||
|
||||
- **Found during:** Task 1 GREEN — when running tests after implementing the sibling-status DB select
|
||||
- **Issue:** `wireMockChain`'s `mockFromFn` used `JSON.stringify(table).includes('member_credentials')` to identify the credential table. `JSON.stringify` on a Drizzle `MySqlTable` object throws `TypeError: Converting circular structure to JSON` (MySqlInt columns hold a back-reference to their parent table). The `catch` block silently set `isCred = false`, making ALL `db.select().from(...)` calls route to `mockWherePending` — including credential lookups. Prior tests "worked" accidentally because `mockDecryptPassword` was mocked to succeed regardless of input, but the new sibling-status select consumed `mockWherePending` calls out of order, breaking the D-04 ordering test and the CR-04 drain 2 test.
|
||||
- **Fix:** Replaced with `(table as Record<symbol, string>)[Symbol.for('drizzle:Name')]` which reads the table name property Drizzle attaches as a Symbol. Added separate `mockWhereCalEvents` for `calendarEvents` table selects. Switched all `beforeEach` to `vi.resetAllMocks()`.
|
||||
@@ -106,10 +107,10 @@ None beyond the mock infrastructure deviation above.
|
||||
|
||||
## Issues Closed
|
||||
|
||||
| ID | Description |
|
||||
|----|-------------|
|
||||
| CR-04 | Create-before-delete ordering relied on in-memory Set, broke across drain batches — DB sibling-status gate now authoritative |
|
||||
| CR-05 | No concurrency guard — overlapping drain cycles could double-dispatch same row — isDraining guard prevents it (single-process) |
|
||||
| ID | Description |
|
||||
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| CR-04 | Create-before-delete ordering relied on in-memory Set, broke across drain batches — DB sibling-status gate now authoritative |
|
||||
| CR-05 | No concurrency guard — overlapping drain cycles could double-dispatch same row — isDraining guard prevents it (single-process) |
|
||||
| WR-02 | Update dispatch used stale enqueue-time etag — rapid successive edits guaranteed 412 — fresh calendarEvents.etag re-read at dispatch time |
|
||||
|
||||
## Known Stubs
|
||||
|
||||
Reference in New Issue
Block a user