tuwunel_service/admin/
context.rs1use std::{fmt, fmt::Debug, time::SystemTime};
2
3use futures::{FutureExt, lock::Mutex};
4use ruma::UserId;
5use tokio::time::Instant;
6use tuwunel_core::{Err, Result};
7
8use crate::Services;
9
10const OUTPUT_MAX_BYTES: usize = 64 * 1024 * 1024;
13
14pub struct Context<'a> {
19 pub services: &'a Services,
20 pub body: &'a [&'a str],
21
22 pub sender: Option<&'a UserId>,
24
25 pub timer: SystemTime,
26 pub output: Mutex<String>,
27}
28
29impl Context<'_> {
30 pub async fn write_timed_query<F, T>(&self, query: F) -> Result
31 where
32 F: Future<Output = T>,
33 T: Debug,
34 {
35 let timer = Instant::now();
36 let result = query.await;
37 let query_time = timer.elapsed();
38
39 self.write_string(format!(
40 "Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"
41 ))
42 .await
43 }
44
45 pub async fn write_timed_query_try<F, T>(&self, query: F) -> Result
46 where
47 F: Future<Output = Result<T>>,
48 T: Debug,
49 {
50 let timer = Instant::now();
51 let result = query.await?;
52 let query_time = timer.elapsed();
53
54 self.write_string(format!(
55 "Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"
56 ))
57 .await
58 }
59
60 pub fn write_fmt(
61 &self,
62 arguments: fmt::Arguments<'_>,
63 ) -> impl Future<Output = Result> + Send + '_ + use<'_> {
64 let buf = format!("{arguments}");
65 self.write_string(buf)
66 }
67
68 #[inline]
69 pub async fn write_string(&self, s: String) -> Result { self.write_str(&s).await }
70
71 pub fn write_str<'a>(&'a self, s: &'a str) -> impl Future<Output = Result> + Send + 'a {
72 self.output.lock().map(move |mut output| {
73 if output.len().saturating_add(s.len()) > OUTPUT_MAX_BYTES {
74 return Err!("Command output exceeded the maximum size and was aborted.");
75 }
76
77 output.push_str(s);
78 Ok(())
79 })
80 }
81}