Skip to main content

tuwunel_admin/query/raw/
keys.rs

1use futures::{FutureExt, StreamExt, TryStreamExt};
2use tokio::time::Instant;
3use tuwunel_core::{Result, utils::TryReadyExt};
4
5use super::{decode, encode};
6use crate::admin_command;
7
8#[admin_command]
9pub(super) async fn raw_keys(
10	&self,
11	map: String,
12	prefix: Option<String>,
13	limit: Option<usize>,
14	from: Option<String>,
15	backwards: bool,
16) -> Result {
17	writeln!(self, "```").boxed().await?;
18
19	let map = self.services.db.get(map.as_str())?;
20	let timer = Instant::now();
21
22	let prefix = prefix.as_deref().map(decode);
23	let from = from.as_deref().map(decode);
24
25	let stream = match from.as_ref().or(prefix.as_ref()) {
26		| Some(from) if !backwards => map.raw_keys_from(from).boxed(),
27		| Some(from) => map.rev_raw_keys_from(from).boxed(),
28		| None if !backwards => map.raw_keys().boxed(),
29		| None => map.rev_raw_keys().boxed(),
30	};
31
32	stream
33		.ready_try_take_while(|k| {
34			Ok(prefix
35				.as_ref()
36				.map(|prefix| k.starts_with(prefix))
37				.unwrap_or(true))
38		})
39		.take(limit.unwrap_or(usize::MAX))
40		.map_ok(encode)
41		.try_for_each(|str| writeln!(self, "{str}"))
42		.boxed()
43		.await?;
44
45	let query_time = timer.elapsed();
46	write!(self, "\n```\n\nQuery completed in {query_time:?}").await
47}