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
//! Error types for segment-buffer.
//!
//! Errors carry the context an operator needs to diagnose a failure at 3am:
//! the path to the offending segment file, the phase that failed, and the
//! underlying cause. Use [`Result`](crate::Result) as the alias.
//!
//! # Matching on a failure to recover the offending path
//!
//! Every non-I/O variant carries the segment file's [`PathBuf`](std::path::PathBuf),
//! so an operator can match on the variant and act (move the bad file aside,
//! alert, etc.) without parsing the rendered message:
//!
//! ```
//! use segment_buffer::{SegmentBuffer, SegmentConfig, SegmentError};
//! use tempfile::tempdir;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let dir = tempdir()?;
//! let buf: SegmentBuffer<u64> =
//! SegmentBuffer::open(dir.path(), SegmentConfig::default())?;
//!
//! // Drop a corrupt segment so the next read surfaces a typed error.
//! std::fs::write(
//! dir.path().join("seg_000000000000_000000000000.zst"),
//! b"this is not zstd+CBOR",
//! )?;
//!
//! match buf.read_from(0, 10) {
//! Ok(_) => { /* happy path */ }
//! Err(SegmentError::Cbor { path, phase, .. }) => {
//! eprintln!(
//! "CBOR {phase} failed on {}; quarantining",
//! path.display()
//! );
//! let quarantined = format!("{}.quarantined", path.display());
//! let _ = std::fs::rename(&path, quarantined);
//! }
//! Err(SegmentError::Cipher { path, .. }) => {
//! eprintln!("cipher failure on {} — likely wrong key", path.display());
//! }
//! Err(SegmentError::Integrity { path, reason }) => {
//! eprintln!("integrity failure on {}: {reason}", path.display());
//! }
//! Err(SegmentError::Io(e)) => {
//! eprintln!("unrelated I/O failure: {e}");
//! }
//! // `SegmentError` is `#[non_exhaustive]`, so a catch-all is required
//! // for forward compatibility with future variants.
//! Err(other) => {
//! eprintln!("unhandled segment-buffer error: {other}");
//! }
//! }
//! # Ok(())
//! # }
//! ```
use PathBuf;
/// Errors produced by segment-buffer operations.
///
/// Every non-I/O variant carries the [`path`](Self::Cbor) of the segment file
/// involved, so an operator can act on the failure without spelunking through
/// logs.
/// Result alias used throughout the crate.
pub type Result<T> = Result;