Skip to main content

risingwave_storage/hummock/
error.rs

1// Copyright 2022 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use risingwave_object_store::object::ObjectError;
16use risingwave_pb::id::TableId;
17use thiserror::Error;
18use thiserror_ext::AsReport;
19use tokio::sync::oneshot::error::RecvError;
20
21// TODO(error-handling): should prefer use error types than strings.
22#[derive(Error, thiserror_ext::ReportDebug, thiserror_ext::Arc)]
23#[thiserror_ext(newtype(name = HummockError, backtrace))]
24pub enum HummockErrorInner {
25    #[error("Magic number mismatch: expected {expected}, found: {found}")]
26    MagicMismatch { expected: u32, found: u32 },
27    #[error("Invalid format version: {0}")]
28    InvalidFormatVersion(u32),
29    #[error("Checksum mismatch: expected {expected}, found: {found}")]
30    ChecksumMismatch { expected: u64, found: u64 },
31    #[error("Invalid block")]
32    InvalidBlock,
33    #[error("Encode error: {0}")]
34    EncodeError(String),
35    #[error("Decode error: {0}")]
36    DecodeError(String),
37    #[error("ObjectStore failed with IO error: {0}")]
38    ObjectIoError(
39        #[from]
40        #[backtrace]
41        ObjectError,
42    ),
43    #[error("Meta error: {0}")]
44    MetaError(String),
45    #[error("SharedBuffer error: {0}")]
46    SharedBufferError(String),
47    #[error("Wait epoch error: {0}")]
48    WaitEpoch(String),
49    #[error("Next epoch error: {0}")]
50    NextEpoch(String),
51    #[error("Change log retention miss: table {table_id}, epoch {epoch}")]
52    ChangeLogRetentionMiss { table_id: TableId, epoch: u64 },
53    #[error("Time-travel version expired: table {table_id}, epoch {epoch}")]
54    TimeTravelVersionExpired { table_id: TableId, epoch: u64 },
55    #[error(
56        "Committed epoch mismatch: table {table_id}, committed_epoch {committed_epoch}, read_epoch {read_epoch}"
57    )]
58    CommittedEpochMismatch {
59        table_id: TableId,
60        committed_epoch: u64,
61        read_epoch: u64,
62    },
63    #[error("Barrier read is unavailable for now. Likely the cluster is recovering")]
64    ReadCurrentEpoch,
65    #[error("CompactionExecutor error: {0}")]
66    CompactionExecutor(String),
67    #[error("FileCache error: {0}")]
68    FileCache(String),
69    #[error("SstObjectIdTracker error: {0}")]
70    SstObjectIdTrackerError(String),
71    #[error("CompactionGroup error: {0}")]
72    CompactionGroupError(String),
73    #[error("SstableUpload error: {0}")]
74    SstableUploadError(String),
75    #[error("Read backup error: {0}")]
76    ReadBackupError(String),
77    #[error("Foyer error: {0}")]
78    FoyerError(#[from] foyer::Error),
79    #[error("Other error: {0}")]
80    Other(String),
81}
82
83impl HummockError {
84    pub fn invalid_format_version(v: u32) -> HummockError {
85        HummockErrorInner::InvalidFormatVersion(v).into()
86    }
87
88    pub fn invalid_block() -> HummockError {
89        HummockErrorInner::InvalidBlock.into()
90    }
91
92    pub fn encode_error(error: impl ToString) -> HummockError {
93        HummockErrorInner::EncodeError(error.to_string()).into()
94    }
95
96    pub fn decode_error(error: impl ToString) -> HummockError {
97        HummockErrorInner::DecodeError(error.to_string()).into()
98    }
99
100    pub fn magic_mismatch(expected: u32, found: u32) -> HummockError {
101        HummockErrorInner::MagicMismatch { expected, found }.into()
102    }
103
104    pub fn checksum_mismatch(expected: u64, found: u64) -> HummockError {
105        HummockErrorInner::ChecksumMismatch { expected, found }.into()
106    }
107
108    pub fn meta_error(error: impl ToString) -> HummockError {
109        HummockErrorInner::MetaError(error.to_string()).into()
110    }
111
112    pub fn shared_buffer_error(error: impl ToString) -> HummockError {
113        HummockErrorInner::SharedBufferError(error.to_string()).into()
114    }
115
116    pub fn wait_epoch(error: impl ToString) -> HummockError {
117        HummockErrorInner::WaitEpoch(error.to_string()).into()
118    }
119
120    pub fn next_epoch(error: impl ToString) -> HummockError {
121        HummockErrorInner::NextEpoch(error.to_string()).into()
122    }
123
124    pub fn change_log_retention_miss(table_id: TableId, epoch: u64) -> HummockError {
125        HummockErrorInner::ChangeLogRetentionMiss { table_id, epoch }.into()
126    }
127
128    pub fn time_travel_version_expired(table_id: TableId, epoch: u64) -> HummockError {
129        HummockErrorInner::TimeTravelVersionExpired { table_id, epoch }.into()
130    }
131
132    pub fn committed_epoch_mismatch(
133        table_id: TableId,
134        committed_epoch: u64,
135        read_epoch: u64,
136    ) -> HummockError {
137        HummockErrorInner::CommittedEpochMismatch {
138            table_id,
139            committed_epoch,
140            read_epoch,
141        }
142        .into()
143    }
144
145    pub fn read_current_epoch() -> HummockError {
146        HummockErrorInner::ReadCurrentEpoch.into()
147    }
148
149    pub fn is_meta_error(&self) -> bool {
150        matches!(self.inner(), HummockErrorInner::MetaError(..))
151    }
152
153    pub fn is_object_error(&self) -> bool {
154        matches!(self.inner(), HummockErrorInner::ObjectIoError { .. })
155    }
156
157    pub fn compaction_executor(error: impl ToString) -> HummockError {
158        HummockErrorInner::CompactionExecutor(error.to_string()).into()
159    }
160
161    pub fn sst_object_id_tracker_error(error: impl ToString) -> HummockError {
162        HummockErrorInner::SstObjectIdTrackerError(error.to_string()).into()
163    }
164
165    pub fn compaction_group_error(error: impl ToString) -> HummockError {
166        HummockErrorInner::CompactionGroupError(error.to_string()).into()
167    }
168
169    pub fn file_cache(error: impl ToString) -> HummockError {
170        HummockErrorInner::FileCache(error.to_string()).into()
171    }
172
173    pub fn sstable_upload_error(error: impl ToString) -> HummockError {
174        HummockErrorInner::SstableUploadError(error.to_string()).into()
175    }
176
177    pub fn read_backup_error(error: impl ToString) -> HummockError {
178        HummockErrorInner::ReadBackupError(error.to_string()).into()
179    }
180
181    pub fn foyer_error(error: foyer::Error) -> HummockError {
182        HummockErrorInner::FoyerError(error).into()
183    }
184
185    pub fn other(error: impl ToString) -> HummockError {
186        HummockErrorInner::Other(error.to_string()).into()
187    }
188}
189
190impl From<prost::DecodeError> for HummockError {
191    fn from(error: prost::DecodeError) -> Self {
192        HummockErrorInner::DecodeError(error.to_report_string()).into()
193    }
194}
195
196impl From<RecvError> for HummockError {
197    fn from(error: RecvError) -> Self {
198        ObjectError::from(error).into()
199    }
200}
201
202pub type HummockResult<T> = std::result::Result<T, HummockError>;