This patch implements the following wrapper methods (over
`LinkedChunk`): `push_gap`, `replace_gap_at` and `events`. This patch
also implements the `reset` method that clears/drops all chunks in the
`LinkedChunk`.
This adds additional checks for each room updates, and works around a few race conditions, notably one where the server would send a remote echo for a message, but not update the
computed unread_notification_counts immediately. This tends to make the test more stable, in that each response is well known and now properly tested.
It's not worth panic'ing the whole timeline because we removed the wrong item; worst case, users will complain and can send a rageshake that contains all the information that's
needed to debug what went wrong.
There could be situations where we have a day divider, then a read marker, then an event. In that case, when looking at the event, if the previous day divider is wrong and needs
to be removed, we would assume the "previous item" (= the day divider) was at position i-1, which could be that of the read marker, and we'd remove the read marker instead of the
day divider.
Local echoes (which haven't received a remote echo yet) can have no event id, so when computing the report, don't unwrap the event id but use a sensible
default instead.
Also tweaks comments from a previous version of another PR. And rename `DayDividerAdjuster::maybe_adjust_day_dividers` to `run`.
The previous API relied on the callers not forgetting about adjusting day dividers after handling an event.
This makes it statically impossible, by requiring that `TimelineEventHandler` takes a `&mut DayDividerAdjuster` when operating, that it marks as not "consumed". Later, the caller must call `DayDividerAdjuster::maybe_adjust_day_dividers()`, to mark it as consumed. When dropping, we check that it's been consumed, otherwise we panic — as it's a developer error to not call `maybe_adjust_day_dividers()`.
Notably, split the code into smaller functions, and revamp the high-level signatures so the individual handle_ functions don't take a bazillion arguments.
The reports now include the final state as well as the set of operations to run, so we can really debug all the steps just from looking at a rageshake.
When we're removing or inserting any day divider, we're also updating the offset, so that subsequent operations happen at the right positions.
The previous code made the error to clamp the offset when assigning it, instead of letting it be "out of bounds" and clamping the uses, which is
the correct way to implement this.
This patch renames `ChunkIdentifierGenerator::generate_next` to `next.
This patch also simplifies a `.saturating_add(1)` to a simple `+ 1`,
which is fine because we have checked for overflow just before.
`TryFrom` and `TryInto` are imported redundantly. They are already
defined in `core::prelude::rust_2021` which is automatically imported.
This is generating warnings on my side. This patch fixes that.
This patch makes `ChunkIdentifierGenerator::generate_next` to panic
if there is no more identifiers available. It was previously returning
a `Result` but we were doing nothing with this `Result` except
`unwrap`ping it. To simplify the API: let's panic.
As suggested in https://github.com/matrix-org/matrix-rust-sdk/
pull/3251#discussion_r1532103818 by Poljar, it is possible that the
value of the atomic changes between the `fetch_add` and the `load` (if
and only if it is used in a concurrency model, which is not the case
right now, but anyway… better being correct now!). The idea is not
`load` but repeat the addition manually to compute the “current” value.
Imagine we have this linked chunk:
```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] ['d', 'e', 'f']);
```
Before the patch, when we were running:
```rust
let position_of_d = linked_chunk.item_position(|item| *item == 'd').unwrap();
linked_chunk.insert_gap_at((), position_of_d)?;
```
it was taking `['d', 'e', 'f']` to split it at index 0, so `[]` + `['d',
'e', 'f']`, and then was inserting a gap in between, thus resulting
into:
```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [] [-] ['d', 'e', 'f']);
```
The problem is that it creates a useless empty chunk. It's a waste of
space, and rapidly, of computation. When used with `EventCache`, this
problem occurs every time a backpagination occurs (because it executes
a `replace_gap_at` to insert the new item, and then executes a
`insert_gap_at` if the backpagination contains another `prev_batch`
token).
With this patch, the result of the operation is now:
```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [-] ['d', 'e', 'f']);
```
The `assert_items_eq!` macro has been updated to be able to assert
empty chunks. The `test_insert_gap_at` has been updated to test all
edge cases.