mz_persist_client/
error.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Errors for the crate
11
12use std::fmt::Debug;
13
14use timely::progress::{Antichain, Timestamp};
15
16use crate::ShardId;
17
18/// An error resulting from invalid usage of the API.
19#[derive(Debug)]
20#[cfg_attr(any(test, debug_assertions), derive(PartialEq))]
21pub enum InvalidUsage<T> {
22    /// Append bounds were invalid
23    InvalidBounds {
24        /// The given lower bound
25        lower: Antichain<T>,
26        /// The given upper bound
27        upper: Antichain<T>,
28    },
29    /// An update was sent at an empty interval of times.
30    InvalidEmptyTimeInterval {
31        /// The given lower bound
32        lower: Antichain<T>,
33        /// The given upper bound
34        upper: Antichain<T>,
35        /// Set of keys containing updates.
36        keys: Vec<String>,
37    },
38    /// Bounds of a [crate::batch::Batch] are not valid for the attempted append call
39    InvalidBatchBounds {
40        /// The lower of the batch
41        batch_lower: Antichain<T>,
42        /// The upper of the batch
43        batch_upper: Antichain<T>,
44        /// The lower bound given to the append call
45        append_lower: Antichain<T>,
46        /// The upper bound given to the append call
47        append_upper: Antichain<T>,
48    },
49    /// An update was not beyond the expected lower of the batch
50    UpdateNotBeyondLower {
51        /// Timestamp of the update
52        ts: T,
53        /// The given lower bound
54        lower: Antichain<T>,
55    },
56    /// An update in the batch was beyond the expected upper
57    UpdateBeyondUpper {
58        /// The timestamp of the update
59        ts: T,
60        /// The expected upper of the batch
61        expected_upper: Antichain<T>,
62    },
63    /// A [crate::batch::Batch] or [crate::fetch::LeasedBatchPart] was
64    /// given to a [crate::write::WriteHandle] from a different shard
65    BatchNotFromThisShard {
66        /// The shard of the batch
67        batch_shard: ShardId,
68        /// The shard of the handle
69        handle_shard: ShardId,
70    },
71    /// Attempted to finalize a shard without advancing frontiers.
72    FinalizationError {
73        /// The current since of the shard.
74        since: Antichain<T>,
75        /// The current upper of the shard.
76        upper: Antichain<T>,
77    },
78    /// The requested codecs don't match the actual ones in durable storage.
79    CodecMismatch(Box<CodecMismatch>),
80    /// An invalid usage of [crate::batch::Batch::rewrite_ts].
81    InvalidRewrite(String),
82}
83
84impl<T: Debug> std::fmt::Display for InvalidUsage<T> {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        match self {
87            InvalidUsage::InvalidBounds { lower, upper } => {
88                write!(f, "invalid bounds [{:?}, {:?})", lower, upper)
89            }
90            InvalidUsage::InvalidEmptyTimeInterval { lower, upper, keys } => {
91                write!(
92                    f,
93                    "invalid empty time interval [{:?}, {:?} {:?})",
94                    lower, upper, keys
95                )
96            }
97            InvalidUsage::InvalidBatchBounds {
98                batch_lower,
99                batch_upper,
100                append_lower,
101                append_upper,
102            } => {
103                write!(
104                    f,
105                    "invalid batch bounds [{:?}, {:?}) for append call with [{:?}, {:?})",
106                    batch_lower, batch_upper, append_lower, append_upper
107                )
108            }
109            InvalidUsage::UpdateNotBeyondLower { ts, lower } => {
110                write!(f, "timestamp {:?} not beyond batch lower {:?}", ts, lower)
111            }
112            InvalidUsage::UpdateBeyondUpper { ts, expected_upper } => write!(
113                f,
114                "timestamp {:?} is beyond the expected batch upper: {:?}",
115                ts, expected_upper
116            ),
117            InvalidUsage::BatchNotFromThisShard {
118                batch_shard,
119                handle_shard,
120            } => write!(f, "batch was from {} not {}", batch_shard, handle_shard),
121            InvalidUsage::FinalizationError { since, upper } => {
122                write!(
123                    f,
124                    "finalized without fully advancing since {since:?} and upper {upper:?}"
125                )
126            }
127            InvalidUsage::CodecMismatch(err) => std::fmt::Display::fmt(err, f),
128            InvalidUsage::InvalidRewrite(err) => write!(f, "invalid rewrite: {err}"),
129        }
130    }
131}
132
133impl<T: Debug> std::error::Error for InvalidUsage<T> {}
134
135/// The requested codecs don't match the actual ones in durable storage.
136#[derive(Debug)]
137#[cfg_attr(any(test, debug_assertions), derive(PartialEq))]
138pub struct CodecMismatch {
139    /// The requested (K, V, T, D) codecs.
140    ///
141    /// The last element in the tuple is Some when the name of the codecs match,
142    /// but the concrete types don't: e.g. mz_repr::Timestamp and u64.
143    pub(crate) requested: (String, String, String, String, Option<CodecConcreteType>),
144    /// The actual (K, V, T, D) codecs in durable storage.
145    ///
146    /// The last element in the tuple is Some when the name of the codecs match,
147    /// but the concrete types don't: e.g. mz_repr::Timestamp and u64.
148    pub(crate) actual: (String, String, String, String, Option<CodecConcreteType>),
149}
150
151impl std::error::Error for CodecMismatch {}
152
153impl std::fmt::Display for CodecMismatch {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        write!(
156            f,
157            "requested codecs {:?} did not match ones in durable storage {:?}",
158            self.requested, self.actual
159        )
160    }
161}
162
163/// The concrete type of a [mz_persist_types::Codec] or
164/// [mz_persist_types::Codec64] impl.
165#[derive(Debug)]
166#[cfg_attr(any(test, debug_assertions), derive(PartialEq))]
167pub struct CodecConcreteType(#[allow(dead_code)] pub(crate) &'static str);
168
169impl<T> From<CodecMismatch> for InvalidUsage<T> {
170    fn from(x: CodecMismatch) -> Self {
171        InvalidUsage::CodecMismatch(Box::new(x))
172    }
173}
174
175impl<T> From<Box<CodecMismatch>> for InvalidUsage<T> {
176    fn from(x: Box<CodecMismatch>) -> Self {
177        InvalidUsage::CodecMismatch(x)
178    }
179}
180
181#[derive(Debug)]
182pub(crate) struct CodecMismatchT {
183    /// The requested T codec.
184    pub(crate) requested: String,
185    /// The actual T codec in durable storage.
186    pub(crate) actual: String,
187}
188
189impl std::error::Error for CodecMismatchT {}
190
191impl std::fmt::Display for CodecMismatchT {
192    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193        write!(
194            f,
195            "requested ts codec {:?} did not match one in durable storage {:?}",
196            self.requested, self.actual
197        )
198    }
199}
200
201/// An error returned from [crate::write::WriteHandle::compare_and_append] (and
202/// variants) when the expected upper didn't match the actual current upper of
203/// the shard.
204#[derive(Debug, PartialEq)]
205pub struct UpperMismatch<T> {
206    /// The expected upper given by the caller.
207    pub expected: Antichain<T>,
208    /// The actual upper of the shard at the time compare_and_append evaluated.
209    pub current: Antichain<T>,
210}
211
212impl<T: Timestamp> std::fmt::Display for UpperMismatch<T> {
213    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
214        write!(
215            f,
216            "expected upper {:?} did not match current upper {:?}",
217            self.expected, self.current,
218        )
219    }
220}