-
Notifications
You must be signed in to change notification settings - Fork 269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: RoomEvents::reset
really clears the linked chunk
#4321
refactor: RoomEvents::reset
really clears the linked chunk
#4321
Conversation
RoomEvents::reset
really clear the linked chunk
RoomEvents::reset
really clear the linked chunkRoomEvents::reset
really clears the linked chunk
20b61fe
to
64e8114
Compare
64e8114
to
19a86e9
Compare
// An `Update::Clear` happens when `LinkedChunk::clear` is called, which removes | ||
// all chunks, and re-adds one `Chunk` with `FIRST_IDENTIFIER` as its chunk | ||
// identifier. | ||
self.chunks.push_back((ChunkIdentifierGenerator::FIRST_IDENTIFIER, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's the wrong layer to do that, the linked chunk should save that update and propagate it instead; see also #4314 which describes the same issue at construction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sure! Good idea. I'll update this PR to address that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this PR has the correct approach now, but another PR is necessary to fully fix #4314. I'm already on it, but I think it's nice to keep them separate, otherwise the diff will be a bit confusing.
/// [`Update`]: matrix_sdk_base::linked_chunk::Update | ||
#[allow(unused)] // gonna be useful very soon! but we need it now for test purposes | ||
pub fn updates_as_vector_diffs(&mut self) -> Vec<VectorDiff<Event>> { | ||
self.chunks_updates_as_vectordiffs.take() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have to store a chunks_updates_as_vectordiffs
field, and why is not sufficient to expose the underlying method? Now that the underlying linked chunk is properly reset and not re-created, the stream won't close after a reset, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a Stream
:-). If we recreate the AsVector
everytime, it will lose all its states, and the VectorDiff
would be pretty messy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we have to re-create an AsVector
? I'm not sure about that.
Imagine we had:
pub fn as_vector(&self) -> ... {
self.chunks.as_vector()
}
The resulting AsVector
could live as long as the caller wants, and it would always be sync'd with the underlying linked chunk, as long as it lived. In that case, we wouldn't have to store anything new in the linked chunk. Is there any reason we cannot do this?
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4321 +/- ##
==========================================
- Coverage 85.07% 85.06% -0.01%
==========================================
Files 275 275
Lines 30314 30325 +11
==========================================
+ Hits 25789 25797 +8
- Misses 4525 4528 +3 ☔ View full report in Codecov by Sentry. |
19a86e9
to
c6e6705
Compare
This patch fixes a bug in `AsVector`: when an `Update::Clear` value is received, `AsVector`'s internal state must be cleared too, i.e. the `UpdateToVectorDiff::chunks` field should be reset to an initial value! This patch adds a test to ensure this works as expected.
This patch updates `RoomEvents::reset` to not drop the `LinkedChunk` to clear it.
c6e6705
to
149ca7d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still an open question before I approve, but this looks like this is on the right track!
/// All events, all gaps, everything is dropped, move into the void, into | ||
/// the ether, forever. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a blast, are you? :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have no idea!
// SAFETY: The `LinkedChunk` has been built with `new_with_update_history`, so | ||
// `as_vector` must return `Some(…)`. | ||
.expect("`LinkedChunk` must have been constructor with `new_with_update_history`"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid this expect, would it make sense that new_with_update_history()
return the AsVector data structure too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, new_with_update_history()
could return (LinkedChunk, Update)
, but I don't see why it should return an AsVector
directly. Problem is: to compute an AsVector
, it needs an &mut Update
, so the constructor would have to return (LinkedChunk, &mut Update)
, where the &mut
is a mutable reference to LinkedChunk
itself. Er, that's not possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, too bad!
/// [`Update`]: matrix_sdk_base::linked_chunk::Update | ||
#[allow(unused)] // gonna be useful very soon! but we need it now for test purposes | ||
pub fn updates_as_vector_diffs(&mut self) -> Vec<VectorDiff<Event>> { | ||
self.chunks_updates_as_vectordiffs.take() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we have to re-create an AsVector
? I'm not sure about that.
Imagine we had:
pub fn as_vector(&self) -> ... {
self.chunks.as_vector()
}
The resulting AsVector
could live as long as the caller wants, and it would always be sync'd with the underlying linked chunk, as long as it lived. In that case, we wouldn't have to store anything new in the linked chunk. Is there any reason we cannot do this?
First off, we create If we re-create an Also, this I've always seen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this AsVector will be used by RoomEvents to broadcast the VectorDiff to the Timeline via RoomEventCacheInner. So the caller is technically RoomEventCacherInner, which holds a RoomEvents, but I think it's much simpler for RoomEvents to hold AsVector rather than RoomEventCacheInner to fetch a new AsVector every time a RoomEventCacheUpdate must be sent.
Either way, AsVector has to be stored somewhere: either by RoomEventCacheInner or by RoomEvents. I thought it was easier on RoomEvents because it's more confined and easier to test (one less layer).
Thanks, I'm convinced by this 👍
// SAFETY: The `LinkedChunk` has been built with `new_with_update_history`, so | ||
// `as_vector` must return `Some(…)`. | ||
.expect("`LinkedChunk` must have been constructor with `new_with_update_history`"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, too bad!
This PR is twofold:
AsVector
: when anUpdate::Clear
was received, the internal state ofAsVector
wasn't cleared,RoomEvents::reset
to useLinkedChunk::clear
so that events are correctly cleared and not dropped silently, i.e. theUpdate
s andVectorDiff
s are correctly reflecting that. That's important to clear the stores (implementations ofEventCacheStore
, likeMemoryStore
orSqliteStore
). A newRoomEvents::updates_as_vector_diffs()
method is added, it's going to be used later and it's useful to test the new behaviour now.EventCache
storage #3280