• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / etl / 24712719693

21 Apr 2026 08:39AM UTC coverage: 78.38%. First build
24712719693

Pull #675

github

web-flow
Merge 41f90c12a into 4d653bd29
Pull Request #675: refactor: enable extended clippy lint set

414 of 503 new or added lines in 59 files covered. (82.31%)

24399 of 31129 relevant lines covered (78.38%)

1072.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/etl-replicator/src/error.rs
1
use std::{backtrace::Backtrace, error::Error, fmt};
2

3
use etl::error::EtlError;
4

5
/// Returns whether terminal output should include backtraces.
6
fn should_render_backtrace() -> bool {
×
NEW
7
    matches!(std::env::var("RUST_BACKTRACE").as_deref(), Ok("1" | "full"))
×
8
}
×
9

10
/// Result type for replicator operations.
11
pub(crate) type ReplicatorResult<T> = Result<T, ReplicatorError>;
12

13
/// Captured backtrace wrapper to avoid thiserror's unstable feature detection.
14
pub(crate) struct CapturedBacktrace(Backtrace);
15

16
impl CapturedBacktrace {
17
    /// Captures a new backtrace for an error variant.
18
    fn capture() -> Self {
×
19
        Self(Backtrace::capture())
×
20
    }
×
21
}
22

23
impl fmt::Debug for CapturedBacktrace {
24
    /// Renders the wrapped backtrace for debugging output.
25
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
26
        write!(f, "{}", self.0)
×
27
    }
×
28
}
29

30
/// Error type for the replicator service.
31
///
32
/// Wraps [`EtlError`] for pipeline errors and provides variants for
33
/// infrastructure errors.
34
#[derive(Debug)]
35
pub(crate) enum ReplicatorError {
36
    /// Pipeline or ETL-related error.
37
    Etl(EtlError),
38
    /// Configuration error.
39
    Config(Box<dyn Error + Send + Sync>, CapturedBacktrace),
40
    /// Database migration error.
41
    Migration(sqlx::Error, CapturedBacktrace),
42
    /// I/O error.
43
    Io(std::io::Error, CapturedBacktrace),
44
}
45

46
impl ReplicatorError {
47
    /// Returns a short category label for this error.
48
    fn category(&self) -> &'static str {
×
49
        match self {
×
50
            ReplicatorError::Etl(_) => "replicator error",
×
51
            ReplicatorError::Config(_, _) => "configuration error",
×
52
            ReplicatorError::Migration(_, _) => "migration error",
×
53
            ReplicatorError::Io(_, _) => "i/o error",
×
54
        }
55
    }
×
56

57
    /// Returns the backtrace for this error.
58
    pub(crate) fn backtrace(&self) -> Option<&Backtrace> {
×
59
        match self {
×
60
            ReplicatorError::Etl(err) => err.backtrace(),
×
NEW
61
            ReplicatorError::Config(_, cb)
×
NEW
62
            | ReplicatorError::Migration(_, cb)
×
NEW
63
            | ReplicatorError::Io(_, cb) => Some(&cb.0),
×
64
        }
65
    }
×
66

67
    /// Creates a configuration error from any boxed source.
68
    pub(crate) fn config<E: Error + Send + Sync + 'static>(err: E) -> Self {
×
69
        ReplicatorError::Config(Box::new(err), CapturedBacktrace::capture())
×
70
    }
×
71

72
    /// Returns a user-oriented report for terminal output.
73
    pub(crate) fn render_report(&self) -> String {
×
74
        let mut out = String::new();
×
75
        out.push_str("replicator failed\n");
×
76
        out.push_str(&format!("category: {}\n", self.category()));
×
77
        out.push_str(&format!("error: {self}\n"));
×
78

79
        if !matches!(self, ReplicatorError::Etl(err) if err.errors().is_some()) {
×
80
            let mut source = Error::source(self);
×
81
            let mut idx = 1usize;
×
82
            while let Some(err) = source {
×
83
                out.push_str(&format!("cause {idx}: {err}\n"));
×
84
                source = err.source();
×
85
                idx += 1;
×
86
            }
×
87
        }
×
88

89
        if should_render_backtrace()
×
90
            && let Some(backtrace) = self.backtrace()
×
91
        {
92
            out.push_str("backtrace:\n");
×
93
            out.push_str(&backtrace.to_string());
×
94
            if !out.ends_with('\n') {
×
95
                out.push('\n');
×
96
            }
×
97
        }
×
98

99
        out
×
100
    }
×
101
}
102

103
impl fmt::Display for ReplicatorError {
104
    /// Renders a user-focused one-line description for terminal and log output.
105
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
106
        match self {
×
107
            ReplicatorError::Etl(err) => write!(f, "{err}"),
×
108
            ReplicatorError::Config(source, _) => write!(f, "configuration error: {source}"),
×
109
            ReplicatorError::Migration(source, _) => write!(f, "migration error: {source}"),
×
110
            ReplicatorError::Io(source, _) => write!(f, "i/o error: {source}"),
×
111
        }
112
    }
×
113
}
114

115
impl Error for ReplicatorError {
116
    /// Returns the direct cause for this error variant.
117
    fn source(&self) -> Option<&(dyn Error + 'static)> {
×
118
        match self {
×
119
            ReplicatorError::Etl(err) => err.source(),
×
120
            ReplicatorError::Config(source, _) => Some(source.as_ref()),
×
121
            ReplicatorError::Migration(source, _) => Some(source),
×
122
            ReplicatorError::Io(source, _) => Some(source),
×
123
        }
124
    }
×
125
}
126

127
impl From<sqlx::Error> for ReplicatorError {
128
    /// Converts a SQLx error into a migration error variant.
129
    fn from(err: sqlx::Error) -> Self {
×
130
        ReplicatorError::Migration(err, CapturedBacktrace::capture())
×
131
    }
×
132
}
133

134
impl From<std::io::Error> for ReplicatorError {
135
    /// Converts an I/O error into an I/O error variant.
136
    fn from(err: std::io::Error) -> Self {
×
137
        ReplicatorError::Io(err, CapturedBacktrace::capture())
×
138
    }
×
139
}
140

141
impl From<EtlError> for ReplicatorError {
142
    /// Converts an ETL error into a replicator ETL error variant.
143
    fn from(err: EtlError) -> Self {
×
144
        ReplicatorError::Etl(err)
×
145
    }
×
146
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc