tuwunel_admin/query/raw/
keys.rs1use 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}