Repository navigation
feat(email): dual-write finalized inbound Mailbox state - #1127
Conversation
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
📝 WalkthroughWalkthroughInbound email processing now schedules terminal Mailbox work. Received deliveries mirror graphs, apply effects, and mirror updated events. Rejected deliveries mirror only events. Retries, failures, replay repair, system mail, and D1 authority are covered by tests and documentation. ChangesInbound Mailbox mirroring
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant InboundEmail
participant TerminalWork
participant Mailbox
participant D1Effects
participant EmailEvents
InboundEmail->>TerminalWork: schedule received terminal work
TerminalWork->>Mailbox: mirror message graph
TerminalWork->>D1Effects: apply delivery effects
D1Effects-->>TerminalWork: updated delivery state
TerminalWork->>EmailEvents: mirror received delivery event
EmailEvents->>Mailbox: persist delivery event
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
Restore deleteEmailMessageById to D1 batch then immediate R2 cleanup with no Mailbox env/waitUntil/mirror. Restore insertEmailMessageWithAttachments signature without mirror forwarding. Drop PR-only delete mirror tests and update data-storage.md: live explicit/retention deletes are repaired by parity purge/rebuild; direct delete wiring remains pending. Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
|
🔎 Preview deployed: https://kody-pr-1127.kody-a99.workers.dev Worker: Mocks:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/worker/src/email/inbound.ts (1)
663-676: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSource all three delivery fields from
storageClaim.delivery.This block reads
messageIdfromclaimedDeliverybut readsdeliveryIdandexpectedFinalizationTokenfromstorageClaim.delivery. Both objects describe the same delivery row today, so behavior is correct. Use the freshest row for all three fields to remove the drift risk ifclaimInboundDeliveryStorageever returns a different stable delivery.♻️ Proposed change
if (storageClaim.delivery?.state === 'received') { await scheduleInboundReceivedTerminalWork({ env, userId, - messageId: claimedDelivery.messageId, + messageId: storageClaim.delivery.messageId, deliveryId: storageClaim.delivery.deliveryId, expectedFinalizationToken: storageClaim.delivery.finalizationToken,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/worker/src/email/inbound.ts` around lines 663 - 676, Update the scheduleInboundReceivedTerminalWork call in the !storageClaim.claimed received-delivery branch to source messageId from storageClaim.delivery.messageId, matching deliveryId and expectedFinalizationToken; stop using claimedDelivery for these fields.packages/worker/src/email/inbound-mailbox.node.test.ts (1)
132-162: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a case where the graph mirror rejects.
This test only covers a graph mirror that resolves with a degraded status (
status: 'timeout'). The coordinator chainsawait mirrorMailboxMessageGraphFromD1(...)beforeprocessInboundDeliveryEffects(...), so a rejecting graph mirror skips the D1 effects entirely and logs once. That branch carries the real risk, because the delivery effects never run. Cover it explicitly.♻️ Suggested additional test
test('graph mirror rejection skips D1 effects and logs once', async () => { resetMocks() consoleError.mockImplementation(() => {}) mocks.mirrorMailboxMessageGraphFromD1.mockRejectedValueOnce( new Error('graph exploded'), ) await scheduleInboundReceivedTerminalWork({ env: { APP_DB: {} } as unknown as Parameters< typeof scheduleInboundReceivedTerminalWork >[0]['env'], userId: 'user-ddd', messageId: 'msg-1', deliveryId: 'delivery-4', logLabel: 'Inbound email effect dispatch failed', }) expect(mocks.processInboundDeliveryEffects).not.toHaveBeenCalled() expect(mocks.mirrorMailboxDeliveryEventFromD1).not.toHaveBeenCalled() expect(consoleError).toHaveBeenCalledTimes(1) })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/worker/src/email/inbound-mailbox.node.test.ts` around lines 132 - 162, Add a separate test alongside the existing terminal-work tests for a rejected mirrorMailboxMessageGraphFromD1 call, configuring it to reject with an error and invoking scheduleInboundReceivedTerminalWork. Assert processInboundDeliveryEffects and mirrorMailboxDeliveryEventFromD1 are not called, and consoleError is called exactly once.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/contributing/architecture/data-storage.md`:
- Around line 810-831: Update the inbound terminals documentation to use
scheduleInboundReceivedTerminalWork and scheduleInboundRejectedTerminalWork as
the coordinator names. Clarify that the received coordinator, after awaiting
processInboundDeliveryEffects, re-mirrors the updated delivery event via
mirrorMailboxDeliveryEventFromD1 rather than attributing this step to the
effects chain.
---
Nitpick comments:
In `@packages/worker/src/email/inbound-mailbox.node.test.ts`:
- Around line 132-162: Add a separate test alongside the existing terminal-work
tests for a rejected mirrorMailboxMessageGraphFromD1 call, configuring it to
reject with an error and invoking scheduleInboundReceivedTerminalWork. Assert
processInboundDeliveryEffects and mirrorMailboxDeliveryEventFromD1 are not
called, and consoleError is called exactly once.
In `@packages/worker/src/email/inbound.ts`:
- Around line 663-676: Update the scheduleInboundReceivedTerminalWork call in
the !storageClaim.claimed received-delivery branch to source messageId from
storageClaim.delivery.messageId, matching deliveryId and
expectedFinalizationToken; stop using claimedDelivery for these fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 734006fa-d4d7-4182-accb-240305d57df0
📒 Files selected for processing (5)
docs/contributing/architecture/data-storage.mdpackages/worker/src/email/inbound-mailbox-mirror.workers.test.tspackages/worker/src/email/inbound-mailbox.node.test.tspackages/worker/src/email/inbound-mailbox.tspackages/worker/src/email/inbound.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Summary
Completes high-risk inbound terminal Mailbox dual-write while preserving D1/R2 authority:
receivedfinalizationsystem:emailremains D1-only; direct/retention deletes remain parity-repairedMailbox failure/timeout never changes reject/refund/retry/charge/finalization/ack behavior. Production-mode captured-
waitUntiltests deliberately delay graph RPCs and prove finalized effects cannot be overwritten.Shipping: high risk by policy; stop green + ready-for-review, do not self-merge.
System recap — extends existing primitives (high operational risk)
Mode: recap · Base:
main@e76b8c9· Head:8397c90Classification: extends — inbound Email Routing composes its finalized D1/R2 boundary with one ordered post-commit Mailbox/effects task; authority does not move.
Invariants
Conductor report
Summary by CodeRabbit
New Features
Documentation