Skip to content

fix(stress): discard results from cancelled screen loads - #2738

Merged
ryanbr merged 1 commit into
ryanbr:mainfrom
UtkuDenizAltiok:codex/stress-load-cancellation
Oct 9, 2026
Merged

ryanbr merged 1 commit into
ryanbr:mainfrom
UtkuDenizAltiok:codex/stress-load-cancellation

Conversation

@UtkuDenizAltiok

@UtkuDenizAltiok UtkuDenizAltiok commented Oct 8, 2026 •

Copy link
Copy Markdown

What this PR does

A cancelled Stress screen refresh can finish after its replacement and overwrite the newer chart or advanced readouts. On Android, runCatching can also turn cancellation into an empty failed-read fallback and publish it.

Check cancellation before and after all seven Apple load phases and Android's stored-series, fingerprint and advanced-lens reads. Propagate Android cancellation while retaining ordinary failed-read fallbacks. Publish the Apple personal-lens flag together with its timeline. Normal values, read limits, task priorities, timeline-before-advanced rendering and layout stay the same. Already-running non-cooperative calculations can still finish; their cancelled result is discarded.

Android's core call is unchanged: #2725 already handles its cancellation as part of the separate retry fix. This PR keeps that work separate.

The existing personal-lens wiring test now checks preference forwarding and selected-mode scoring without depending on the exact assignment text.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • CI / tooling

How it was tested

  • Controlled replay compiles the actual original/fixed Apple load methods and priority helper with gated dependencies. Hold the old load, cancel it, complete a replacement, then release it: original source overwrote fresh state at all seven suspension points; repaired source preserves all seven. The normal control is identical. These are scheduler fixtures, not phone prevalence or physiological-accuracy measurements.
  • Six new Swift/eight Kotlin helper tests cover normal/absent values, phase order, pre-cancellation and late non-cooperative results; Kotlin also covers ordinary failure and cancellation propagation. Every new case was seen to fail with broken helpers, then restored. The adjusted personal-lens guards also fail when the preference is disconnected.
  • Full local verification at 49777b94: 632 store / 2,135 analytics / 327 import tests, all source/i18n/parity checks, 127 governance tests, 2,273 Mac tests and iOS build. One existing import/two Mac skips. Final head only narrows the Kotlin core call and renames a test; all Apple inputs are byte-identical. Final source/package/parity gates rerun at 63e19100.
  • Full Android build and unit tests passed on exact 63e19100, with no warnings in changed Kotlin sources. Existing Swift Sendable warnings match the baseline; no new warnings.
  • Built and ran original/fixed iOS apps on the same synthetic simulator database (7,200 HR and 7,200 R-R rows). Headline, advanced values, intraday/history plots and raw-row digests match. Original simulator state restored. The combined testing update was installed through AltStore on an iPhone with WHOOP 5, and normal Stress appearance was reported. The supplied strap log confirms recent sync/live collection but has no Stress publication diagnostics; it does not show that a cancellation race was triggered on the phone. BLE, storage and analytics are unchanged.

Checklist

  • Swift package tests pass for any package I touched (swift test in Packages/<name>); packages unchanged, reference suites also run
  • Android unit tests pass if I touched android/ (./gradlew testFullDebugUnitTest)
  • No new build warnings introduced
  • UI changes use only StrandDesign tokens — layout/tokens unchanged
  • No hardcoded hex frame bytes; protocol unchanged
  • Follows the conventions in docs/CONTRIBUTING.md
  • I did not commit generated output (Strand.xcodeproj/) or any secrets/keystores

Related issues

Refs #2725 (separate Android core retry/cancellation work).

@UtkuDenizAltiok

Copy link
Copy Markdown
Author

Hi @ryanbr, could you take a look at this when you have time? It stops an older Stress refresh from replacing newer results, so the screen stays consistent while the strap syncs. The calculations and layout stay the same. I’ve installed the update on my iPhone with a WHOOP 5 and Stress looks normal; the before/after tests also reproduce the problem and confirm the fix. All checks are passing.

@ryanbr
ryanbr merged commit 88654a0 into ryanbr:main Oct 9, 2026
6 checks passed
@UtkuDenizAltiok
UtkuDenizAltiok deleted the codex/stress-load-cancellation branch October 9, 2026 09:10
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