Skip to main content

tuwunel_api_client/sync/v3/
mod.rs

1use ruma::{
2	OwnedUserId, RoomId,
3	api::client::sync::sync_events::v3::{State as RoomState, StateEvents},
4};
5use tuwunel_core::{Error, debug_error, err};
6use tuwunel_matrix::pdu::PduEvent;
7use tuwunel_service::rooms::{lazy_loading::Witness, short::ShortStateHash};
8
9pub use self::state::calculate_heroes;
10pub(crate) use self::sync_events::sync_events_route;
11
12mod joined;
13mod left;
14mod state;
15mod sync_events;
16
17#[cfg(test)]
18mod tests;
19
20#[derive(Default)]
21struct StateChanges {
22	heroes: Option<Vec<OwnedUserId>>,
23	joined_member_count: Option<u64>,
24	invited_member_count: Option<u64>,
25	state_events: Vec<PduEvent>,
26
27	/// Witnessed members' current state, lazily loaded for display; never a
28	/// membership change, so the device-list scan leaves them out.
29	lazy_members: Vec<PduEvent>,
30}
31
32struct StateChangeParams<'a> {
33	full_state: bool,
34	state_after: StateAfter,
35	since_shortstatehash: Option<ShortStateHash>,
36	horizon_shortstatehash: Option<ShortStateHash>,
37	after_shortstatehash: Option<ShortStateHash>,
38	current_shortstatehash: ShortStateHash,
39	joined_since_last_sync: bool,
40	witness: Option<&'a Witness>,
41	include_heroes: bool,
42}
43
44/// MSC4222 `state_after` opt-in: which room-state field the response carries.
45#[derive(Clone, Copy, Debug)]
46enum StateAfter {
47	Off,
48	Stable,
49	Unstable,
50}
51
52impl StateAfter {
53	fn requested(self) -> bool { !matches!(self, Self::Off) }
54
55	fn wrap(self, events: StateEvents) -> RoomState {
56		match self {
57			| Self::Off => RoomState::Before(events),
58			| Self::Stable => RoomState::After(events),
59			| Self::Unstable => RoomState::AfterUnstable(events),
60		}
61	}
62}
63
64impl From<(bool, bool)> for StateAfter {
65	fn from((stable, unstable): (bool, bool)) -> Self {
66		// Unstable opt-in wins: such a client reads the unstable field name.
67		match (stable, unstable) {
68			| (_, true) => Self::Unstable,
69			| (true, _) => Self::Stable,
70			| _ => Self::Off,
71		}
72	}
73}
74
75// Keep diagnostic macro expansions under the original tracing target.
76fn log_future_since(since: Option<u64>, next_batch: u64) {
77	debug_error!(?since, next_batch, "received since > next_batch, clamping");
78}
79
80fn missing_room_state(room_id: &RoomId) -> Error {
81	err!(Database(error!("Room {room_id} has no state")))
82}