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