Clear deferred-medium backlog: single-flight status write + example mounted guards - #34
Clear deferred-medium backlog: single-flight status write + example mounted guards#34fonkamloic wants to merge 2 commits into
Conversation
checkAndInstall's contract is that every false return leaves its reason in CodePush.status. The single-flight early return (a second check while one is already running) was the one false return that wrote nothing, so a losing caller surfacing status after false rendered the in-flight check's foreign progress state as its own result. It now writes 'A check is already running' before returning. The write is transient by design: the in-flight check keeps overwriting status as it progresses, and ValueNotifier notifications are synchronous, so the 'Patch active' edge is always delivered before any overwrite. Adds a regression test in the single-flight group. Fixes #32
The overlay re-keys the app subtree when a patch activates, which disposes the demo State mid-await; a setState landing after that throws in debug builds. Every setState that follows an await in _loadStatus, _manualCheck (including the async onUpdateReady callback and the catch branch), and _rollback (both catch branches) now bails out first when the State is no longer mounted. Pre-await synchronous setState calls need no guard and are unchanged; the early returns skip only UI updates on a disposed State, no side effects are lost. Fixes #33
🔴 CriticalNone. No crash path, no new network/file-I/O surface, and no source- or behaviour-breaking change to the public API ( 🟠 MediumThe new loser write makes the "every Before this PR, nothing outside the in-flight check could write
Those awaits are not short: Concretely: an iOS device is offered a patch whose container header doesn't match. The surgical fix is to move the Worth naming the root cause too: "every 🟡 Low
🟢 Positives
Static review — |
Clears the two open
deferred-mediumissues on this repo. Each was a Medium review finding deferred at merge time under the deferred-medium rule and is now being fixed.Fixes #32 — checkAndInstall's single-flight early return now writes its reason to status
checkAndInstall's documented contract is that everyfalsereturn leaves its reason inCodePush.status. The single-flight early return (a second check arriving while one is in flight) was the onefalsereturn that wrote nothing, so a losing caller that surfacedstatusafterfalserendered the in-flight check's progress state as if it were its own result. It now writes'A check is already running'before returning, which also makes the example's "writes status before every false return" comment accurate (all 18false-return sites verified).The write is safe against the 'Patch active' transition: notifications are synchronous, so that edge is always delivered before any overwrite, and the in-flight check keeps overwriting status as it progresses. A regression test is added in the single-flight group.
Fixes #33 — example guards every setState-after-await with a mounted check
The overlay re-keys the app subtree when a patch activates, which disposes the demo page's State mid-await; a
setStatelanding after that throws in debug builds. EverysetStatethat follows anawaitin_loadStatus,_manualCheck(including the asynconUpdateReadycallback and the catch branch), and_rollback(both catch branches) now returns early when the State is unmounted. Pre-await synchronoussetStatecalls need no guard and are unchanged; the early returns skip only UI updates on a disposed State — no side effects are lost.Checks
flutter analyze: no new issues (6 pre-existingavoid_printinfos inlib/src/code_push.dart; example package clean)flutter test: 153/153 pass, including the new regression test