arminius_lib_sync/syncv4/execute/
persist.rs1use std::collections::{BTreeMap, HashMap};
8
9use arminius_lib_db::{DatabaseError, TransactedDb};
10use arminius_lib_db_sync::syncv4::TransactedSyncV4Queries;
11use arminius_lib_model::syncv4::StreamUpperBound;
12use ruma::OwnedRoomId;
13
14use crate::syncv4::{
15 connect,
16 error::SyncV4Error,
17 execute::{Persisted, fetch},
18 plan,
19};
20
21pub(super) async fn persist(
32 mut transaction: TransactedDb<'_>,
33 plan: plan::SyncV4Plan,
34 fetched: Option<fetch::Fetched>,
35) -> Result<Persisted, SyncV4Error> {
36 let plan::SyncV4Plan { mut connection, updated_state, lists_counts, stale_rooms, .. } = plan;
37 update_stale_rooms(&mut transaction, &connection, stale_rooms).await?;
38
39 let rooms = match fetched {
42 Some(fetch::Fetched { rooms }) => {
43 let new_position = new_position(&mut transaction, &mut connection).await?;
44
45 let new_streams: HashMap<OwnedRoomId, StreamUpperBound> = updated_state
46 .into_iter()
47 .map(|(room_id, state)| (room_id, state.events_stream_upper_bound))
48 .collect();
49 transaction.insert_rooms_events_streams(new_position, new_streams).await?;
50
51 rooms
52 }
53 None => BTreeMap::new(),
54 };
55
56 transaction.commit().await?;
57
58 Ok(Persisted { pos: connection.next_pos_as_string(), lists_counts, rooms })
59}
60
61async fn update_stale_rooms<T: TransactedSyncV4Queries>(
65 transaction: &mut T,
66 connection: &connect::ResolvedConnection,
67 stale_rooms: Vec<OwnedRoomId>,
68) -> Result<(), DatabaseError> {
69 let (Some(prev_position), Some(prev_events_stream_id), false) = (
72 connection.previous_stored_position(),
73 connection.prev_events_stream_id(),
74 stale_rooms.is_empty(),
75 ) else {
76 return Ok(());
77 };
78
79 transaction
80 .update_rooms_events_streams_to_previously(
81 prev_position,
82 stale_rooms,
83 prev_events_stream_id,
84 )
85 .await
86}
87
88async fn new_position<T: TransactedSyncV4Queries>(
94 transaction: &mut T,
95 connection: &mut connect::ResolvedConnection,
96) -> Result<i64, DatabaseError> {
97 let prev_position = connection.previous_stored_position();
98
99 let new_position = transaction
100 .new_syncv4_position(
101 &connection.key.user_id,
102 &connection.key.device_id,
103 connection.key.conn_id.as_deref(),
104 prev_position,
105 )
106 .await?;
107
108 connection.next_token.syncv4_position = new_position;
109
110 Ok(new_position)
111}