aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake/api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/remake/api.rs')
-rw-r--r--src/remake/api.rs52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/remake/api.rs b/src/remake/api.rs
index a767706..a4d4cf0 100644
--- a/src/remake/api.rs
+++ b/src/remake/api.rs
@@ -119,6 +119,10 @@ pub(crate) struct StartQuery {
settle: Option<Duration>,
#[serde(default, deserialize_with = "crate::units::optional_duration")]
switch_delay: Option<Duration>,
+ /// As JSON (as in the body), e.g. `{"epochs":1,"age":"7d"}`.
+ replay_window: Option<String>,
+ /// As JSON (as in the body).
+ archive_retention: Option<String>,
}
impl StartQuery {
@@ -127,6 +131,8 @@ impl StartQuery {
|| self.base_heads.is_some()
|| self.settle.is_some()
|| self.switch_delay.is_some()
+ || self.replay_window.is_some()
+ || self.archive_retention.is_some()
}
/// An import request for a document uploaded as is.
@@ -136,6 +142,15 @@ impl StartQuery {
Some(rules) => serde_json::from_str(rules)
.map_err(|error| format!("rules are not valid JSON: {error}"))?,
};
+ let retention = |given: &Option<String>, name: &str| {
+ given
+ .as_deref()
+ .map(|given| {
+ serde_json::from_str::<RetentionRequest>(given)
+ .map_err(|error| format!("{name} is not a valid retention: {error}"))
+ })
+ .transpose()
+ };
Ok(StartRequest {
kind: Some("import".to_owned()),
spec: Some(json!({
@@ -151,7 +166,8 @@ impl StartQuery {
}),
settle: self.settle,
switch_delay: self.switch_delay,
- ..StartRequest::default()
+ replay_window: retention(&self.replay_window, "replayWindow")?,
+ archive_retention: retention(&self.archive_retention, "archiveRetention")?,
})
}
}
@@ -344,7 +360,7 @@ async fn start_kind<H: Host>(
} else if query.has_request_fields() {
return error_response(
StatusCode::BAD_REQUEST,
- "rules, baseHeads, settle and switchDelay go in the query only for an application/octet-stream import; put them in the JSON body",
+ "rules, baseHeads, settle, switchDelay, replayWindow and archiveRetention go in the query only for an application/octet-stream import; put them in the JSON body",
None,
);
} else if body.is_empty() {
@@ -997,3 +1013,35 @@ pub(crate) mod testing {
.collect()
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ /// An octet-stream import takes the retentions from the query, as JSON.
+ #[test]
+ fn import_takes_retentions_from_the_query() {
+ let query = StartQuery {
+ replay_window: Some(r#"{"epochs":2,"age":"1h"}"#.to_owned()),
+ archive_retention: Some(r#"{"epochs":3}"#.to_owned()),
+ ..StartQuery::default()
+ };
+ assert!(query.has_request_fields());
+ let request = query.import_request(b"").unwrap();
+ let replay = Retention::from(request.replay_window.unwrap());
+ assert_eq!(replay.epochs, Some(2));
+ assert_eq!(replay.age_ms, Some(3_600_000));
+ let archive = Retention::from(request.archive_retention.unwrap());
+ assert_eq!((archive.epochs, archive.age_ms), (Some(3), None));
+
+ let bad = StartQuery {
+ replay_window: Some(r#"{"days":2}"#.to_owned()),
+ ..StartQuery::default()
+ };
+ assert!(
+ bad.import_request(b"")
+ .unwrap_err()
+ .contains("replayWindow")
+ );
+ }
+}