From 1d655fda5302b39c03305841c9135645b4a4709d Mon Sep 17 00:00:00 2001 From: Erwan Leboucher Date: Sun, 16 Aug 2026 21:03:27 +0200 Subject: [PATCH] fix(timeline): Keep extremities a local event did not reference --- .../+local-event-extremities.bugfix.md | 1 + src/service/rooms/timeline/build.rs | 21 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 changelog.d/+local-event-extremities.bugfix.md diff --git a/changelog.d/+local-event-extremities.bugfix.md b/changelog.d/+local-event-extremities.bugfix.md new file mode 100644 index 000000000..080052f14 --- /dev/null +++ b/changelog.d/+local-event-extremities.bugfix.md @@ -0,0 +1 @@ +Fixed local events dropping forward extremities they did not reference. Contributed by @eleboucher. diff --git a/src/service/rooms/timeline/build.rs b/src/service/rooms/timeline/build.rs index fcc984cab..989df037f 100644 --- a/src/service/rooms/timeline/build.rs +++ b/src/service/rooms/timeline/build.rs @@ -8,7 +8,7 @@ use conduwuit_core::{ }; use futures::{FutureExt, StreamExt}; use ruma::{ - OwnedEventId, OwnedServerName, RoomId, UserId, + EventId, OwnedEventId, OwnedServerName, RoomId, UserId, events::{ TimelineEventType, room::{ @@ -112,14 +112,27 @@ impl super::Service { let statehashid = self.services.state.append_to_state(&pdu, &room_id).await?; trace!("State hash ID for {room_id}: {statehashid:?}"); + // prev_events is capped at the room version's limit, so this PDU does not + // necessarily reference every extremity. Any it did not reference is still a + // head of the DAG and has to be kept. + let prev_events: HashSet<&EventId> = pdu.prev_events().collect(); + let unreferenced: Vec = self + .services + .state + .get_forward_extremities(&room_id) + .ready_filter(|extremity| !prev_events.contains(&**extremity)) + .collect() + .await; + trace!("Generating raw ID for PDU {}", pdu.event_id()); let pdu_id = self .append_pdu( &pdu, pdu_json, - // Since this PDU references all pdu_leaves we can update the leaves - // of the room - once(pdu.event_id()), + unreferenced + .iter() + .map(AsRef::as_ref) + .chain(once(pdu.event_id())), state_lock, &room_id, )