Clarify bulk sync impact and prevent duplicate full syncs - #2298
Conversation
Use BullMQ lifecycle deduplication to coalesce only pending initial full-history jobs while allowing later runs and checkpoint continuations.\n\nRefs #2178
Use the canonical mobile story background and retain the extended queued-job type in Redis lifecycle assertions.
Use inverse palette text for accent-filled sync actions and cover the accessible contrast role.
Apply the shared busy-state opacity to the mobile full-history link and cover it alongside disabled semantics.
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews. |
Reviewer's GuideClarifies bulk sync hierarchy and semantics across web and mobile, centralizes shared sync action copy, and introduces BullMQ lifecycle-scoped deduplication for user-triggered full-history sync jobs to prevent duplicate work while preserving checkpoint continuations and exact error reporting. Sequence diagram for full-history bulk sync with BullMQ lifecycle deduplicationsequenceDiagram
actor User
participant WebCtrl as SyncAllControls
participant Panel as DataSourcesPanel
participant SyncRouter as syncRouter.triggerSync
participant Enqueue as enqueueSyncJob
participant RequestDedup as enqueueSyncJobWithRequestDedup
participant Queue as BullMQ Queue.add
User->>WebCtrl: click full-history button
WebCtrl->>Panel: onFullSync()
Panel->>SyncRouter: syncMutation.mutateAsync({ sinceDays: undefined })
SyncRouter->>Enqueue: enqueueSyncJob(providerId, jobData, { singleFlightFullSync: true })
Enqueue->>RequestDedup: enqueueSyncJobWithRequestDedup(providerId, jobData, jobOptionsWithDedup)
RequestDedup->>Queue: addJob("sync", jobData, { deduplication: { id: sync:full:... } })
Queue-->>RequestDedup: job(id = J1)
RequestDedup-->>Panel: EnqueuedSyncJob { id: J1, alreadyQueued: false }
Panel-->>WebCtrl: busy = true
alt duplicate full-history while J1 pending
User->>WebCtrl: click full-history button
WebCtrl->>Panel: onFullSync()
Panel->>SyncRouter: syncMutation.mutateAsync({ sinceDays: undefined })
SyncRouter->>Enqueue: enqueueSyncJob(... singleFlightFullSync: true)
Enqueue->>RequestDedup: enqueueSyncJobWithRequestDedup(... deduplication: { id: sync:full:... })
RequestDedup->>Queue: addJob("sync", jobData, { deduplication: { id: sync:full:... } })
Queue-->>RequestDedup: job(id = J1)
RequestDedup-->>Panel: EnqueuedSyncJob { id: J1, alreadyQueued: true }
end
Note over Queue,RequestDedup: BullMQ lifecycle dedup key released when job J1 completes or fails
File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Review limit reached
Next review available in: 54 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThe PR adds shared recent/full sync action semantics, replaces web and mobile bulk-sync controls with confirmation-based full-history flows, surfaces progress and errors, and enables lifecycle-scoped deduplication for initial user-triggered full-sync jobs. ChangesSync action hierarchy
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant SyncAllControls
participant DataSourcesPanel
participant syncRouter
participant enqueueSyncJob
Operator->>SyncAllControls: Select full-history sync
SyncAllControls->>Operator: Show explanation and confirmation
Operator->>SyncAllControls: Confirm full sync
SyncAllControls->>DataSourcesPanel: Invoke onFullSync
DataSourcesPanel->>syncRouter: Trigger provider syncs
syncRouter->>enqueueSyncJob: Enqueue deduplicated jobs
Assessment against linked issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoMake recent sync primary and dedupe user-triggered full-history bulk syncs
AI Description
Diagram
High-Level Assessment
Files changed (22)
|
Mobile PreviewScan to open on device:
To test on device:
|
|
Storybook previews for This comment updates automatically on each PR push. |
Code Review by Qodo
Context used✅ Compliance rules (platform):
216 rules✅ Skills:
fix-provider, write-tests, cloudflare 1. Full-sync dedup ends early
|
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/superpowers/plans/2026-07-29-sync-action-hierarchy.md`:
- Around line 3-4: Move the agent-specific execution guidance from the plan’s
opening block to the applicable AGENTS.md file. Keep the plan focused on
human-readable scope and task steps, preserving the checkbox tracking format
without agent-only instructions.
In `@packages/mobile/app/providers/index.test.tsx`:
- Around line 129-139: Update the Modal mock in the test setup to invoke the
provided onShow callback after mounting, while continuing to omit it from the
rendered props. Add or update the confirmation-modal test to assert
AccessibilityInfo.setAccessibilityFocus receives the cancel control’s node,
using the existing findNodeHandle and mock symbols.
In `@packages/mobile/app/providers/sync-all-controls.tsx`:
- Around line 29-36: Update the focusCancel callback to remove findNodeHandle
and AccessibilityInfo.setAccessibilityFocus, and invoke
AccessibilityInfo.sendAccessibilityEvent with cancelRef.current and the focus
event. Mark the Cancel TouchableOpacity as accessible={true} so the ref-based
accessibility API targets it correctly.
In `@packages/providers-meta/src/sync-actions.ts`:
- Around line 1-7: Keep the routine sync window canonical by interpolating
ROUTINE_SYNC_DAYS into both recent-action strings in
packages/providers-meta/src/sync-actions.ts (lines 1-7), and update the
corresponding assertions in packages/providers-meta/src/sync-actions.test.ts
(lines 5-10) to use `${ROUTINE_SYNC_DAYS}` instead of hard-coded 7.
In `@src/jobs/sync-request-job.integration.test.ts`:
- Around line 13-19: Update the Redis configuration parsing near the URL
construction to require process.env.REDIS_URL, failing immediately with an
explicit “REDIS_URL is required” error when it is absent; preserve the existing
host, port, password, and retry-option mapping for a provided URL.
- Around line 25-39: Update the afterEach teardown to execute cleanup callbacks
sequentially in reverse registration order instead of using Promise.all.
Preserve the existing cleanup.splice(0) behavior while ensuring each callback,
including worker.close() and queue obliteration/closure registered in
createQueue, completes before the next runs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4ce50f1f-6208-43fc-9897-62f651905145
📒 Files selected for processing (22)
docs/superpowers/plans/2026-07-29-sync-action-hierarchy.mdpackages/mobile/app/providers/index.test.tsxpackages/mobile/app/providers/index.tsxpackages/mobile/app/providers/styles.tspackages/mobile/app/providers/sync-all-controls.stories.tsxpackages/mobile/app/providers/sync-all-controls.test.tsxpackages/mobile/app/providers/sync-all-controls.tsxpackages/providers-meta/package.jsonpackages/providers-meta/src/sync-actions.test.tspackages/providers-meta/src/sync-actions.tspackages/server/src/routers/sync.test.tspackages/server/src/routers/sync.tspackages/web/src/components/DataSourcesPanel.test.tsxpackages/web/src/components/DataSourcesPanel.tsxpackages/web/src/components/SyncAllControls.stories.tsxpackages/web/src/components/SyncAllControls.test.tsxpackages/web/src/components/SyncAllControls.tsxsrc/jobs/enqueue-sync-job.test.tssrc/jobs/enqueue-sync-job.tssrc/jobs/sync-request-job.integration.test.tssrc/jobs/sync-request-job.test.tssrc/jobs/sync-request-job.ts
💤 Files with no reviewable changes (1)
- packages/mobile/app/providers/styles.ts
|
🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews. |
|
Review root-cause note for the full-sync single-flight finding: The finding is valid. The current BullMQ simple-mode key is owned by only the initial job. I have paused implementation under the repository strategy-pivot gate. The proposed replacement is an operation-scoped Redis lease keyed by provider + user, with an owner token propagated through continuations, compare-owner refresh/release, terminal-only release, and bounded expiry for abandoned operations. Required failure tests include enqueue failure after acquire, process crash/lease expiry, stale owner release, continuation enqueue failure, terminal success/failure, and a second request during the continuation chain. |
|
🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews. |
|
🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews. |
|
Fixed the branch-owned web layout regression in b9b2ceb. The provider query initially rendered no bulk controls, then inserted the 76px action stack after resolution and shifted the Data Sources section by 52px. The heading row now reserves the existing 80px spacing token throughout loading, and the delayed-query RTL test resolves two providers to cover the conditional controls. Focused unit tests (19/19), web typecheck, Biome, and diff checks pass. |
|
🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews. |
Summary
Validation
pnpm test:changed(28 files, 839 tests)pnpm test(945 files, 14,613 tests)pnpm tsc --noEmitpnpm storybook:web:buildpnpm storybook:mobile:buildFixes #2178