1use std::fmt;
13use std::pin::Pin;
14use std::sync::Arc;
15use std::time::Instant;
16
17use anyhow::anyhow;
18use async_trait::async_trait;
19use azure_core::StatusCode;
20use bytes::Bytes;
21use futures_util::Stream;
22use mz_ore::bytes::SegmentedBytes;
23use mz_ore::cast::u64_to_usize;
24use mz_postgres_client::error::PostgresError;
25use mz_proto::RustType;
26use proptest_derive::Arbitrary;
27use serde::{Deserialize, Serialize};
28use tracing::{Instrument, Span};
29
30use crate::error::Error;
31
32#[derive(
46 Arbitrary,
47 Clone,
48 Copy,
49 Debug,
50 PartialOrd,
51 Ord,
52 PartialEq,
53 Eq,
54 Hash,
55 Serialize,
56 Deserialize
57)]
58pub struct SeqNo(pub u64);
59
60impl std::fmt::Display for SeqNo {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(f, "v{}", self.0)
63 }
64}
65
66impl timely::PartialOrder for SeqNo {
67 fn less_equal(&self, other: &Self) -> bool {
68 self <= other
69 }
70}
71
72impl std::str::FromStr for SeqNo {
73 type Err = String;
74
75 fn from_str(encoded: &str) -> Result<Self, Self::Err> {
76 let encoded = match encoded.strip_prefix('v') {
77 Some(x) => x,
78 None => return Err(format!("invalid SeqNo {}: incorrect prefix", encoded)),
79 };
80 let seqno =
81 u64::from_str(encoded).map_err(|err| format!("invalid SeqNo {}: {}", encoded, err))?;
82 Ok(SeqNo(seqno))
83 }
84}
85
86impl SeqNo {
87 pub fn previous(self) -> Option<SeqNo> {
89 Some(SeqNo(self.0.checked_sub(1)?))
90 }
91
92 pub fn next(self) -> SeqNo {
94 SeqNo(self.0 + 1)
95 }
96
97 pub fn minimum() -> Self {
99 SeqNo(0)
100 }
101
102 pub fn maximum() -> Self {
104 SeqNo(u64::MAX)
105 }
106}
107
108impl RustType<u64> for SeqNo {
109 fn into_proto(&self) -> u64 {
110 self.0
111 }
112
113 fn from_proto(proto: u64) -> Result<Self, mz_proto::TryFromProtoError> {
114 Ok(SeqNo(proto))
115 }
116}
117
118#[derive(Debug)]
121pub struct Determinate {
122 inner: anyhow::Error,
123}
124
125impl std::fmt::Display for Determinate {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(f, "determinate: ")?;
128 self.inner.fmt(f)
129 }
130}
131
132impl std::error::Error for Determinate {
133 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
134 self.inner.source()
135 }
136}
137
138impl From<anyhow::Error> for Determinate {
139 fn from(inner: anyhow::Error) -> Self {
140 Self::new(inner)
141 }
142}
143
144impl Determinate {
145 pub fn new(inner: anyhow::Error) -> Self {
149 Determinate { inner }
150 }
151
152 pub fn context<C>(self, context: C) -> Self
154 where
155 C: fmt::Display + Send + Sync + 'static,
156 {
157 Determinate::new(self.inner.context(context))
158 }
159}
160
161#[derive(Debug)]
164pub struct Indeterminate {
165 pub(crate) inner: anyhow::Error,
166}
167
168impl Indeterminate {
169 pub fn new(inner: anyhow::Error) -> Self {
173 Indeterminate { inner }
174 }
175
176 pub fn context<C>(self, context: C) -> Self
178 where
179 C: fmt::Display + Send + Sync + 'static,
180 {
181 Indeterminate::new(self.inner.context(context))
182 }
183}
184
185impl std::fmt::Display for Indeterminate {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(f, "indeterminate: ")?;
188 self.inner.fmt(f)
189 }
190}
191
192impl std::error::Error for Indeterminate {
193 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
194 self.inner.source()
195 }
196}
197
198#[cfg(any(test, debug_assertions))]
200impl PartialEq for Indeterminate {
201 fn eq(&self, other: &Self) -> bool {
202 self.to_string() == other.to_string()
203 }
204}
205
206#[derive(Debug)]
209pub enum ExternalError {
210 Determinate(Determinate),
212 Indeterminate(Indeterminate),
214}
215
216impl ExternalError {
217 #[track_caller]
222 pub fn new_timeout(deadline: Instant) -> Self {
223 ExternalError::Indeterminate(Indeterminate {
224 inner: anyhow!("timeout at {:?}", deadline),
225 })
226 }
227
228 pub fn is_timeout(&self) -> bool {
233 self.to_string().contains("timeout")
235 }
236
237 pub fn context<C>(self, context: C) -> Self
244 where
245 C: fmt::Display + Send + Sync + 'static,
246 {
247 match self {
248 ExternalError::Determinate(e) => ExternalError::Determinate(e.context(context)),
249 ExternalError::Indeterminate(e) => ExternalError::Indeterminate(e.context(context)),
250 }
251 }
252}
253
254impl std::fmt::Display for ExternalError {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 match self {
257 ExternalError::Determinate(x) => std::fmt::Display::fmt(x, f),
258 ExternalError::Indeterminate(x) => std::fmt::Display::fmt(x, f),
259 }
260 }
261}
262
263impl std::error::Error for ExternalError {
264 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
265 match self {
266 ExternalError::Determinate(e) => e.source(),
267 ExternalError::Indeterminate(e) => e.source(),
268 }
269 }
270}
271
272#[cfg(any(test, debug_assertions))]
274impl PartialEq for ExternalError {
275 fn eq(&self, other: &Self) -> bool {
276 self.to_string() == other.to_string()
277 }
278}
279
280impl From<PostgresError> for ExternalError {
281 fn from(x: PostgresError) -> Self {
282 match x {
283 PostgresError::Determinate(e) => ExternalError::Determinate(Determinate::new(e)),
284 PostgresError::Indeterminate(e) => ExternalError::Indeterminate(Indeterminate::new(e)),
285 }
286 }
287}
288
289impl From<Indeterminate> for ExternalError {
290 fn from(x: Indeterminate) -> Self {
291 ExternalError::Indeterminate(x)
292 }
293}
294
295impl From<Determinate> for ExternalError {
296 fn from(x: Determinate) -> Self {
297 ExternalError::Determinate(x)
298 }
299}
300
301impl From<anyhow::Error> for ExternalError {
302 fn from(inner: anyhow::Error) -> Self {
303 ExternalError::Indeterminate(Indeterminate { inner })
304 }
305}
306
307impl From<Error> for ExternalError {
308 fn from(x: Error) -> Self {
309 ExternalError::Indeterminate(Indeterminate {
310 inner: anyhow::Error::new(x),
311 })
312 }
313}
314
315impl From<std::io::Error> for ExternalError {
316 fn from(x: std::io::Error) -> Self {
317 ExternalError::Indeterminate(Indeterminate {
318 inner: anyhow::Error::new(x),
319 })
320 }
321}
322
323impl From<deadpool_postgres::tokio_postgres::Error> for ExternalError {
324 fn from(e: deadpool_postgres::tokio_postgres::Error) -> Self {
325 let code = match e.as_db_error().map(|x| x.code()) {
326 Some(x) => x,
327 None => {
328 return ExternalError::Indeterminate(Indeterminate {
329 inner: anyhow::Error::new(e),
330 });
331 }
332 };
333 match code {
334 &deadpool_postgres::tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE => {
337 ExternalError::Determinate(Determinate {
338 inner: anyhow::Error::new(e),
339 })
340 }
341 _ => ExternalError::Indeterminate(Indeterminate {
342 inner: anyhow::Error::new(e),
343 }),
344 }
345 }
346}
347
348impl From<azure_core::Error> for ExternalError {
349 fn from(value: azure_core::Error) -> Self {
350 let definitely_determinate = if let Some(http) = value.as_http_error() {
351 match http.status() {
352 StatusCode::TooManyRequests => true,
355 _ => false,
356 }
357 } else {
358 false
359 };
360 if definitely_determinate {
361 ExternalError::Determinate(Determinate {
362 inner: anyhow!(value),
363 })
364 } else {
365 ExternalError::Indeterminate(Indeterminate {
366 inner: anyhow!(value),
367 })
368 }
369 }
370}
371
372impl From<deadpool_postgres::PoolError> for ExternalError {
373 fn from(x: deadpool_postgres::PoolError) -> Self {
374 match x {
375 deadpool_postgres::PoolError::Backend(x) => ExternalError::from(x),
378 x => ExternalError::Indeterminate(Indeterminate {
379 inner: anyhow::Error::new(x),
380 }),
381 }
382 }
383}
384
385impl From<tokio::task::JoinError> for ExternalError {
386 fn from(x: tokio::task::JoinError) -> Self {
387 ExternalError::Indeterminate(Indeterminate {
388 inner: anyhow::Error::new(x),
389 })
390 }
391}
392
393#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
396pub struct VersionedData {
397 pub seqno: SeqNo,
399 pub data: Bytes,
401}
402
403#[allow(clippy::as_conversions)]
407pub const SCAN_ALL: usize = u64_to_usize(i64::MAX as u64);
408
409pub const CONSENSUS_HEAD_LIVENESS_KEY: &str = "LIVENESS";
411
412#[derive(Debug, PartialEq, Serialize, Deserialize)]
414pub enum CaSResult {
415 Committed,
417 ExpectationMismatch,
419}
420
421#[derive(Debug)]
425pub struct Tasked<A>(pub Arc<A>);
426
427impl<A> Tasked<A> {
428 fn clone_backing(&self) -> Arc<A> {
429 Arc::clone(&self.0)
430 }
431}
432
433pub type ResultStream<'a, T> = Pin<Box<dyn Stream<Item = Result<T, ExternalError>> + Send + 'a>>;
436
437#[async_trait]
446pub trait Consensus: std::fmt::Debug + Send + Sync {
447 fn list_keys(&self) -> ResultStream<'_, String>;
449
450 async fn head(&self, key: &str) -> Result<Option<VersionedData>, ExternalError>;
453
454 async fn compare_and_set(
459 &self,
460 key: &str,
461 new: VersionedData,
462 ) -> Result<CaSResult, ExternalError>;
463
464 async fn scan(
470 &self,
471 key: &str,
472 from: SeqNo,
473 limit: usize,
474 ) -> Result<Vec<VersionedData>, ExternalError>;
475
476 async fn truncate(&self, key: &str, seqno: SeqNo) -> Result<Option<usize>, ExternalError>;
483}
484
485#[async_trait]
486impl<A: Consensus + 'static> Consensus for Tasked<A> {
487 fn list_keys(&self) -> ResultStream<'_, String> {
488 self.0.list_keys()
494 }
495
496 async fn head(&self, key: &str) -> Result<Option<VersionedData>, ExternalError> {
497 let backing = self.clone_backing();
498 let key = key.to_owned();
499 mz_ore::task::spawn(
500 || "persist::task::head",
501 async move { backing.head(&key).await }.instrument(Span::current()),
502 )
503 .await
504 }
505
506 async fn compare_and_set(
507 &self,
508 key: &str,
509 new: VersionedData,
510 ) -> Result<CaSResult, ExternalError> {
511 let backing = self.clone_backing();
512 let key = key.to_owned();
513 mz_ore::task::spawn(
514 || "persist::task::cas",
515 async move { backing.compare_and_set(&key, new).await }.instrument(Span::current()),
516 )
517 .await
518 }
519
520 async fn scan(
521 &self,
522 key: &str,
523 from: SeqNo,
524 limit: usize,
525 ) -> Result<Vec<VersionedData>, ExternalError> {
526 let backing = self.clone_backing();
527 let key = key.to_owned();
528 mz_ore::task::spawn(
529 || "persist::task::scan",
530 async move { backing.scan(&key, from, limit).await }.instrument(Span::current()),
531 )
532 .await
533 }
534
535 async fn truncate(&self, key: &str, seqno: SeqNo) -> Result<Option<usize>, ExternalError> {
536 let backing = self.clone_backing();
537 let key = key.to_owned();
538 mz_ore::task::spawn(
539 || "persist::task::truncate",
540 async move { backing.truncate(&key, seqno).await }.instrument(Span::current()),
541 )
542 .await
543 }
544}
545
546#[derive(Debug)]
548pub struct BlobMetadata<'a> {
549 pub key: &'a str,
551 pub size_in_bytes: u64,
553}
554
555pub const BLOB_GET_LIVENESS_KEY: &str = "LIVENESS";
557
558#[async_trait]
570pub trait Blob: std::fmt::Debug + Send + Sync {
571 async fn get(&self, key: &str) -> Result<Option<SegmentedBytes>, ExternalError>;
573
574 async fn list_keys_and_metadata(
579 &self,
580 key_prefix: &str,
581 f: &mut (dyn FnMut(BlobMetadata) + Send + Sync),
582 ) -> Result<(), ExternalError>;
583
584 async fn set(&self, key: &str, value: Bytes) -> Result<(), ExternalError>;
589
590 async fn delete(&self, key: &str) -> Result<Option<usize>, ExternalError>;
595
596 async fn restore(&self, key: &str) -> Result<(), ExternalError>;
606}
607
608#[async_trait]
609impl<A: Blob + 'static> Blob for Tasked<A> {
610 async fn get(&self, key: &str) -> Result<Option<SegmentedBytes>, ExternalError> {
611 let backing = self.clone_backing();
612 let key = key.to_owned();
613 mz_ore::task::spawn(
614 || "persist::task::get",
615 async move { backing.get(&key).await }.instrument(Span::current()),
616 )
617 .await
618 }
619
620 async fn list_keys_and_metadata(
625 &self,
626 key_prefix: &str,
627 f: &mut (dyn FnMut(BlobMetadata) + Send + Sync),
628 ) -> Result<(), ExternalError> {
629 self.0.list_keys_and_metadata(key_prefix, f).await
632 }
633
634 async fn set(&self, key: &str, value: Bytes) -> Result<(), ExternalError> {
636 let backing = self.clone_backing();
637 let key = key.to_owned();
638 mz_ore::task::spawn(
639 || "persist::task::set",
640 async move { backing.set(&key, value).await }.instrument(Span::current()),
641 )
642 .await
643 }
644
645 async fn delete(&self, key: &str) -> Result<Option<usize>, ExternalError> {
650 let backing = self.clone_backing();
651 let key = key.to_owned();
652 mz_ore::task::spawn(
653 || "persist::task::delete",
654 async move { backing.delete(&key).await }.instrument(Span::current()),
655 )
656 .await
657 }
658
659 async fn restore(&self, key: &str) -> Result<(), ExternalError> {
660 let backing = self.clone_backing();
661 let key = key.to_owned();
662 mz_ore::task::spawn(
663 || "persist::task::restore",
664 async move { backing.restore(&key).await }.instrument(Span::current()),
665 )
666 .await
667 }
668}
669
670#[cfg(test)]
672pub mod tests {
673 use std::future::Future;
674
675 use anyhow::anyhow;
676 use futures_util::TryStreamExt;
677 use mz_ore::{assert_err, assert_ok};
678 use uuid::Uuid;
679
680 use crate::location::Blob;
681
682 use super::*;
683
684 fn keys(baseline: &[String], new: &[&str]) -> Vec<String> {
685 let mut ret = baseline.to_vec();
686 ret.extend(new.iter().map(|x| x.to_string()));
687 ret.sort();
688 ret
689 }
690
691 async fn get_keys(b: &impl Blob) -> Result<Vec<String>, ExternalError> {
692 let mut keys = vec![];
693 b.list_keys_and_metadata("", &mut |entry| keys.push(entry.key.to_string()))
694 .await?;
695 Ok(keys)
696 }
697
698 async fn get_keys_with_prefix(
699 b: &impl Blob,
700 prefix: &str,
701 ) -> Result<Vec<String>, ExternalError> {
702 let mut keys = vec![];
703 b.list_keys_and_metadata(prefix, &mut |entry| keys.push(entry.key.to_string()))
704 .await?;
705 Ok(keys)
706 }
707
708 pub async fn blob_impl_test<
710 B: Blob,
711 F: Future<Output = Result<B, ExternalError>>,
712 NewFn: Fn(&'static str) -> F,
713 >(
714 new_fn: NewFn,
715 ) -> Result<(), ExternalError> {
716 let values = ["v0".as_bytes().to_vec(), "v1".as_bytes().to_vec()];
717
718 let blob0 = new_fn("path0").await?;
719
720 let _ = new_fn("path1").await?;
722
723 let blob1 = new_fn("path0").await?;
725
726 let k0 = "foo/bar/k0";
727
728 assert_eq!(blob0.get(k0).await?, None);
730 assert_eq!(blob1.get(k0).await?, None);
731
732 let empty_keys = get_keys(&blob0).await?;
734 assert_eq!(empty_keys, Vec::<String>::new());
735 let empty_keys = get_keys(&blob1).await?;
736 assert_eq!(empty_keys, Vec::<String>::new());
737
738 blob0.set(k0, values[0].clone().into()).await?;
740 assert_eq!(
741 blob0.get(k0).await?.map(|s| s.into_contiguous()),
742 Some(values[0].clone())
743 );
744 assert_eq!(
745 blob1.get(k0).await?.map(|s| s.into_contiguous()),
746 Some(values[0].clone())
747 );
748
749 blob0.set("k0a", values[0].clone().into()).await?;
751 assert_eq!(
752 blob0.get("k0a").await?.map(|s| s.into_contiguous()),
753 Some(values[0].clone())
754 );
755 assert_eq!(
756 blob1.get("k0a").await?.map(|s| s.into_contiguous()),
757 Some(values[0].clone())
758 );
759
760 let mut blob_keys = get_keys(&blob0).await?;
762 blob_keys.sort();
763 assert_eq!(blob_keys, keys(&empty_keys, &[k0, "k0a"]));
764 let mut blob_keys = get_keys(&blob1).await?;
765 blob_keys.sort();
766 assert_eq!(blob_keys, keys(&empty_keys, &[k0, "k0a"]));
767
768 blob0.set(k0, values[1].clone().into()).await?;
770 assert_eq!(
771 blob0.get(k0).await?.map(|s| s.into_contiguous()),
772 Some(values[1].clone())
773 );
774 assert_eq!(
775 blob1.get(k0).await?.map(|s| s.into_contiguous()),
776 Some(values[1].clone())
777 );
778 blob0.set("k0a", values[1].clone().into()).await?;
780 assert_eq!(
781 blob0.get("k0a").await?.map(|s| s.into_contiguous()),
782 Some(values[1].clone())
783 );
784 assert_eq!(
785 blob1.get("k0a").await?.map(|s| s.into_contiguous()),
786 Some(values[1].clone())
787 );
788
789 assert_eq!(blob0.delete(k0).await, Ok(Some(2)));
791 assert_eq!(blob0.get(k0).await?, None);
793 assert_eq!(blob1.get(k0).await?, None);
794 assert_eq!(blob0.delete(k0).await, Ok(None));
796 assert_eq!(blob0.delete("nope").await, Ok(None));
798 blob0.set("empty", Bytes::new()).await?;
801 assert_eq!(blob0.delete("empty").await, Ok(Some(0)));
802
803 blob0.set("undelete", Bytes::from("data")).await?;
806 blob0.restore("undelete").await?;
808 assert_eq!(blob0.delete("undelete").await?, Some("data".len()));
809 let expected = match blob0.restore("undelete").await {
810 Ok(()) => Some(Bytes::from("data").into()),
811 Err(ExternalError::Determinate(_)) => None,
812 Err(other) => return Err(other),
813 };
814 assert_eq!(blob0.get("undelete").await?, expected);
815 blob0.delete("undelete").await?;
816
817 blob0.delete("k0a").await?;
819 let mut blob_keys = get_keys(&blob0).await?;
820 blob_keys.sort();
821 assert_eq!(blob_keys, empty_keys);
822 let mut blob_keys = get_keys(&blob1).await?;
823 blob_keys.sort();
824 assert_eq!(blob_keys, empty_keys);
825 blob0.set(k0, values[1].clone().into()).await?;
827 assert_eq!(
828 blob1.get(k0).await?.map(|s| s.into_contiguous()),
829 Some(values[1].clone())
830 );
831 assert_eq!(
832 blob0.get(k0).await?.map(|s| s.into_contiguous()),
833 Some(values[1].clone())
834 );
835
836 let mut expected_keys = empty_keys;
839 for i in 1..=5 {
840 let key = format!("k{}", i);
841 blob0.set(&key, values[0].clone().into()).await?;
842 expected_keys.push(key);
843 }
844
845 let mut blob_keys = get_keys(&blob0).await?;
847 blob_keys.sort();
848 assert_eq!(blob_keys, keys(&expected_keys, &[k0]));
849 let mut blob_keys = get_keys(&blob1).await?;
850 blob_keys.sort();
851 assert_eq!(blob_keys, keys(&expected_keys, &[k0]));
852
853 let mut expected_prefix_keys = vec![];
856 for i in 1..=3 {
857 let key = format!("k-prefix-{}", i);
858 blob0.set(&key, values[0].clone().into()).await?;
859 expected_prefix_keys.push(key);
860 }
861 let mut blob_keys = get_keys_with_prefix(&blob0, "k-prefix").await?;
862 blob_keys.sort();
863 assert_eq!(blob_keys, expected_prefix_keys);
864 let mut blob_keys = get_keys_with_prefix(&blob0, "k").await?;
865 blob_keys.sort();
866 expected_keys.extend(expected_prefix_keys);
867 expected_keys.sort();
868 assert_eq!(blob_keys, expected_keys);
869
870 let blob3 = new_fn("path0").await?;
872 assert_eq!(
873 blob3.get(k0).await?.map(|s| s.into_contiguous()),
874 Some(values[1].clone())
875 );
876
877 Ok(())
878 }
879
880 pub async fn consensus_impl_test<
882 C: Consensus,
883 F: Future<Output = Result<C, ExternalError>>,
884 NewFn: FnMut() -> F,
885 >(
886 mut new_fn: NewFn,
887 ) -> Result<(), ExternalError> {
888 let consensus = new_fn().await?;
889
890 let key = Uuid::new_v4().to_string();
893
894 assert_eq!(consensus.head(&key).await, Ok(None));
896
897 assert_eq!(consensus.scan(&key, SeqNo(0), SCAN_ALL).await, Ok(vec![]));
899
900 assert_err!(consensus.truncate(&key, SeqNo(0)).await);
902
903 let state_at = |v| VersionedData {
904 seqno: SeqNo(v),
905 data: Bytes::from("abc"),
906 };
907
908 assert_eq!(
910 consensus.compare_and_set(&key, state_at(1)).await,
911 Ok(CaSResult::ExpectationMismatch),
912 );
913
914 assert_eq!(
916 consensus.compare_and_set(&key, state_at(0)).await,
917 Ok(CaSResult::Committed),
918 );
919
920 let keys: Vec<_> = consensus.list_keys().try_collect().await?;
922 assert_eq!(keys, vec![key.to_owned()]);
923
924 assert_eq!(consensus.head(&key).await, Ok(Some(state_at(0))));
926
927 assert_eq!(
929 consensus.scan(&key, SeqNo(0), SCAN_ALL).await,
930 Ok(vec![state_at(0)])
931 );
932
933 assert_eq!(
935 consensus.scan(&key, SeqNo(0), SCAN_ALL).await,
936 Ok(vec![state_at(0)])
937 );
938
939 assert_eq!(consensus.scan(&key, SeqNo(1), SCAN_ALL).await, Ok(vec![]));
942
943 assert_ok!(consensus.truncate(&key, SeqNo(0)).await);
946
947 assert_err!(consensus.truncate(&key, SeqNo(1)).await);
949
950 let new_state_at = |v| VersionedData {
951 seqno: SeqNo(v),
952 data: Bytes::from("def"),
953 };
954
955 assert_eq!(
957 consensus.compare_and_set(&key, new_state_at(3)).await,
958 Ok(CaSResult::ExpectationMismatch),
959 );
960
961 assert_eq!(
963 consensus.compare_and_set(&key, new_state_at(0)).await,
964 Ok(CaSResult::ExpectationMismatch),
965 );
966
967 assert_eq!(
969 consensus.compare_and_set(&key, new_state_at(1)).await,
970 Ok(CaSResult::Committed),
971 );
972
973 assert_eq!(consensus.head(&key).await, Ok(Some(new_state_at(1))));
975
976 assert_eq!(
979 consensus.scan(&key, SeqNo(0), SCAN_ALL).await,
980 Ok(vec![state_at(0), new_state_at(1)])
981 );
982
983 assert_eq!(
986 consensus.scan(&key, SeqNo(1), SCAN_ALL).await,
987 Ok(vec![new_state_at(1)])
988 );
989
990 assert_eq!(consensus.scan(&key, SeqNo(2), SCAN_ALL).await, Ok(vec![]));
992
993 assert_eq!(
995 consensus.scan(&key, SeqNo::minimum(), 1).await,
996 Ok(vec![state_at(0)])
997 );
998
999 assert_eq!(
1001 consensus.scan(&key, SeqNo::minimum(), 2).await,
1002 Ok(vec![state_at(0), new_state_at(1)])
1003 );
1004
1005 assert_eq!(
1007 consensus.scan(&key, SeqNo(0), 100).await,
1008 Ok(vec![state_at(0), new_state_at(1)])
1009 );
1010
1011 assert_ok!(consensus.truncate(&key, SeqNo(1)).await);
1013
1014 assert_eq!(
1016 consensus.scan(&key, SeqNo(0), SCAN_ALL).await,
1017 Ok(vec![new_state_at(1)])
1018 );
1019
1020 assert_ok!(consensus.truncate(&key, SeqNo(1)).await);
1023
1024 let other_key = Uuid::new_v4().to_string();
1026
1027 assert_eq!(consensus.head(&other_key).await, Ok(None));
1028
1029 let state = VersionedData {
1030 seqno: SeqNo(0),
1031 data: Bytes::from("einszweidrei"),
1032 };
1033
1034 assert_eq!(
1035 consensus.compare_and_set(&other_key, state.clone()).await,
1036 Ok(CaSResult::Committed),
1037 );
1038
1039 assert_eq!(consensus.head(&other_key).await, Ok(Some(state.clone())));
1040
1041 assert_eq!(consensus.head(&key).await, Ok(Some(new_state_at(1))));
1043
1044 let invalid_jump_forward = VersionedData {
1046 seqno: SeqNo(11),
1047 data: Bytes::from("invalid"),
1048 };
1049 assert_eq!(
1050 consensus.compare_and_set(&key, invalid_jump_forward).await,
1051 Ok(CaSResult::ExpectationMismatch),
1052 );
1053
1054 let large_state = VersionedData {
1056 seqno: SeqNo(2),
1057 data: std::iter::repeat(b'a').take(10240).collect(),
1058 };
1059 assert_eq!(
1060 consensus.compare_and_set(&key, large_state).await,
1061 Ok(CaSResult::Committed),
1062 );
1063
1064 let v3 = VersionedData {
1066 seqno: SeqNo(3),
1067 data: Bytes::new(),
1068 };
1069 assert_eq!(
1070 consensus.compare_and_set(&key, v3).await,
1071 Ok(CaSResult::Committed),
1072 );
1073 assert_ok!(consensus.truncate(&key, SeqNo(3)).await);
1074
1075 Ok(())
1076 }
1077
1078 #[mz_ore::test]
1079 fn timeout_error() {
1080 assert!(ExternalError::new_timeout(Instant::now()).is_timeout());
1081 assert!(!ExternalError::from(anyhow!("foo")).is_timeout());
1082 }
1083}