Skip to main content

tuwunel_admin/room/
prune_extremities.rs

1use 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}