fix(sync): bootstrap a push channel for an imported calendar that lacks one - #2530
Merged
Merged
Conversation
…ks one The initialImport followup was the only thing that ever opened a channel, and the renewal sweep only renews channels that already exist (its finder filters on subscriptionId). A calendar that reached an imported state by any other route could therefore never become watchable, and nothing in the system could detect or repair that. Production preseeded 938 calendars directly into the store during the Sync cutover. They hold cursors and sync correctly, but bypassed the import job, so they have no push channel and never could. Only 4 of 1786 resources hold one. Everything else rides the reconcile sweep, which at 100 resources per ~10 min cycle refreshes a given calendar roughly every 100 minutes. Enqueue the bootstrap followup after an applied pull when the resource has no channel. Pulls already run for every stale calendar, so this needs no new sweep, no migration, and heals the existing fleet as each calendar comes around. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tyler-dane
added a commit
that referenced
this pull request
Aug 7, 2026
…ing every pull (#2652) A calendar the provider terminally refuses to watch (Google holiday calendars, durable 4xx) reported 'unsupported' and was never recorded as such, so the incremental-pull path re-attempted a watch on every cycle (~1/100min per calendar, forever) - the wart sync-job-dispatch documented after #2530. - sync_resources gains watchUnsupportedAt (nullable, DEFAULTED - a new required field froze the fleet for 23h on 2026-07-31). - maintainSubscription's unsupported outcome now stamps it. - The pull path's channel-bootstrap followup skips resources carrying the marker. - A calendar-list FULL pass clears the connection's markers, giving every unwatchable calendar one fresh attempt per day (the rediscovery sweep forces a daily full pass) instead of one per pull. - A successful watch (updateSubscription) also clears it. listExpiringSubscriptions is untouched: it only selects resources that already hold a channel, which a refused calendar never does. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
Only 4 of 1786 sync resources in production hold a push subscription. Everything else depends entirely on the reconcile sweep, which is what turned a three-document schema bug into a 23-hour fleet-wide outage (#2527).
The cause is a hole in the channel lifecycle:
subscriptionFollowupis enqueued from exactly one place — theinitialImportdispatch branch.listExpiringSubscriptions, filters onsubscriptionId: { $ne: null }. It renews channels that exist; it cannot create one.So a calendar that reaches an imported state by any route other than the
initialImportjob can never become watchable, and nothing detects or repairs it.Production got there by preseeding: the Sync cutover wrote events and cursors straight into the store, bypassing the import job. The data confirms it — 938 resources created 2026-07-26 have a cursor and no subscription, while the only 4 with channels are from the same day via the live connect path.
The practical cost: with ~1000 active resources swept 100 at a time every ~10 minutes, any given calendar is refreshed roughly every 100 minutes. That is the floor on freshness for nearly every user, and it is why the sweep is a single point of failure.
Change
Enqueue the bootstrap followup after an applied incremental pull when the resource has no channel.
Pulls already run for every stale calendar, so this needs no new sweep, no migration, and no operator step — the existing fleet heals as each calendar comes around. The followup uses the same coalescing key as the renewal sweep, so a bootstrap and a renewal can never open two channels.
Known wart, stated plainly
A calendar the provider refuses to watch returns
unsupported, and that verdict is not recorded anywhere. Such a calendar re-attempts one watch per pull (~1 per 100 min at current cadence). Cheap and bounded, but it is a real cost rather than something that self-heals. Recording the verdict would need a new schema field, which is deliberately out of scope here given #2527.Tests
subscriptionMaintainfollowup.750/750 sync tests pass; type-check and lint clean.
🤖 Generated with Claude Code