Skip to content

Google Health sync toggle, auto-reconnect, and incremental sync#6

Merged
isAdamBailey merged 3 commits into
mainfrom
google-health-sync-toggle-and-incremental-sync
Jul 18, 2026
Merged

Google Health sync toggle, auto-reconnect, and incremental sync#6
isAdamBailey merged 3 commits into
mainfrom
google-health-sync-toggle-and-incremental-sync

Conversation

@isAdamBailey

Copy link
Copy Markdown
Owner

Summary

  • Adds a pause/resume toggle for Google Health sync (sync_enabled on google_oauth_credentials, POST /api/google/sync-enabled), auto-reconnect handling when a save is blocked on reauthorization, and incremental sync that pulls only missing weight/height/active-energy data (watermark-based) instead of a full backfill on every run.
  • Fixes a bug found in review: an OAuth access-token refresh mid-sync persisted credentials through the same upsert used for explicit connects, which always sets sync_enabled = true — a token refresh could silently re-enable a sync the user had just paused. Added a dedicated UpdateGoogleOAuthTokens query/UpdateTokens repository method used only for token refresh, which never touches sync_enabled, plus a regression test (TestCredentialsRepository_UpdateTokens_DoesNotResumePausedSync).

Test plan

  • go build ./...
  • go test ./...
  • golangci-lint run ./... — 0 issues
  • npm run test (vitest) — 18 passed
  • npm run lint (eslint) — clean
  • /code-review (8-angle multi-agent review) run against the full diff vs main; the one confirmed correctness bug was fixed and covered by a new test. Remaining findings were efficiency/architecture cleanup (N+1 query patterns during backfill/reconnect, sequential Google API calls, minor TOCTOU in SetSyncEnabled) judged non-critical and out of scope for this change.

🤖 Generated with Claude Code

isAdamBailey and others added 3 commits July 18, 2026 08:51
…ssing data

Sync used to require a manual Disconnect/Connect round trip whenever
Google's refresh token expired, and every sync re-pulled full history.
Now a failed sync during a weight save stashes the entry and redirects
straight to Google's consent screen, resuming the save automatically
once reconnected. Settings gains a pause/resume toggle that keeps the
connection (no re-consent needed to resume), and syncs are bounded to
data missing since the last watermark instead of always fetching
everything — weight/height never overwrite existing days, while
active energy always refreshes today/yesterday since it's the only
Google-only, continuously-accumulating metric.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
persistRefreshedToken reused CredentialsRepository.Save to persist a
refreshed access/refresh token, but Save's upsert always sets
sync_enabled = true (intentional for an explicit connect/reconnect).
A token refresh mid-sync could race a user's pause toggle and flip
sync_enabled back on. Add a dedicated UpdateGoogleOAuthTokens query/
UpdateTokens repository method that updates only the token columns.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Make the toggle the sole Settings control (connect/resume/pause), auto-open OAuth when enabling hits expired credentials, and use the correct snake_case active-energy filter so post-reconnect backfill can update last-sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
@isAdamBailey
isAdamBailey merged commit b498d1d into main Jul 18, 2026
5 checks passed
@isAdamBailey
isAdamBailey deleted the google-health-sync-toggle-and-incremental-sync branch July 18, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant