Wire background-delivered HealthKit updates through to JS#365
Open
the-woody-kim wants to merge 1 commit into
Open
Wire background-delivered HealthKit updates through to JS#365the-woody-kim wants to merge 1 commit into
the-woody-kim wants to merge 1 commit into
Conversation
HKObserverQuery in BackgroundDeliveryManager correctly survives app termination and wakes the process (registered in didFinishLaunchingWithOptions per the docs), but nothing ever connected its callback to a JS-facing subscription — events either dispatched to a global jsCallback that nothing ever registered, or queued in pendingEvents that nothing ever drained. Separately, CoreModule.subscribeToObserverQuery always registered its own independent HKObserverQuery, so even a caller who *did* want to listen for a background-configured type would get a second observer disconnected from BackgroundDeliveryManager's state. Also, the observer's completion handler was signaled before asking iOS for any extended execution time, so even a listening JS callback could get suspended before the JS runtime finished booting on a cold, background-triggered launch. Changes: - BackgroundDeliveryManager: add a per-type callback API (setCallback/removeCallback/isBackgroundConfigured) alongside the existing global one, so a specific type can be subscribed to without touching unrelated types' behavior. Wrap the observer dispatch in beginBackgroundTask/endBackgroundTask, opened before the completion handler fires, for a real execution window. - CoreModule.subscribeToObserverQuery: when a type is already background-configured, route through BackgroundDeliveryManager's per-type API instead of registering a second, independent HKObserverQuery for the same type. unsubscribeQuery mirrors this for cleanup. Types that aren't background-configured are unaffected. Verified on a real device (iOS, Release build, no debugger attached): force-quit the host app, wrote a HealthKit sample from a different source, and confirmed via device console logs that the observer fired, a background task opened, and the JS callback ran while the app was fully terminated. Related: kingstinct#51, kingstinct#341, kingstinct#343, kingstinct#344
|
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
BackgroundDeliveryManager'sHKObserverQuerycorrectly survives app termination and wakes the process (registered indidFinishLaunchingWithOptionsper Apple's recommendations, see #51), but nothing ever connected its callback to a JS-facing subscription:jsCallbackthat nothing in the library ever registered, or queued intopendingEventsthat nothing ever drained.CoreModule.subscribeToObserverQueryalways registered its own independentHKObserverQueryfor a type, so even a caller that did want to listen for a background-configured type ended up with a second, disconnected observer.Net effect: the background-delivery machinery wakes the process and detects the data change, then discards that information — functionally equivalent to not having it. This is the gap #51 → #341 (merged with its "kill app, write data, verify wakes and delivers" test-plan item left unchecked) → #343 (closed) → #344 (open, where the discussion pivots to a native-only, no-JS approach) has been circling.
Changes
BackgroundDeliveryManager: add a per-type callback API (setCallback/removeCallback/isBackgroundConfigured) alongside the existing global one, so a specific type can be subscribed to without touching unrelated types' behavior. Wrap the observer dispatch inbeginBackgroundTask/endBackgroundTask, opened before the completion handler fires, for a real execution window.CoreModule.subscribeToObserverQuery: when a type is already background-configured, route throughBackgroundDeliveryManager's per-type API instead of registering a second, independentHKObserverQueryfor the same type.unsubscribeQuerymirrors this for cleanup. Types that aren't background-configured are unaffected — this only changes behavior for types that already opted into background delivery.This is intentionally scoped to wiring the existing plumbing together rather than the native-only rewrite discussed in #344 — it reuses all the existing JS-side sync logic in consuming apps without duplicating business logic into Swift.
Test plan
Verified on a real device (iOS, Release build, no debugger attached — a debugger changes iOS's suspend/resume behavior):
os_logbreadcrumbs + Apple's own HealthKit/RunningBoard logs) that: the observer fired, a named background task opened, and the JS callback ran and completed a sync — all while the host app was fully terminatedsubscribeToObserverQuery's shared implementationOne clean trial confirmed the mechanism works end-to-end. I haven't yet run a larger multi-trial success-rate test across varied device states (charging/locked/network) — happy to gather that data if useful for review.