feat: native background sync engine for HealthKit#343
Closed
oakleaf wants to merge 1 commit intokingstinct:masterfrom
Closed
feat: native background sync engine for HealthKit#343oakleaf wants to merge 1 commit intokingstinct:masterfrom
oakleaf wants to merge 1 commit intokingstinct:masterfrom
Conversation
Adds `configureBackgroundSync` — a fully-native background sync pipeline that
runs when HealthKit observer queries fire without the JS bridge available
(e.g. after the app has been terminated by iOS).
The library is consumer-agnostic: you provide the HTTP endpoint (url, method,
headers), a list of SyncTypeConfig entries mapping HealthKit identifiers to
your own type names and units, and an UpdateFrequency. Records are sent as
a `{ records: [...] }` JSON body with fields the consumer defined.
Cumulative types (steps, distance, etc.) use HKStatisticsCollectionQuery with
.cumulativeSum — Apple deduplicates across iPhone + Watch and returns one
correct daily total per bucket. Discrete types use HKSampleQuery.
Implementation notes:
- New native file NativeSyncEngine.swift added to the existing companion
ReactNativeHealthkitBackground pod (no NitroModules / C++ deps, safe for
AppDelegate imports on any RN version).
- Setup-time validation: URL well-formedness, HTTP method (POST/PUT/PATCH),
non-empty typeConfigs, JSON encodability. Errors surface at
configureBackgroundSync() call time rather than failing silently on every
background wake.
- 20-second hard timeout per sync event (iOS allows ~30s; 10s buffer for safety).
- No retry / queue on HTTP failure — relies on iOS to fire observers again
on the next HealthKit change.
- Content-Type defaults to application/json when not supplied.
See README "Background Delivery & Native Sync" for comparison with the
existing configureBackgroundTypes observer-only API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: e82a0c6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
Member
|
Love this idea @oakleaf! But would prefer if we exposed all available data, which I don't think is the case here - right? |
Contributor
Author
|
Let me work through that! |
Contributor
Author
|
Superseded by #344 (v2 rewrite with four sample kinds, metadata enrichment, dual-unit hkUnit). |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Adds
configureBackgroundSync— a fully-native background sync pipeline that runs when HealthKit observer queries fire without the JS bridge available (e.g. after the app has been terminated by iOS).The library stays consumer-agnostic: you provide the HTTP endpoint (url, method, headers), a list of
SyncTypeConfigentries mapping HealthKit identifiers to your own type names and units, and anUpdateFrequency. Records are sent as a{ records: [...] }JSON body with fields the consumer defined.Why
configureBackgroundTypes(merged via #341) solves observer registration at AppDelegate time, but the delivery callback queues events until JS subscribes viasubscribeToChanges. For apps that want to forward health data to a backend when the app is terminated, JS never gets a chance to run.configureBackgroundSynccloses that gap by doing the sync entirely in native Swift.How it works
HKStatisticsCollectionQuerywith.cumulativeSum. Apple deduplicates across iPhone + Watch sources and returns one correct total per day.HKSampleQuery, one record per sample.Design choices
ios/NativeSyncEngine.swiftadded to the existing companion podReactNativeHealthkitBackground— no NitroModules / C++ dependencies, safe to import from AppDelegate on any RN version.configureBackgroundSync()call time rather than failing silently on every background wake.New TypeScript surface
configureBackgroundSync(endpoint, typeConfigs, updateFrequency): Promise<boolean>clearBackgroundSync(): Promise<boolean>BackgroundSyncEndpoint/SyncTypeConfigtypesDocs
Added a
## Background Delivery & Native Syncsection to the README with:configureBackgroundTypes(observer + JS callback) andconfigureBackgroundSync(native HTTP)Test plan
🤖 Generated with Claude Code