fix: paginate Google incremental calendar sync - #94
Merged
wahve3 merged 1 commit intoSep 9, 2026
Merged
Conversation
PixelJonas
force-pushed
the
fix/google-incremental-sync-pagination-upstream
branch
2 times, most recently
from
September 9, 2026 10:46
2e0e0ea to
1ffb3f8
Compare
list_events_incremental/1 only fetched page 1 of a syncToken listing and ignored nextPageToken. Google only returns nextSyncToken on the final page, so whenever a delta spanned more than one page, the persisted sync token was never advanced — every subsequent 15-minute sync run re-fetched the exact same stale first page forever, silently dropping every changed event beyond it. Confirmed live: a production integration's incremental sync had returned exactly 250 events (Google's default page size) on every run for hours, with nextPageToken present and nextSyncToken absent on the raw API response — the sync token had been stuck, never advancing. Fix mirrors the pagination loop bootstrap_sync/1 already uses correctly: walk pageToken until exhausted, accumulate events, and only persist the nextSyncToken from the final page. Assisted-by: Claude Code Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>
PixelJonas
force-pushed
the
fix/google-incremental-sync-pagination-upstream
branch
from
September 9, 2026 11:16
1ffb3f8 to
ccc1bd4
Compare
Collaborator
|
Confirmed and reproduced locally: reverting only the pagination loop makes the new multi-page test fail with Thanks for the clear diagnosis and for chasing down the production evidence. Merging now. Two small follow-ups I will take separately: |
PixelJonas
deleted the
fix/google-incremental-sync-pagination-upstream
branch
September 9, 2026 19:03
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
What does this change?
Fixes a pagination bug in
Tymeslot.Integrations.Calendar.Google.CalendarAPI.list_events_incremental/1that caused Google Calendar incremental (delta) syncs to silently drop events and never advance the sync token when a delta response spanned more than one page.Root cause:
list_events_incremental/1only fetched page 1 of asyncTokenlisting and ignorednextPageToken. Google's Calendar API only returnsnextSyncToken(needed to advance the stored sync cursor) on the final page of a multi-page response. Whenever a delta spanned more than 250 events (Google's default page size), the persisted sync token was never advanced, and every subsequent periodic sync run re-fetched the exact same stale first page forever — silently dropping every changed/moved/deleted event beyond page 1.Production evidence: a live integration had returned exactly 250 events on every 15-minute sync run for hours, with
nextPageTokenpresent andnextSyncTokenabsent on the raw API response. After the fix, a single sync fetched 4,465 events (the full accumulated backlog across ~18 pages) and the sync token advanced correctly.Fix: mirrors the pagination loop that
bootstrap_sync/1in the same file already implements correctly — walkspageTokenuntil exhausted, accumulates events, and only persists thenextSyncTokenfrom the final page.Tests: 2 new regression tests (single-page pass-through and multi-page accumulation with correct sync-token extraction from the final page only). Full test suite passes (19/19 in the affected test file, 12243/12246 full suite — 3 pre-existing DST-fuzzing/flaky failures confirmed unrelated).
Checklist
git commit -s(required — CI enforces the DCO; see CONTRIBUTING)mix test), if relevant