diff --git a/src/api/k2v/batch.rs b/src/api/k2v/batch.rs index db0f4a80..8a2d1196 100644 --- a/src/api/k2v/batch.rs +++ b/src/api/k2v/batch.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use garage_table::{EnumerationOrder, TableSchema}; use garage_model::k2v::item_table::*; +use garage_model::k2v::rpc::K2VMonotonicRead; use garage_api_common::helpers::*; @@ -68,7 +69,7 @@ pub async fn handle_read_batch( async fn handle_read_batch_query( ctx: &ReqCtx, query: ReadBatchQuery, - monotonic_read: bool, + monotonic_read: K2VMonotonicRead, ) -> Result { let ReqCtx { garage, bucket_id, .. @@ -92,10 +93,11 @@ async fn handle_read_batch_query( .start .as_ref() .ok_or_bad_request("start should be specified if single_item is set")?; - let item = if monotonic_read { - garage.k2v.item_table.get_monotonic(&partition, sk).await? - } else { - garage.k2v.item_table.get(&partition, sk).await? + let item = match monotonic_read { + K2VMonotonicRead::Monotonic => { + garage.k2v.item_table.get_monotonic(&partition, sk).await? + } + K2VMonotonicRead::NonMonotonic => garage.k2v.item_table.get(&partition, sk).await?, } .filter(|e| K2VItemTable::matches_filter(e, &filter)); match item { diff --git a/src/api/k2v/item.rs b/src/api/k2v/item.rs index 7916bbc7..8b5ad453 100644 --- a/src/api/k2v/item.rs +++ b/src/api/k2v/item.rs @@ -5,6 +5,7 @@ use hyper::{Request, Response, StatusCode}; use garage_model::k2v::causality::*; use garage_model::k2v::item_table::*; +use garage_model::k2v::rpc::K2VMonotonicRead; use garage_api_common::helpers::*; @@ -24,19 +25,17 @@ pub(crate) fn parse_causality_token(s: &str) -> Result { CausalContext::parse(s).ok_or(Error::InvalidCausalityToken) } -pub(crate) fn is_monotonic_read(req: &Request) -> Result { +pub(crate) fn is_monotonic_read(req: &Request) -> Result { let v_opt = req .headers() .get(X_GARAGE_NON_MONOTONIC_READ) .map(|s| s.to_str()) .transpose()?; - // The header is set to 'true' if the read may be *non*-monotonic, - // and this function returns if we must do a *monotonic* read; hence - // the boolean negation. match v_opt { - Some("true") => Ok(false), - Some("false") | None => Ok(true), + Some("true") => Ok(K2VMonotonicRead::NonMonotonic), + // Reads are monotonic by default + Some("false") | None => Ok(K2VMonotonicRead::Monotonic), Some(s) => Err(Error::InvalidNonMonotonicRead(s.to_string())), } } @@ -133,14 +132,17 @@ pub async fn handle_read_item( partition_key: partition_key.to_string(), }; - let item = if monotonic_read { - garage - .k2v - .item_table - .get_monotonic(&partition_key, sort_key) - .await? - } else { - garage.k2v.item_table.get(&partition_key, sort_key).await? + let item = match monotonic_read { + K2VMonotonicRead::Monotonic => { + garage + .k2v + .item_table + .get_monotonic(&partition_key, sort_key) + .await? + } + K2VMonotonicRead::NonMonotonic => { + garage.k2v.item_table.get(&partition_key, sort_key).await? + } } .ok_or(Error::NoSuchKey)?; diff --git a/src/model/k2v/rpc.rs b/src/model/k2v/rpc.rs index abdf80ef..09931abd 100644 --- a/src/model/k2v/rpc.rs +++ b/src/model/k2v/rpc.rs @@ -38,6 +38,12 @@ const POLL_RANGE_EXTRA_DELAY: Duration = Duration::from_millis(200); const TIMESTAMP_KEY: &[u8] = b"timestamp"; +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum K2VMonotonicRead { + Monotonic, + NonMonotonic, +} + /// RPC messages for K2V #[derive(Debug, Serialize, Deserialize)] enum K2VRpc { @@ -210,7 +216,7 @@ impl K2VRpcHandler { sort_key: String, causal_context: CausalContext, timeout_msec: u64, - monotonic_read: bool, + monotonic_read: K2VMonotonicRead, ) -> Result, Error> { let poll_key = PollKey { partition: K2VItemPartition { @@ -272,7 +278,7 @@ impl K2VRpcHandler { } if let Some(v) = &resp { - if monotonic_read && not_all_same { + if monotonic_read == K2VMonotonicRead::Monotonic && not_all_same { self.item_table.repair_on_read(&nodes, &[&v]).await?; } } @@ -285,7 +291,7 @@ impl K2VRpcHandler { range: PollRange, seen_str: Option, timeout_msec: u64, - monotonic_read: bool, + monotonic_read: K2VMonotonicRead, ) -> Result, String)>, HelperError> { let has_seen_marker = seen_str.is_some(); @@ -402,7 +408,7 @@ impl K2VRpcHandler { } } - if monotonic_read && !to_repair.is_empty() { + if monotonic_read == K2VMonotonicRead::Monotonic && !to_repair.is_empty() { let to_repair: Vec<_> = to_repair .into_iter() .map(|k| new_items.get(&k).unwrap())