From bb596ecc9a822559380d8682d8a10fe45d1fb452 Mon Sep 17 00:00:00 2001 From: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co> Date: Thu, 2 Jul 2026 19:54:34 -0400 Subject: [PATCH] test(desktop): cover the late-island-response downgrade race An ancestor/thread fetch can start while an event is missing, a contiguous history page can fetch that same id unmarked, and the late out-of-band response then merges for an id that is now contiguous. mergeNonContiguousTimelineMessages must treat that as a no-op (it filters incoming ids already in cache before marking), or the frontier that contiguous paging just advanced gets re-poisoned. Pin that invariant with a test. Co-authored-by: Tyler Longwell Signed-off-by: Tyler Longwell --- .../messages/lib/pageOlderMessages.test.mjs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/desktop/src/features/messages/lib/pageOlderMessages.test.mjs b/desktop/src/features/messages/lib/pageOlderMessages.test.mjs index 644d1e0d5..512989568 100644 --- a/desktop/src/features/messages/lib/pageOlderMessages.test.mjs +++ b/desktop/src/features/messages/lib/pageOlderMessages.test.mjs @@ -151,3 +151,30 @@ test("frontier falls back to the oldest cached event when nothing is contiguous" ]); assert.equal(oldestContiguousHistoryTimestamp(healed), 500); }); + +test("late island response never downgrades a contiguous copy (downgrade race)", () => { + const channelId = "island-downgrade-race"; + // The event was missing when the ancestor fetch started, but a contiguous + // history page fetched it (unmarked) before the island response landed. + const contiguousCopy = event({ + id: id("race", 0), + createdAt: 1_000, + channelId, + }); + const cache = mergeTimelineHistoryMessages( + [], + [contiguousCopy, event({ id: id("new", 0), createdAt: 10_000, channelId })], + ); + + // Late ancestor/thread response for the same id must be a no-op — marking + // it here would re-poison the frontier that contiguous paging just fixed. + const merged = mergeNonContiguousTimelineMessages(cache, [ + { ...contiguousCopy }, + ]); + + const kept = merged.find((e) => e.id === contiguousCopy.id); + assert.ok(!kept.nonContiguous, "island merge downgraded a contiguous copy"); + assert.equal(oldestContiguousHistoryTimestamp(merged), 1_000); + // And the reverse direction: thread replies already contiguous stay put. + assert.equal(merged.length, cache.length); +});