Skip to content

fix: deduplicate concurrent sync state requests#969

Draft
ryokun6 wants to merge 1 commit intomainfrom
cursor/sync-state-request-duplicates-bffd
Draft

fix: deduplicate concurrent sync state requests#969
ryokun6 wants to merge 1 commit intomainfrom
cursor/sync-state-request-duplicates-bffd

Conversation

@ryokun6
Copy link
Copy Markdown
Owner

@ryokun6 ryokun6 commented Mar 15, 2026

Problem

Multiple duplicate GET /api/sync/state?domain=... requests are fired concurrently for the same domain. From the server logs, the same domain (e.g. calendar, songs, contacts) was being fetched 3–5 times simultaneously:

08:54:52 → GET /api/sync/state?domain=calendar   ×3
08:54:52 → GET /api/sync/state?domain=songs      ×3
08:54:52 → GET /api/sync/state?domain=contacts   ×3
08:55:05 → GET /api/sync/state?domain=videos     ×5
08:55:05 → GET /api/sync/state?domain=calendar   ×5

Root causes

  1. No in-flight deduplication on fetchRedisStateDomainSnapshot: When the batch check (checkRemoteUpdates), the realtime Pusher handler (handleRealtimeDomainUpdate), and upload pre-merge reads (uploadRedisStateDomain) all request the same domain concurrently, each fires a separate HTTP request.

  2. Rapid-fire requestCloudSyncCheck() from component mounts: Multiple components (Calendar, Stickies, Contacts) call requestCloudSyncCheck() synchronously on mount, each triggering the sync check listener.

Fix

1. In-flight request deduplication for fetchRedisStateDomainSnapshot (cloudSync.ts)

Added a Map<RedisSyncDomain, Promise> that caches in-flight requests. When multiple callers request the same domain concurrently, they share a single HTTP request. The cache is cleared when the request settles (success or error), so subsequent calls get fresh data.

2. Debounce requestCloudSyncCheck() (cloudSyncEvents.ts)

Replaced the synchronous dispatch with a setTimeout(fn, 0) coalescing pattern. All requestCloudSyncCheck() calls within the same event-loop tick are batched into a single listener notification.

Testing

  • bun run build — compiles successfully
  • bun run test:unit — all 89 tests pass
Open in Web Open in Cursor 

Two changes to eliminate redundant GET /api/sync/state?domain=... requests:

1. In-flight request deduplication for fetchRedisStateDomainSnapshot:
   When multiple callers (batch check, realtime handler, upload pre-merge)
   request the same domain concurrently, they now share a single HTTP
   request via a promise cache keyed by domain. The cache is cleared
   when the request settles (success or error).

2. Debounce requestCloudSyncCheck() across component mounts:
   Multiple components (Calendar, Stickies, Contacts) call
   requestCloudSyncCheck() on mount. These synchronous calls are now
   coalesced into a single listener notification using setTimeout(fn, 0).

Co-authored-by: Ryo Lu <me@ryo.lu>
@ryos-deploy
Copy link
Copy Markdown

ryos-deploy bot commented Mar 15, 2026

The preview deployment for ryos-dev is ready. 🟢

Open Preview | Open Build Logs | Open Application Logs

Last updated at: 2026-03-15 09:18:35 CET

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.

2 participants