fix(sync): Retain overlapping sync positions

This commit is contained in:
Erwan Leboucher
2026-08-29 17:08:01 +00:00
committed by Ellis Git
parent 6919f9681e
commit f92032f6da
2 changed files with 25 additions and 26 deletions
@@ -0,0 +1 @@
Fixed simplified Sliding Sync restarting when overlapping sync responses arrive out of order. Contributed by @eleboucher.
+24 -26
View File
@@ -37,32 +37,18 @@ struct SnakeSyncCache {
subscriptions: BTreeMap<OwnedRoomId, v5::request::RoomSubscription>,
known_rooms: BTreeMap<String, BTreeMap<OwnedRoomId, u64>>,
acknowledged_pos: u64,
pending: Option<PendingSnakeSync>,
pending: BTreeMap<u64, BTreeMap<String, BTreeMap<OwnedRoomId, u64>>>,
extensions: v5::request::Extensions,
}
struct PendingSnakeSync {
pos: u64,
known_rooms: BTreeMap<String, BTreeMap<OwnedRoomId, u64>>,
}
impl SnakeSyncCache {
fn accepts_pos(&self, pos: u64) -> bool {
self.acknowledged_pos == pos
|| self
.pending
.as_ref()
.is_some_and(|pending| pending.pos == pos)
self.acknowledged_pos == pos || self.pending.contains_key(&pos)
}
fn acknowledge(&mut self, pos: u64) {
if self
.pending
.as_ref()
.is_some_and(|pending| pending.pos == pos)
{
let pending = self.pending.take().expect("pending sync checked above");
self.known_rooms = pending.known_rooms;
if let Some(known_rooms) = self.pending.remove(&pos) {
self.known_rooms = known_rooms;
self.acknowledged_pos = pos;
}
}
@@ -308,7 +294,7 @@ pub fn store_snake_sync_pending(
list.insert(room_id, pos);
}
}
cached.pending = Some(PendingSnakeSync { pos, known_rooms: pending_rooms });
cached.pending.insert(pos, pending_rooms);
}
pub fn update_snake_sync_subscriptions(
@@ -425,13 +411,10 @@ async fn subscriber_still_woken_after_a_sibling_disconnects() {
fn pending_rooms_are_committed_only_when_the_response_pos_is_acknowledged() {
let room_id = OwnedRoomId::try_from("!room:example.com").unwrap();
let mut cache = SnakeSyncCache {
pending: Some(PendingSnakeSync {
pos: 42,
known_rooms: BTreeMap::from([(
"list".to_owned(),
BTreeMap::from([(room_id, 42)]),
)]),
}),
pending: BTreeMap::from([(
42,
BTreeMap::from([("list".to_owned(), BTreeMap::from([(room_id, 42)]))]),
)]),
..Default::default()
};
@@ -447,4 +430,19 @@ fn pending_rooms_are_committed_only_when_the_response_pos_is_acknowledged() {
assert_eq!(cache.acknowledged_pos, 42);
assert_eq!(cache.known_rooms["list"].len(), 1);
}
#[test]
fn overlapping_responses_accept_either_response_position() {
let mut cache = SnakeSyncCache {
acknowledged_pos: 100,
pending: BTreeMap::from([(200, BTreeMap::new()), (201, BTreeMap::new())]),
..Default::default()
};
assert!(cache.accepts_pos(200));
assert!(cache.accepts_pos(201));
cache.acknowledge(200);
assert!(cache.accepts_pos(201));
}
}