-
Notifications
You must be signed in to change notification settings - Fork 373
feat(event cache): return relations in their local ordering #5258
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
Conversation
ec3a8cd to
f8321ca
Compare
68d7da4 to
5a55d8b
Compare
f8321ca to
d268712
Compare
e0ca18f to
e04f87b
Compare
d268712 to
70b457b
Compare
Codecov ReportAttention: Patch coverage is
✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## main #5258 +/- ##
==========================================
- Coverage 88.75% 88.74% -0.01%
==========================================
Files 331 331
Lines 89504 89548 +44
Branches 89504 89548 +44
==========================================
+ Hits 79435 79469 +34
- Misses 6260 6268 +8
- Partials 3809 3811 +2 ☔ View full report in Codecov by Sentry. |
poljar
left a comment
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.
Looks good.
| pub fn unordered_linked_chunk_items<'a>( | ||
| &'a self, | ||
| target: LinkedChunkId<'a>, | ||
| target: &OwnedLinkedChunkId, |
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.
It's quite strange to have OwnedLinkedChunkId and LinkedChunkId but also use &OwnedLinkedChunkId.
Why don't we have borrow() implemented to convert from one to the other?
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 don't think I can do this, because the Borrow trait resembles this:
pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}So if I implemented it for OwnedLinkedChunk, then I'd need to return &LinkedChunk<'_>. Unfortunately, it's impossible to construct a temporary LinkedChunk and return a reference to it (since it's dropped at the end of the function's scope). I've added a fake OwnedLinkedChunkId::as_ref() method, but it can't be used for a HashMap<OwnedLinkedChunkId, T> lookup (as the lookups really want &impl Borrow<HashMapKey>). Hence this sub-optimal API.
It's something I would appreciate help with, because I've tried many things when implementing the pair LinkedChunkId / OwnedLinkedChunkId, and couldn't find something that's nice to implement for hashmap lookups.
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.
Yes, for maps you'll need a Borrow. I think the docs on Borrow explain why:
/// In particular `Eq`, `Ord` and `Hash` must be equivalent for
/// borrowed and owned values: `x.borrow() == y.borrow()` should give the
/// same result as `x == y`.
///
/// If generic code merely needs to work for all types that can
/// provide a reference to related type `T`, it is often better to use
/// [`AsRef<T>`] as more types can safely implement it.
So if I implemented it for OwnedLinkedChunk, then I'd need to return &LinkedChunk<'_>. Unfortunately, it's impossible to construct a temporary LinkedChunk and return a reference to it (since it's dropped at the end of the function's scope).
Sadly for borrow you usually need a bit of unsafe, you can transmute from one type to the other, this is probably a minimal example:
use std::collections::HashMap;
use std::borrow::Borrow;
#[derive(PartialEq, Eq, Hash)]
struct Foo(str);
impl From<&str> for &Foo {
fn from(s: &str) -> Self {
unsafe { std::mem::transmute(s) }
}
}
#[derive(PartialEq, Eq, Hash)]
struct OwnedFoo(String);
impl Borrow<Foo> for OwnedFoo {
fn borrow(&self) -> &Foo {
self.0.as_str().into()
}
}
fn main() {
let owned_foo = OwnedFoo("foo".to_owned());
let mut map = HashMap::new();
map.insert(owned_foo, 1);
let foo = <&Foo>::from("foo");
let get = map.get(foo).expect("We should get foo");
println!("Hello {get}")
}You can also take a look at what the Ruma types do using cargo expand -p ruma-common:
For example OwnedRoomId is defined as:
pub struct OwnedRoomId {
inner: Box<RoomId>,
}Which makes a Borrow and AsRef implementation are pretty easy. Though they do require unsafe somewhere:
impl RoomId {
pub(super) const fn from_borrowed(s: &str) -> &Self {
unsafe { std::mem::transmute(s) }
}
}… any linked chunk, only the room one
…de the position of items
…osition in the duplicate set
One must now specify the target linked chunk; both callers would filter out items based on this after the fact, which is a bit overkill since most items would thus be filtered out on the sinking end.
…the relational linked chunk
…MemoryStore::filter_duplicate_events` And remove useless comments.
70b457b to
ade063f
Compare
This makes it so that the relations returned by
RoomEventCache::event_with_relationsare now sorted by their position in the linked chunk, if available (events that can't be located in a linked chunk will be at the front of the array, as they might be "bundled" relations they should be handled in priority).This will make it possible, for a threaded timeline, to retrieve all related edits in a thread, and to correctly order them (if we've seen them in the main linked chunk first).
(In the meantime, we could even use it to include the edit to a latest thread event as the latest event 👀 Will look into that as a separate PR.)
On top of #5225. Part of #4869 / #5122.