at main 194 lines 5.2 kB view raw
1use std::path::PathBuf; 2 3use miette::Diagnostic; 4use thiserror::Error; 5 6/// Top-level error type for weaver-index operations 7#[derive(Debug, Error, Diagnostic)] 8pub enum IndexError { 9 #[error(transparent)] 10 #[diagnostic(transparent)] 11 ClickHouse(#[from] ClickHouseError), 12 13 #[error(transparent)] 14 #[diagnostic(transparent)] 15 Firehose(#[from] FirehoseError), 16 17 #[error(transparent)] 18 #[diagnostic(transparent)] 19 Car(#[from] CarError), 20 21 #[error(transparent)] 22 #[diagnostic(transparent)] 23 Config(#[from] ConfigError), 24 25 #[error(transparent)] 26 #[diagnostic(transparent)] 27 Server(#[from] ServerError), 28 29 #[error(transparent)] 30 #[diagnostic(transparent)] 31 Sqlite(#[from] SqliteError), 32 33 #[error("resource not found: {resource}")] 34 #[diagnostic(code(index::not_found))] 35 NotFound { resource: String }, 36} 37 38/// HTTP server errors 39#[derive(Debug, Error, Diagnostic)] 40pub enum ServerError { 41 #[error("failed to bind to {addr}")] 42 #[diagnostic(code(server::bind))] 43 Bind { 44 addr: std::net::SocketAddr, 45 #[source] 46 source: std::io::Error, 47 }, 48 49 #[error("server terminated unexpectedly")] 50 #[diagnostic(code(server::serve))] 51 Serve { 52 #[source] 53 source: std::io::Error, 54 }, 55} 56 57/// SQLite shard errors 58#[derive(Debug, Error, Diagnostic)] 59pub enum SqliteError { 60 #[error("failed to open database at {}", path.display())] 61 #[diagnostic(code(sqlite::open))] 62 Open { 63 path: PathBuf, 64 #[source] 65 source: rusqlite::Error, 66 }, 67 68 #[error("failed to create directory {}", path.display())] 69 #[diagnostic(code(sqlite::io))] 70 Io { 71 path: PathBuf, 72 #[source] 73 source: std::io::Error, 74 }, 75 76 #[error("failed to set pragma {pragma}")] 77 #[diagnostic(code(sqlite::pragma))] 78 Pragma { 79 pragma: &'static str, 80 #[source] 81 source: rusqlite::Error, 82 }, 83 84 #[error("migration failed: {message}")] 85 #[diagnostic(code(sqlite::migration))] 86 Migration { message: String }, 87 88 #[error("query failed: {message}")] 89 #[diagnostic(code(sqlite::query))] 90 Query { message: String }, 91 92 #[error("shard lock poisoned")] 93 #[diagnostic(code(sqlite::lock))] 94 LockPoisoned, 95} 96 97/// ClickHouse database errors 98#[derive(Debug, Error, Diagnostic)] 99pub enum ClickHouseError { 100 #[error("failed to connect to ClickHouse: {message}: {source}")] 101 #[diagnostic(code(clickhouse::connection))] 102 Connection { 103 message: String, 104 #[source] 105 source: clickhouse::error::Error, 106 }, 107 108 #[error("ClickHouse query failed: {message}: {source}")] 109 #[diagnostic(code(clickhouse::query))] 110 Query { 111 message: String, 112 #[source] 113 source: clickhouse::error::Error, 114 }, 115 116 #[error("failed to insert batch: {message}: {source}")] 117 #[diagnostic(code(clickhouse::insert))] 118 Insert { 119 message: String, 120 #[source] 121 source: clickhouse::error::Error, 122 }, 123 124 #[error("schema migration failed: {message}")] 125 #[diagnostic(code(clickhouse::schema))] 126 Schema { message: String }, 127} 128 129/// Firehose/subscription stream errors 130#[derive(Debug, Error, Diagnostic)] 131pub enum FirehoseError { 132 #[error("failed to connect to relay at {url}")] 133 #[diagnostic(code(firehose::connection))] 134 Connection { url: String, message: String }, 135 136 #[error("websocket stream error: {message}")] 137 #[diagnostic(code(firehose::stream))] 138 Stream { message: String }, 139 140 #[error("failed to parse event header")] 141 #[diagnostic(code(firehose::header))] 142 HeaderParse { 143 #[source] 144 source: ciborium::de::Error<std::io::Error>, 145 }, 146 147 #[error("failed to decode event body: {event_type}")] 148 #[diagnostic(code(firehose::decode))] 149 BodyDecode { event_type: String, message: String }, 150 151 #[error("unknown event type: {event_type}")] 152 #[diagnostic(code(firehose::unknown_event))] 153 UnknownEvent { event_type: String }, 154} 155 156/// CAR file parsing errors 157#[derive(Debug, Error, Diagnostic)] 158pub enum CarError { 159 #[error("failed to parse CAR data")] 160 #[diagnostic(code(car::parse))] 161 Parse { message: String }, 162 163 #[error("block not found for CID: {cid}")] 164 #[diagnostic(code(car::block_not_found))] 165 BlockNotFound { cid: String }, 166 167 #[error("failed to decode record from block: {message}")] 168 #[diagnostic(code(car::record_decode))] 169 RecordDecode { message: String }, 170} 171 172/// Configuration errors 173#[derive(Debug, Error, Diagnostic)] 174pub enum ConfigError { 175 #[error("missing required environment variable: {var}")] 176 #[diagnostic( 177 code(config::missing_env), 178 help("Set the {var} environment variable or add it to your .env file") 179 )] 180 MissingEnv { var: &'static str }, 181 182 #[error("invalid configuration value for {field}: {message}")] 183 #[diagnostic(code(config::invalid))] 184 Invalid { 185 field: &'static str, 186 message: String, 187 }, 188 189 #[error("failed to parse URL: {url}")] 190 #[diagnostic(code(config::url_parse))] 191 UrlParse { url: String, message: String }, 192} 193 194pub type Result<T> = std::result::Result<T, IndexError>;