diff --git a/src/table/table.rs b/src/table/table.rs index 3fc0d5ee..0a767fe2 100644 --- a/src/table/table.rs +++ b/src/table/table.rs @@ -293,7 +293,26 @@ impl Table { let span = tracer.start(format!("{} get", F::TABLE_NAME)); let res = self - .get_internal(partition_key, sort_key) + .get_internal(partition_key, sort_key, false) + .bound_record_duration(&self.data.metrics.get_request_duration) + .with_context(Context::current_with_span(span)) + .await?; + + self.data.metrics.get_request_counter.add(1); + + Ok(res) + } + + pub async fn get_monotonic( + self: &Arc, + partition_key: &F::P, + sort_key: &F::S, + ) -> Result, Error> { + let tracer = opentelemetry::global::tracer("garage_table"); + let span = tracer.start(format!("{} get_monotonic", F::TABLE_NAME)); + + let res = self + .get_internal(partition_key, sort_key, true) .bound_record_duration(&self.data.metrics.get_request_duration) .with_context(Context::current_with_span(span)) .await?; @@ -307,6 +326,7 @@ impl Table { self: &Arc, partition_key: &F::P, sort_key: &F::S, + monotonic_read: bool, ) -> Result, Error> { let hash = partition_key.hash(); let who = self.data.replication.read_nodes(&hash)?; @@ -355,14 +375,8 @@ impl Table { } if let Some(ret_entry) = &ret { - if not_all_same { - let self2 = self.clone(); - let ent2 = ret_entry.clone(); - tokio::spawn(async move { - if let Err(e) = self2.repair_on_read(&who[..], ent2).await { - warn!("Error doing repair on read: {}", e); - } - }); + if monotonic_read && not_all_same { + self.repair_on_read(&who, ret_entry.clone()).await?; } } @@ -387,6 +401,36 @@ impl Table { filter, limit, enumeration_order, + false, + ) + .bound_record_duration(&self.data.metrics.get_request_duration) + .with_context(Context::current_with_span(span)) + .await?; + + self.data.metrics.get_request_counter.add(1); + + Ok(res) + } + + pub async fn get_range_monotonic( + self: &Arc, + partition_key: &F::P, + begin_sort_key: Option, + filter: Option, + limit: usize, + enumeration_order: EnumerationOrder, + ) -> Result, Error> { + let tracer = opentelemetry::global::tracer("garage_table"); + let span = tracer.start(format!("{} get_range_monotonic", F::TABLE_NAME)); + + let res = self + .get_range_internal( + partition_key, + begin_sort_key, + filter, + limit, + enumeration_order, + true, ) .bound_record_duration(&self.data.metrics.get_request_duration) .with_context(Context::current_with_span(span)) @@ -404,6 +448,7 @@ impl Table { filter: Option, limit: usize, enumeration_order: EnumerationOrder, + monotonic_read: bool, ) -> Result, Error> { let hash = partition_key.hash(); let who = self.data.replication.read_nodes(&hash)?; @@ -465,19 +510,11 @@ impl Table { } } - if !to_repair.is_empty() { - let self2 = self.clone(); - let to_repair = to_repair - .into_iter() - .map(|k| ret.get(&k).unwrap().clone()) - .collect::>(); - tokio::spawn(async move { - for v in to_repair { - if let Err(e) = self2.repair_on_read(&who[..], v).await { - warn!("Error doing repair on read: {}", e); - } - } - }); + if monotonic_read && !to_repair.is_empty() { + let to_repair = to_repair.into_iter().map(|k| ret.get(&k).unwrap().clone()); + for v in to_repair { + self.repair_on_read(&who, v).await?; + } } // At this point, the `ret` btreemap might contain more than `limit`