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::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	let stream = match from.as_ref().or(prefix.as_ref()) {
22		| Some(from) if !backwards => map.raw_keys_from(from).boxed(),
23		| Some(from) => map.rev_raw_keys_from(from).boxed(),
24		| None if !backwards => map.raw_keys().boxed(),
25		| None => map.rev_raw_keys().boxed(),
26	};
27
28	let prefix = prefix.as_ref().map(String::as_bytes);
29
30	stream
31		.ready_try_take_while(|k| {
32			Ok(prefix
33				.map(|prefix| k.starts_with(prefix))
34				.unwrap_or(true))
35		})
36		.take(limit.unwrap_or(usize::MAX))
37		.map_ok(encode)
38		.try_for_each(|str| writeln!(self, "{str}"))
39		.boxed()
40		.await?;
41
42	let query_time = timer.elapsed();
43	write!(self, "\n```\n\nQuery completed in {query_time:?}").await
44}