feat: destructive reconciliation - #1822
Conversation
| const interval = this.ingestPage({ page, isHead: true, setActive: false }); | ||
| if (!interval) return; | ||
|
|
||
| // Re-compute hasMoreTail from the FETCHED PAGE, not the merged interval. The interval's isTail is |
There was a problem hiding this comment.
Do we miss tests for this?
There was a problem hiding this comment.
Not really, why do you have that impression ?
| const { requestedLimit } = options ?? {}; | ||
| const reachedChannelStart = | ||
| typeof requestedLimit === 'number' && | ||
| page.length < Math.min(requestedLimit, DEFAULT_CHANNEL_MESSAGE_LIST_PAGE_SIZE); |
There was a problem hiding this comment.
The hard-coded channel value would be applied to Threads as well? I am wondering whether it is possible to take the configured value on the paginator instance.
There was a problem hiding this comment.
It would and it needs to apply to those as well. The point is not page size (100 is anyway too much for a page size at least for mobile), but rather the maximum BE can return. I'll try resolving this a different way and make sure pagination doesn't break. But in general we need to fetch as many as we can as there is no other way to reconcile updates without ditching the entire list altogether.
CLA
Description of the changes, What, Why and How?
Adds destructive reconciliation of the channel message list. On reconnect/rehydrate, messages that were hard-deleted by anyone while the client was offline are removed from the list, for the channel main list and thread replies, with offline support enabled or disabled.
A hard delete emits no event to other clients, and the newest page merge is additive (it never removes), so a message deleted while you were offline lingers as a ghost forever after reconnect and with offline support on, it also survives in SQLite and returns on cold start.
Reconciliation is folded into the existing newest page merge, so every reseed path (
channel.query, channel list hydrate,channel.reload,Thread.reload,recoverState) reconciles uniformly, without a full reload and without dropping already-loaded older pages. A loaded message that's absent from the authoritative page is pruned; a prefetch snapshot distinguishes a genuine hard-delete from a message that arrived live during the fetch, and local (optimistic/failed/error) messages are always kept. Reconciled ids are mirrored into the offline DB so a cold start doesn't reseed them. I've also added a billion unit tests that should capture this behaviour because it's an incredible pain to test all of the nooks and crannies here.Changelog