fix(mobile): suppress DOFEK-MOBILE-19 HealthKit background timeouts - #2351
Conversation
Treat transient background fetch timeouts as retryable noise across observer sync, route pushes, and Sentry beforeSend, and lazy-init the HealthKit observer coordinator for safe self capture. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
|
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. |
Reviewer's GuideThis PR centralizes transient HealthKit network timeout detection, suppresses their reporting to Sentry in background sync flows and SDK telemetry, and adjusts iOS observer coordination to safely reference sync-in-progress state while adding targeted tests around the new behavior. Sequence diagram for Sentry beforeSend HealthKit timeout suppressionsequenceDiagram
actor MobileApp
participant SentrySDK as Sentry
participant HealthKitErrors
MobileApp->>SentrySDK: initTelemetry()
SentrySDK->>SentrySDK: init(beforeSend)
MobileApp->>SentrySDK: captureException(error)
SentrySDK->>HealthKitErrors: isBackgroundHealthKitTransientNetworkError(error)
alt error is Error
HealthKitErrors->>HealthKitErrors: isTransientNetworkErrorMessage(error.message)
alt message is timeout
HealthKitErrors-->>SentrySDK: true
else message not timeout
alt error.cause exists
HealthKitErrors->>HealthKitErrors: isBackgroundHealthKitTransientNetworkError(error.cause)
HealthKitErrors-->>SentrySDK: true/false
else no cause
HealthKitErrors-->>SentrySDK: false
end
end
else error not Error
HealthKitErrors->>HealthKitErrors: isTransientNetworkErrorMessage(String(error))
HealthKitErrors-->>SentrySDK: true/false
end
alt isBackgroundHealthKitTransientNetworkError == true
SentrySDK-->>MobileApp: beforeSend returns null (event dropped)
else transient == false
SentrySDK-->>MobileApp: beforeSend returns event (reported)
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Review limit reached
Next review available in: 49 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 (19)
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 |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The error-handling blocks in
syncHealthKitToServerandsyncObserverWorkoutsfor workout routes are now duplicated; consider extracting a shared helper (e.g.,handleWorkoutRouteError) to centralize theisTransientNetworkErrorMessagelogic and avoid repeated message extraction. - The transient timeout detection relies on specific substrings in
isTransientNetworkErrorMessage; if these server messages change frequently, consider tightening the matching (e.g., via more structured error types or regex) to avoid accidentally classifying unrelated errors as transient.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The error-handling blocks in `syncHealthKitToServer` and `syncObserverWorkouts` for workout routes are now duplicated; consider extracting a shared helper (e.g., `handleWorkoutRouteError`) to centralize the `isTransientNetworkErrorMessage` logic and avoid repeated message extraction.
- The transient timeout detection relies on specific substrings in `isTransientNetworkErrorMessage`; if these server messages change frequently, consider tightening the matching (e.g., via more structured error types or regex) to avoid accidentally classifying unrelated errors as transient.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
PR Summary by QodoSuppress transient HealthKit background timeouts in mobile telemetry
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Mobile PreviewScan to open on device:
To test on device:
|
|
Storybook previews for This comment updates automatically on each PR push. |
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Code Review by Qodo
Context used✅ Compliance rules (platform):
171 rules✅ Skills:
fix-provider, write-tests, cloudflare 1.
|
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Use the canonical is-error guard pattern for transient network failures and apply biome formatting needed for CI lint. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Pass fullSync through handleSyncProvider and render the Full sync action on connected provider cards so routine and full-history sync call the correct sinceDays values. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Align infrastructure error test with the rate-limit fetch timeout message introduced for transient provider transport failures. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Use WeeklyReportData and MonthlyReportData in report components, export createReportEmptyState from dofek-server, and update tests and shared-report parsing for the required emptyState field. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Resolve conflicts in HealthKit observer sync, health-report tests, and web report fixtures while keeping createReportEmptyState usage for component-level WeeklyReportCard and MonthlyReportContent types. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Only drop transient network errors in beforeSend when the event is tagged with a HealthKit background sync source, avoiding suppression of unrelated fetch timeouts elsewhere in the app. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Apply biome formatting to telemetry and health-kit-errors files, and pass sinceDays: undefined when handleSyncProvider is called with fullSync. Co-authored-by: Cursor <cursoragent@cursor.com>
|
LGTM! The PR cleanly addresses scoped Sentry timeout filtering for HealthKit background syncs, filters non-actionable transient timeouts before reporting observer sync errors, adds full sync capabilities to provider cards, and refactors report empty states across web and server components. 🤖 Reviewed by codereviewbot.ai - Catch bugs before your team does. |
…edback Initialize observerUpdateCoordinator on module create with lock-guarded access instead of lazy var, and add a test that TRPC timeout wrappers during route push skip captureException via cause-aware detection. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
… match Extract handleWorkoutRouteError for shared query/push error handling in full and observer sync paths, and match transient fetch timeouts with a regex targeting the DOFEK-MOBILE-19 request timed out shape. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Extend the catch telemetry linter to treat handleWorkoutRouteError as a canonical error reporter, and restructure route query catches to throw locked-device errors before delegating to the shared helper. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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. |
Resolve conflicts in HealthKit observer coordinator and report empty-state fixtures by combining lock-guarded coordinator init with main's breadcrumb-only expiration handling and server-owned emptyState in shared reports. Co-authored-by: Cursor <cursoragent@cursor.com>
|
LGTM! Key Changes Reviewed:
🤖 Reviewed by codereviewbot.ai - Catch bugs before your team does. |
Knip flagged report-empty-state-fixtures.ts as unused after stories and tests switched to createReportEmptyState from dofek-server. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 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
beforeSendfilter.TRPCClientErrorcauses and skip reporting when syncresult.errorsare only transient timeouts.Test plan
pnpm exec vitest run packages/mobile/lib/health-kit-errors.test.ts packages/mobile/lib/background-health-kit-sync.test.ts packages/mobile/lib/telemetry.test.ts packages/mobile/lib/health-kit-sync.test.tsMade with Cursor
Summary by Sourcery
Suppress transient HealthKit background timeout errors from Sentry and treat them as non-actionable during mobile sync flows.
Bug Fixes:
Enhancements:
Tests:
Summary by cubic
Suppress transient HealthKit background fetch timeouts (DOFEK-MOBILE-19) by treating them as retryable and filtering them from Sentry only for HealthKit-tagged events. Also restores Full sync on provider cards and moves web reports to server-owned emptyState.
Bug Fixes
@sentry/react-nativebeforeSend to drop transient network errors only for HealthKit sources (bg-healthkit-sync,health-kit-*).sinceDays: undefined.emptyState; usecreateReportEmptyStatefromdofek-server/report-empty-stateand switch toWeeklyReportData/MonthlyReportData.handleWorkoutRouteErroras a canonical reporter.Refactors
report-empty-state-fixtures.tsafter switching to servercreateReportEmptyState.Written for commit 3ebb24c. Summary will update on new commits.