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