143 lines
7.7 KiB
Markdown
143 lines
7.7 KiB
Markdown
---
|
|
phase: 09-faster-write-back
|
|
reviewed: 2026-06-12T21:05:00Z
|
|
depth: standard
|
|
files_reviewed: 5
|
|
files_reviewed_list:
|
|
- apps/api/src/lib/outboxTrigger.ts
|
|
- apps/api/src/broker/outboxWorker.ts
|
|
- apps/api/src/routes/events.ts
|
|
- apps/api/src/index.ts
|
|
- apps/api/tests/broker/outboxWorker.test.ts
|
|
findings:
|
|
critical: 0
|
|
warning: 0
|
|
info: 2
|
|
total: 2
|
|
status: issues_found
|
|
---
|
|
|
|
# Phase 09: Code Review Report
|
|
|
|
**Reviewed:** 2026-06-12
|
|
**Depth:** standard
|
|
**Status:** issues_found (2 Info; no Blockers, no Warnings)
|
|
|
|
## Summary
|
|
|
|
Iteration-2 re-review of the phase-09 write-back trigger wiring after a fixer pass
|
|
addressed all seven iteration-1 findings (WR-01..03, IN-01..04). I re-traced the four
|
|
high-risk areas the prompt called out and verified each fix is correct AND complete,
|
|
and scanned for new defects the fixes could have introduced. Tooling: `vitest run`
|
|
(30/30 pass) and `tsc --noEmit` (exit 0, both clean).
|
|
|
|
**Fix verification — all four focus areas confirmed correct:**
|
|
|
|
1. **`queueMicrotask` deferral (WR-01).** `signalOutboxDrain()` now defers the emit:
|
|
`queueMicrotask(() => emitter.emit('drain'))` (outboxTrigger.ts:37). This preserves
|
|
fire-and-forget (the caller never blocks) and moves listener execution off the route
|
|
handler's stack, so a synchronous throw in the listener chain can no longer corrupt the
|
|
enqueue response. Trailing-re-drain semantics are intact: in the D-05 test two mid-drain
|
|
signals each queue a microtask; both microtasks run (and collapse to one
|
|
`drainRequested=true`) before the test's `setImmediate`-based flushes, yielding exactly
|
|
2 dispatches — the test still passes. The stale "Synchronous" JSDoc claim flagged in
|
|
iteration 1 is gone; the new comment block (lines 24-35) accurately describes the
|
|
deferral. **Correct and complete.**
|
|
|
|
2. **`initOutboxTrigger()` idempotency (WR-02).** Now guarded by a retained module-level
|
|
`unsubscribeDrain` handle (outboxWorker.ts:858-863): a second call short-circuits
|
|
(`if (unsubscribeDrain) return`), so no double-`'drain'`-listener and no
|
|
`MaxListenersExceededWarning`. `stopOutboxTrigger()` (871-874) calls the retained
|
|
unsubscribe and nulls the handle, allowing a clean re-`init`. The unsubscribe closure
|
|
passed to `emitter.off('drain', handler)` is the exact handler registered by
|
|
`emitter.on('drain', handler)` (outboxTrigger.ts:45-46), so removal-by-reference is
|
|
correct. A `stop → init` cycle registers a fresh closure and captures a fresh handle —
|
|
no stale-listener leak. **Genuinely safe.**
|
|
|
|
3. **`resolveFinalRrule()` extraction (IN-02) — byte-identical output.** Highest regression
|
|
risk (two previously independent write paths merged). I diffed the extraction commit
|
|
(d3163f2) line-by-line: the original `update` and `create` decision trees were **already
|
|
character-identical**, and both now call `resolveFinalRrule(fields, hasExplicitRecurrence,
|
|
rruleFromPayload, preservedRrule)` with identical argument order (outboxWorker.ts:476-481
|
|
and 554-559). The only per-branch difference — the *source* of `preservedRrule` (update
|
|
re-reads `rawVevent`; create reads `_preservedRrule`) — is computed before the call and
|
|
passed in, exactly as before. The bound-strip regex `/;(UNTIL|COUNT)=[^;]*/g`, the
|
|
COUNT-over-UNTIL precedence, and the `recurrence:'none' → undefined` clearing are all
|
|
preserved verbatim. The CR-01 create-branch tests (`_preservedRrule` → RRULE present;
|
|
`recurrence:'none'` → no RRULE) and the D-07 FREQ-persistence lock all pass. **No
|
|
behavioral change; byte-identical for both branches.**
|
|
|
|
4. **`__resetDrainState()` test-only hook (IN-03).** Exported from the production module but
|
|
confirmed to have NO production caller (`grep` shows only the declaration and test
|
|
imports). It resets `isDraining`/`drainRequested` to false, which is correct for the
|
|
`beforeEach` quiescent-state reset and harmless in the test process. The only residual
|
|
concern is the unguarded production export (see IN-01 below). The stale RED `@ts-ignore`
|
|
removal (IN-04) and the `afterAll(stopOutboxTrigger)` teardown (WR-03) are both present
|
|
and the suite is green, confirming no leaked listener bleeds across describe blocks under
|
|
`fileParallelism:false`.
|
|
|
|
**No new BLOCKER or WARNING defects were introduced by the fixes.** The two findings below
|
|
are Info-level robustness notes; both are pre-existing or latent, neither blocks shipping.
|
|
|
|
## Narrative Findings (AI reviewer)
|
|
|
|
### IN-01: `__resetDrainState()` is a production export with no environment guard
|
|
|
|
**File:** `apps/api/src/broker/outboxWorker.ts:883-886`
|
|
|
|
**Issue:** `__resetDrainState()` is exported from a production module and unconditionally
|
|
clears the entire single-process concurrency contract (`isDraining = false;
|
|
drainRequested = false;`). Its only protection against misuse is a JSDoc line ("Not for
|
|
production use"). If any future code path imports and calls it while a drain is in flight,
|
|
it would clear `isDraining` mid-cycle and allow `scheduleOutboxDrain()`/`runOutboxDrain()`
|
|
to start a concurrent drain that double-dispatches the same still-`pending` outbox row —
|
|
exactly the CR-05 hazard the guard exists to prevent. Today there is no such caller (grep
|
|
confirms test-only usage), so this is latent, not active.
|
|
|
|
**Fix:** Gate the body on a non-production check so an accidental production call is a
|
|
no-op, keeping the contract enforced by code rather than by comment:
|
|
|
|
```ts
|
|
export function __resetDrainState(): void {
|
|
if (process.env.NODE_ENV === 'production') return; // test-only; never clear the guard in prod
|
|
isDraining = false;
|
|
drainRequested = false;
|
|
}
|
|
```
|
|
|
|
(Alternatively, move the reset behind a test-only entry point not reachable from the
|
|
production import graph. The env guard is the smaller change.)
|
|
|
|
### IN-02: Signal arriving in the `isDraining=false` → `.finally` window starts a fresh drain rather than collapsing via `drainRequested`
|
|
|
|
**File:** `apps/api/src/broker/outboxWorker.ts:237-253` (in concert with the
|
|
`isDraining=false` reset at line 838)
|
|
|
|
**Issue:** `runOutboxDrain` clears `isDraining` in its own `finally` (line 838), and the
|
|
`.finally()` callback in `scheduleOutboxDrain` (line 246) runs in a *later* microtask. A
|
|
`signalOutboxDrain()` whose deferred emit lands in that gap finds `isDraining === false`
|
|
and starts a brand-new `runOutboxDrain()` directly instead of being collapsed into the
|
|
single trailing re-drain via `drainRequested`. The just-completed drain's `.finally` may
|
|
then *also* observe `drainRequested` (if a still-earlier signal set it) and kick a second
|
|
pass. The net effect can be two near-back-to-back drains instead of one collapsed trailing
|
|
drain. This is NOT a correctness bug — the re-entrant `isDraining` guard (line 658) keeps
|
|
every concrete `runOutboxDrain` body strictly serialized, so no row is double-dispatched —
|
|
but it weakens the documented "collapse any number of mid-drain signals into exactly one
|
|
trailing drain" guarantee (lines 216-219) at this specific boundary, and can produce one
|
|
extra Fastmail-facing drain pass under rapid edits. It is pre-existing (the `queueMicrotask`
|
|
deferral did not create it; it only shifts the emit by one microtask) and was not flagged
|
|
in iteration 1.
|
|
|
|
**Fix:** Reset `isDraining` and check/consume `drainRequested` in the *same* synchronous
|
|
step so the gap cannot be observed — e.g. fold the trailing-re-drain decision into
|
|
`runOutboxDrain`'s own `finally` (snapshot `const shouldRedrain = drainRequested`, reset
|
|
both flags atomically before releasing `isDraining`), rather than splitting the reset
|
|
(`runOutboxDrain.finally`) from the re-drain trigger (`scheduleOutboxDrain.finally`). Low
|
|
priority given the guard makes the worst case one redundant — not unsafe — drain pass.
|
|
|
|
---
|
|
|
|
_Reviewed: 2026-06-12T21:05:00Z_
|
|
_Reviewer: Claude (gsd-code-reviewer)_
|
|
_Depth: standard_
|