tuwunel_admin/room/
prune_extremities.rs1use std::borrow::Borrow;
2
3use futures::StreamExt;
4use ruma::OwnedRoomOrAliasId;
5use tuwunel_core::Result;
6use tuwunel_service::rooms::state::{PruneSummary, Trigger};
7
8use crate::admin_command;
9
10#[admin_command]
11#[tracing::instrument(level = "debug", skip(self))]
12pub(super) async fn room_prune_extremities(
13 &self,
14 room_id: OwnedRoomOrAliasId,
15 target: Option<usize>,
16 dry_run: bool,
17) -> Result {
18 let room_id = self
19 .services
20 .alias
21 .maybe_resolve(&room_id)
22 .await?;
23
24 let state_lock = self.services.state.mutex.lock(&room_id).await;
25
26 let mut band = self
27 .services
28 .state
29 .get_forward_extremities(&room_id)
30 .map(ToOwned::to_owned)
31 .collect::<Vec<_>>()
32 .await;
33
34 let config = &self.services.server.config;
35 let target = target
36 .unwrap_or(config.forward_extremities_max)
37 .max(1);
38
39 let goal = band.len().saturating_sub(target);
40
41 let summary = self
42 .services
43 .state
44 .prune_forward_extremities(&room_id, &mut band, goal, Trigger::Admin)
45 .await;
46
47 if !dry_run {
48 self.services
49 .state
50 .set_forward_extremities(&room_id, band.iter().map(Borrow::borrow), &state_lock)
51 .await;
52 }
53
54 let verb = if dry_run { "Would prune" } else { "Pruned" };
55 let PruneSummary {
56 before,
57 after,
58 dangling,
59 referenced,
60 message,
61 state,
62 } = summary;
63
64 let out = format!(
65 "{verb} {room_id}: {before} to {after} forward extremities (swept {dangling} dangling, \
66 {referenced} referenced; dropped {message} message, {state} state)."
67 );
68
69 self.write_str(&out).await
70}