aboutsummaryrefslogtreecommitdiffstats
path: root/src/api
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-30 19:13:40 +0100
committertv <tv@krebsco.de>2026-10-30 19:13:40 +0100
commit289b84b09a791b88f039664d71bb644c94de6000 (patch)
tree727ee46dc62409f2b5ca2c31def506034e4f92be /src/api
parent7d3d8031d2301f24b32ee08215a8d004fb81493b (diff)
api: add support for shallow store reads
Diffstat (limited to 'src/api')
-rw-r--r--src/api/store.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/api/store.rs b/src/api/store.rs
index d0fc807..7e8caed 100644
--- a/src/api/store.rs
+++ b/src/api/store.rs
@@ -32,6 +32,10 @@ pub(crate) struct ReadQuery {
/// to base a replacing remake on exactly what was read.
#[serde(default)]
heads: bool,
+ /// What's there, one level deep (`store::read_shallow`), to browse a large store a
+ /// level at a time.
+ #[serde(default)]
+ shallow: bool,
}
#[derive(Debug, Deserialize)]
@@ -54,6 +58,9 @@ pub(crate) async fn get_store_root(
headers: HeaderMap,
Query(query): Query<ReadQuery>,
) -> Result<Response, StatusCode> {
+ if query.shallow {
+ return shallow(&state, Vec::new(), true, &query).await;
+ }
let accept = headers.get(ACCEPT).cloned();
let want_conflicts = query.conflicts;
@@ -91,6 +98,9 @@ pub(crate) async fn get_store_entry(
Query(query): Query<ReadQuery>,
) -> Result<Response, StatusCode> {
let path = parse_key_path(&key)?;
+ if query.shallow {
+ return shallow(&state, path, false, &query).await;
+ }
let accept = headers.get(ACCEPT).cloned();
let want_conflicts = query.conflicts;
@@ -121,6 +131,33 @@ pub(crate) async fn get_store_entry(
mark_source(response, source, heads)
}
+/// `?shallow=true`: what's at `path`, one level deep, as JSON (`store::read_shallow`);
+/// with conflicts asked for too, `400`. `unready_live` as `render_read` has it.
+async fn shallow(
+ state: &AppState,
+ path: Vec<String>,
+ unready_live: bool,
+ query: &ReadQuery,
+) -> Result<Response, StatusCode> {
+ if query.conflicts {
+ return Err(StatusCode::BAD_REQUEST);
+ }
+ let (response, source, heads) = state
+ .render_read(
+ unready_live,
+ query.heads,
+ move |doc| store::read_shallow(doc, &path),
+ move |result| {
+ let value = result
+ .map_err(|e| store_status(e, "Failed to read store path"))?
+ .ok_or(StatusCode::NOT_FOUND)?;
+ response_for_value(&value, None)
+ },
+ )
+ .await?;
+ mark_source(response, source, heads)
+}
+
/// Header on reads served from the pre-rejoin document; its value is that epoch.
const STALE_HEADER: &str = "x-continuum-stale";