Skip to content

refactor: dedupe microsoft zone resolution and the email dispatch send tail - #4827

Merged
tyler-dane merged 2 commits into
mainfrom
claude/kind-dirac-ct9t0z
Oct 25, 2026
Merged

tyler-dane merged 2 commits into
mainfrom
claude/kind-dirac-ct9t0z

Conversation

@tyler-dane

Copy link
Copy Markdown
Contributor

Fixes #

What and why

A debt sweep over the last 7 days of merged changes. Two duplication clusters grew out of recent fixes; both are behavior-preserving to collapse.

refactor(sync): share microsoft iana zone resolution

The Graph zone fallback (IANA passthrough → Windows display-name lookup → UTC on failure) was copied byte-for-byte into microsoft-event.normalizer.ts and microsoft-cancelled-occurrences.ts as the recurrence-zone fixes landed (#4794, #4797, #4805, #4824). It now lives once in microsoft-timezone.ts, so the next zone rule changes in a single place.

Same commit drops the item.type === "exception" branch in mapRecurrence: it was fully subsumed by the seriesMasterId && originalStart branch immediately below it and returned an identical value.

resolveIanaZone in microsoft-recurrence.ts is deliberately left alone. It throws UnsupportedRecurrenceError on an unknown zone rather than falling back to UTC, so folding it in would turn skipped events into imported ones with a guessed UNTIL. That is a product call, not a refactor.

refactor(backend): share the email dispatch send-and-retry tail

#dispatchBookingHostRow and #dispatchWelcomeRow had each grown their own copy of the same tail: a skip closure, the mid-dispatch stop re-check and isQueued claim guard added by #4788, markSent, the email_sent capture, and a catch block that was byte-identical apart from its log prefix. Both now call #skipRow and #deliverRow, passing only what actually differs: the stop re-check, the provider payload, and the welcome path's preview-loop follow-up. 164 lines removed, 146 added, and the duplicated retry/backoff policy has one home.

One intentional log change: the welcome skip log now carries the same reason field the booking skip log already had.

Verify

VERDICT: FAIL
Selected packages: sync, backend
Checks run: test:sync:fast, type-check, lint, knip
Failed: test:backend:fast

test:sync:fast (897 tests), type-check, lint, and knip all pass. test:backend:fast reports 618 pass / 13 fail, and all 13 are environmental, not this diff:

  • The failing specs are GET /api/config (3) and SSE Server (10). This diff touches neither; it changes only packages/sync/src/providers/microsoft/* and packages/backend/src/email/email-dispatch.service.ts.
  • Stashing the diff and rerunning on the unmodified tree at the same base commit gives the identical result: 618 pass / 13 fail, same 13 spec names.
  • Root cause is the sandbox, not config. /api/config returns 500 and the SSE specs time out waiting for userMetadataChanged; mongodb-memory-server in the same sandbox fails with Failed to listen at ::. Adding compass.yaml (cp compass.example.yaml compass.yaml plus bun dev:ports) does not change the count.

CI decides.


Generated by Claude Code

The Graph zone fallback (IANA passthrough, Windows display-name lookup,
UTC on failure) was copied byte-for-byte into the event normalizer and
the cancelled-occurrences mapper as the recurrence-zone fixes landed.
Move it to one microsoft-timezone module so a future zone rule changes
in a single place.

Also drop the "exception" instance branch in mapRecurrence: it is fully
subsumed by the seriesMasterId branch directly below it and returns the
same shape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AF2JdyXsHsxqEk7KFTEoTn
The booking-host and welcome dispatch paths had each grown their own
copy of the same tail: a skip closure, a mid-dispatch stop re-check, the
isQueued claim guard, markSent, the email_sent capture, and a catch
block that was byte-identical apart from its log prefix.

Collapse both into #skipRow and #deliverRow, with each sequence passing
only what differs: its stop re-check, its provider payload, and the
welcome path's preview-loop follow-up. Behavior is unchanged; the
welcome skip log now carries the same `reason` field the booking one
already logged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AF2JdyXsHsxqEk7KFTEoTn
@tyler-dane
tyler-dane marked this pull request as ready for review October 25, 2026 10:20
@tyler-dane tyler-dane added the agent-automerge Agent-loop finished; merge-guard may squash-merge label Oct 25, 2026 — with Claude
@tyler-dane
tyler-dane enabled auto-merge October 25, 2026 10:21

tyler-dane commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Tech-debt sweep: 2026-10-18 → 2026-10-25

Reviewed the 50 non-merge commits merged in the last 7 days. Two duplication clusters were worth a PR; both are in this one, as separate commits.

Addressed here

Debt Where it came from Commit
toIanaTimeZone duplicated byte-for-byte across two Microsoft modules the recurrence-zone fix series (#4794, #4797, #4805, #4824) ef95167
Dead item.type === "exception" branch in mapRecurrence, subsumed by the branch below it #4805 ef95167
Booking-host and welcome email dispatch each carrying their own copy of the skip closure, stop re-check, isQueued guard, markSent path and an identical catch #4780 added the second path, #4788 then grew both in parallel bc22fd7

Net on the email service: 164 lines removed, 146 added, and the retry/backoff policy now has one home instead of two that have to be kept in step.

Inspected and deliberately left alone

Outcome: merged to main as 605c60b at 10:27 UTC via the merge queue. Every check was green on the head commit, unit-leg (sync) and unit-leg (backend) included, which also confirms the 13 backend failures in the PR body's local verdict were sandbox-only.


Generated by Claude Code

@tyler-dane
tyler-dane added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 605c60b Oct 25, 2026
27 checks passed
@tyler-dane
tyler-dane deleted the claude/kind-dirac-ct9t0z branch October 25, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-automerge Agent-loop finished; merge-guard may squash-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants