Files
buzz/mobile/lib
Tom Brow 15c65c76d9 fix(mobile): keep a superseded roster read out of the offline snapshot (#9452)
The channel member list keeps a snapshot of the last roster it read,
which it shows while the relay is disconnected. When two roster updates
arrive close together, the member list starts a read for each. If the
first read answered after the second, it still wrote its older roster
over the snapshot. The live list stayed correct, but once the app went
offline it showed the older roster: for example, a member just removed,
or a bot role just changed, came back.

A read that a later read has replaced no longer writes the snapshot. The
snapshot cache numbers each read of a channel's roster, and only the
latest read for that channel may write. A read that ends because nothing
is watching the list any more (the user leaves the screen mid-read, or a
one-off lookup such as sending a message) still writes, since its roster
is the newest one.

### Validation

New tests, which fail without this change:

- Two roster updates arrive, the second read answers first and the first
answers after it, with a roster, with no roster event, or with an empty
roster. Once disconnected, the member list still shows the newer roster.
- A roster update arrives and the user leaves before its read answers.
Once disconnected, the member list shows that newer roster. (This passes
on main and guards against fencing on disposal, which an earlier version
of this PR did.)

The rest of the channel management tests pass unchanged. Full mobile
test suite and `flutter analyze` pass.

The race itself needs two roster reads to answer out of order and then a
disconnect, which a device run can't reliably produce. An automated run
on an iPhone 12 mini signed in to Block's Builderlab (profile build of
this head) covered the roster paths it touches: cold start, searching
for and opening buzz-mobile, its details (86 members) and its member
list (49 people, roles shown), scrolling it, backgrounding the app for
60 seconds, resuming, and reopening the member list, which loaded the
same roster.

### Regressions

None. A replaced read's result was already discarded for the live list;
now it is also kept out of the offline snapshot. Reads that nothing
replaced write the snapshot as before.

---------

Signed-off-by: Tom Brow <tomb@squareup.com>
Co-authored-by: Tom Brow <tomb@squareup.com>
Co-authored-by: corey <2dafccf60ea6d431a568f6d67fc60016c1b2a51e415e09dc8b213b8e3606cf54@buzz.block.builderlab.xyz>
Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz>
Co-authored-by: perfie <1fc92b08616bef6025a30fa24528ba2417d2a0c82f2c67b62e7f912089235028@buzz.block.builderlab.xyz>
2026-11-13 14:37:45 -08:00
..