mz_persist/
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//! Persistence related errors.
11
12use std::sync::Arc;
13use std::{error, fmt, io, sync};
14
15use crate::location::{ExternalError, SeqNo};
16
17/// A persistence related error.
18#[derive(Debug, Clone)]
19pub enum Error {
20    /// A persistence related error resulting from an io failure.
21    IO(Arc<io::Error>),
22    /// An operation failed because storage was out of space or quota.
23    OutOfQuota(String),
24    /// An unstructured persistence related error.
25    String(String),
26    /// There is no stream registered under the given name.
27    UnknownRegistration(String),
28    /// The associated write request was sequenced (given a SeqNo) and applied
29    /// to the persist state machine, but that application was deterministically
30    /// made into a no-op because it was contextually invalid (a write or seal
31    /// at a sealed timestamp, an allow_compactions at an unsealed timestamp,
32    /// etc).
33    Noop(SeqNo, String),
34    /// An error returned when a command is sent to a persistence runtime that
35    /// was previously stopped.
36    RuntimeShutdown,
37}
38
39impl error::Error for Error {}
40
41impl fmt::Display for Error {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        match self {
44            Error::IO(e) => fmt::Display::fmt(e, f),
45            Error::OutOfQuota(e) => f.write_str(e),
46            Error::String(e) => f.write_str(e),
47            Error::UnknownRegistration(id) => write!(f, "unknown registration: {}", id),
48            Error::Noop(_, e) => f.write_str(e),
49            Error::RuntimeShutdown => f.write_str("runtime shutdown"),
50        }
51    }
52}
53
54// Hack so we can debug_assert_eq against Result<(), Error>.
55impl PartialEq for Error {
56    fn eq(&self, other: &Self) -> bool {
57        match (self, other) {
58            (Error::String(s), Error::String(o)) => s == o,
59            (Error::OutOfQuota(s), Error::OutOfQuota(o)) => s == o,
60            (Error::UnknownRegistration(s), Error::UnknownRegistration(o)) => s == o,
61            (Error::RuntimeShutdown, Error::RuntimeShutdown) => true,
62            _ => false,
63        }
64    }
65}
66
67impl From<ExternalError> for Error {
68    fn from(e: ExternalError) -> Self {
69        // Print the chain of causes along with each error by default.
70        Error::String(format!("{e:#}"))
71    }
72}
73
74impl From<io::Error> for Error {
75    fn from(e: io::Error) -> Self {
76        // This only works on unix/macos, but I don't see a great alternative.
77        if let Some(28) = e.raw_os_error() {
78            return Error::OutOfQuota(e.to_string());
79        }
80        Error::IO(Arc::new(e))
81    }
82}
83
84impl From<String> for Error {
85    fn from(e: String) -> Self {
86        Error::String(e)
87    }
88}
89
90impl<'a> From<&'a str> for Error {
91    fn from(e: &'a str) -> Self {
92        Error::String(e.into())
93    }
94}
95
96impl From<parquet::errors::ParquetError> for Error {
97    fn from(e: parquet::errors::ParquetError) -> Self {
98        Error::String(e.to_string())
99    }
100}
101
102impl From<arrow::error::ArrowError> for Error {
103    fn from(e: arrow::error::ArrowError) -> Self {
104        Error::String(e.to_string())
105    }
106}
107
108impl<T> From<sync::PoisonError<T>> for Error {
109    fn from(e: sync::PoisonError<T>) -> Self {
110        Error::String(format!("poison: {}", e))
111    }
112}