Skip to content

Commit 844c970

Browse files
committed
WIP convert final error from thiserror to snafu and drop thiserror dep
No backtraces yet!
1 parent 4fce71e commit 844c970

File tree

6 files changed

+127
-57
lines changed

6 files changed

+127
-57
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ irpc = { version = "0.4.0", features = ["rpc", "quinn_endpoint_setup", "message_
3838
iroh-metrics = { version = "0.32.0" }
3939
hashlink = "0.10.0"
4040
futures-buffered = "0.2.11"
41-
thiserror = "2.0.12"
4241

4342
[dev-dependencies]
4443
clap = { version = "4.5.31", features = ["derive"] }

src/api/remote.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ impl GetProgress {
9494

9595
pub async fn complete(self) -> GetResult<Stats> {
9696
just_result(self.stream()).await.unwrap_or_else(|| {
97-
Err(GetError::LocalFailure(anyhow::anyhow!(
98-
"stream closed without result"
99-
)))
97+
Err(GetError::LocalFailure {
98+
source: anyhow::anyhow!("stream closed without result"),
99+
})
100100
})
101101
}
102102
}
@@ -502,12 +502,18 @@ impl Remote {
502502
progress: impl Sink<u64, Error = io::Error>,
503503
) -> GetResult<Stats> {
504504
let content = content.into();
505-
let local = self.local(content).await.map_err(GetError::LocalFailure)?;
505+
let local = self
506+
.local(content)
507+
.await
508+
.map_err(|source| GetError::LocalFailure { source })?;
506509
if local.is_complete() {
507510
return Ok(Default::default());
508511
}
509512
let request = local.missing();
510-
let conn = conn.connection().await.map_err(GetError::LocalFailure)?;
513+
let conn = conn
514+
.connection()
515+
.await
516+
.map_err(|source| GetError::LocalFailure { source })?;
511517
let stats = self.execute_get_sink(conn, request, progress).await?;
512518
Ok(stats)
513519
}
@@ -676,9 +682,9 @@ impl Remote {
676682
store
677683
.get_bytes(root)
678684
.await
679-
.map_err(|e| GetError::LocalFailure(e.into()))?,
685+
.map_err(|e| GetError::LocalFailure { source: e.into() })?,
680686
)
681-
.map_err(GetError::BadRequest)?;
687+
.map_err(|source| GetError::BadRequest { source })?;
682688
// let mut hash_seq = LazyHashSeq::new(store.blobs().clone(), root);
683689
loop {
684690
let at_start_child = match next_child {
@@ -883,7 +889,7 @@ async fn get_blob_ranges_impl(
883889
let handle = store
884890
.import_bao(hash, size, buffer_size)
885891
.await
886-
.map_err(|e| GetError::LocalFailure(e.into()))?;
892+
.map_err(|e| GetError::LocalFailure { source: e.into() })?;
887893
let write = async move {
888894
GetResult::Ok(loop {
889895
match content.next().await {
@@ -892,7 +898,7 @@ async fn get_blob_ranges_impl(
892898
progress
893899
.send(next.stats().payload_bytes_read)
894900
.await
895-
.map_err(|e| GetError::LocalFailure(e.into()))?;
901+
.map_err(|e| GetError::LocalFailure { source: e.into() })?;
896902
handle.tx.send(item).await?;
897903
content = next;
898904
}
@@ -904,8 +910,8 @@ async fn get_blob_ranges_impl(
904910
})
905911
};
906912
let complete = async move {
907-
handle.rx.await.map_err(|e| {
908-
GetError::LocalFailure(anyhow::anyhow!("error reading from import stream: {e}"))
913+
handle.rx.await.map_err(|e| GetError::LocalFailure {
914+
source: anyhow::anyhow!("error reading from import stream: {e}"),
909915
})
910916
};
911917
let (_, end) = tokio::try_join!(complete, write)?;

src/get.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ pub mod fsm {
129129
let (mut writer, reader) = connection.open_bi().await?;
130130
let request = Request::GetMany(request);
131131
let request_bytes =
132-
postcard::to_stdvec(&request).map_err(|e| GetError::BadRequest(e.into()))?;
132+
postcard::to_stdvec(&request).map_err(|source| GetError::BadRequest {
133+
source: source.into(),
134+
})?;
133135
writer.write_all(&request_bytes).await?;
134136
writer.finish()?;
135137
let Request::GetMany(request) = request else {

src/get/error.rs

Lines changed: 99 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,60 @@
11
//! Error returned from get operations
22
33
use iroh::endpoint::{self, ClosedStream};
4+
use n0_snafu::SpanTrace;
5+
use nested_enum_utils::common_fields;
6+
use snafu::{Backtrace, Snafu};
7+
8+
#[common_fields({
9+
backtrace: Option<Backtrace>,
10+
#[snafu(implicit)]
11+
span_trace: SpanTrace,
12+
})]
13+
#[derive(Debug, Snafu)]
14+
pub enum GetNotFoundError {
15+
AtBlobHeader {},
16+
}
417

518
/// Failures for a get operation
6-
#[derive(Debug, thiserror::Error)]
19+
#[derive(Debug, Snafu)]
720
pub enum GetError {
821
/// Hash not found, or a requested chunk for the hash not found.
9-
#[error("Data for hash not found")]
10-
NotFound(#[source] anyhow::Error),
22+
#[snafu(display("Data for hash not found"))]
23+
NotFound { source: GetNotFoundError },
1124
/// Remote has reset the connection.
12-
#[error("Remote has reset the connection")]
13-
RemoteReset(#[source] anyhow::Error),
25+
#[snafu(display("Remote has reset the connection"))]
26+
RemoteReset { source: anyhow::Error },
1427
/// Remote behaved in a non-compliant way.
15-
#[error("Remote behaved in a non-compliant way")]
16-
NoncompliantNode(#[source] anyhow::Error),
28+
#[snafu(display("Remote behaved in a non-compliant way"))]
29+
NoncompliantNode { source: anyhow::Error },
1730

1831
/// Network or IO operation failed.
19-
#[error("A network or IO operation failed")]
20-
Io(#[source] anyhow::Error),
32+
#[snafu(display("A network or IO operation failed"))]
33+
Io { source: anyhow::Error },
2134

2235
/// Our download request is invalid.
23-
#[error("Our download request is invalid")]
24-
BadRequest(#[source] anyhow::Error),
36+
#[snafu(display("Our download request is invalid"))]
37+
BadRequest { source: anyhow::Error },
2538
/// Operation failed on the local node.
26-
#[error("Operation failed on the local node")]
27-
LocalFailure(#[source] anyhow::Error),
39+
#[snafu(display("Operation failed on the local node"))]
40+
LocalFailure { source: anyhow::Error },
2841
}
2942

3043
pub type GetResult<T> = std::result::Result<T, GetError>;
3144

3245
impl From<irpc::channel::SendError> for GetError {
3346
fn from(value: irpc::channel::SendError) -> Self {
34-
Self::LocalFailure(value.into())
47+
Self::LocalFailure {
48+
source: value.into(),
49+
}
3550
}
3651
}
3752

3853
impl<T: Send + Sync + 'static> From<tokio::sync::mpsc::error::SendError<T>> for GetError {
3954
fn from(value: tokio::sync::mpsc::error::SendError<T>) -> Self {
40-
Self::LocalFailure(value.into())
55+
Self::LocalFailure {
56+
source: value.into(),
57+
}
4158
}
4259
}
4360

@@ -49,40 +66,40 @@ impl From<endpoint::ConnectionError> for GetError {
4966
e @ ConnectionError::VersionMismatch => {
5067
// > The peer doesn't implement any supported version
5168
// unsupported version is likely a long time error, so this peer is not usable
52-
GetError::NoncompliantNode(e.into())
69+
GetError::NoncompliantNode { source: e.into() }
5370
}
5471
e @ ConnectionError::TransportError(_) => {
5572
// > The peer violated the QUIC specification as understood by this implementation
5673
// bad peer we don't want to keep around
57-
GetError::NoncompliantNode(e.into())
74+
GetError::NoncompliantNode { source: e.into() }
5875
}
5976
e @ ConnectionError::ConnectionClosed(_) => {
6077
// > The peer's QUIC stack aborted the connection automatically
6178
// peer might be disconnecting or otherwise unavailable, drop it
62-
GetError::Io(e.into())
79+
GetError::Io { source: e.into() }
6380
}
6481
e @ ConnectionError::ApplicationClosed(_) => {
6582
// > The peer closed the connection
6683
// peer might be disconnecting or otherwise unavailable, drop it
67-
GetError::Io(e.into())
84+
GetError::Io { source: e.into() }
6885
}
6986
e @ ConnectionError::Reset => {
7087
// > The peer is unable to continue processing this connection, usually due to having restarted
71-
GetError::RemoteReset(e.into())
88+
GetError::RemoteReset { source: e.into() }
7289
}
7390
e @ ConnectionError::TimedOut => {
7491
// > Communication with the peer has lapsed for longer than the negotiated idle timeout
75-
GetError::Io(e.into())
92+
GetError::Io { source: e.into() }
7693
}
7794
e @ ConnectionError::LocallyClosed => {
7895
// > The local application closed the connection
7996
// TODO(@divma): don't see how this is reachable but let's just not use the peer
80-
GetError::Io(e.into())
97+
GetError::Io { source: e.into() }
8198
}
8299
e @ ConnectionError::CidsExhausted => {
83100
// > The connection could not be created because not enough of the CID space
84101
// > is available
85-
GetError::Io(e.into())
102+
GetError::Io { source: e.into() }
86103
}
87104
}
88105
}
@@ -92,32 +109,38 @@ impl From<endpoint::ReadError> for GetError {
92109
fn from(value: endpoint::ReadError) -> Self {
93110
use endpoint::ReadError;
94111
match value {
95-
e @ ReadError::Reset(_) => GetError::RemoteReset(e.into()),
112+
e @ ReadError::Reset(_) => GetError::RemoteReset { source: e.into() },
96113
ReadError::ConnectionLost(conn_error) => conn_error.into(),
97114
ReadError::ClosedStream
98115
| ReadError::IllegalOrderedRead
99116
| ReadError::ZeroRttRejected => {
100117
// all these errors indicate the peer is not usable at this moment
101-
GetError::Io(value.into())
118+
GetError::Io {
119+
source: value.into(),
120+
}
102121
}
103122
}
104123
}
105124
}
106125
impl From<ClosedStream> for GetError {
107126
fn from(value: ClosedStream) -> Self {
108-
GetError::Io(value.into())
127+
GetError::Io {
128+
source: value.into(),
129+
}
109130
}
110131
}
111132

112133
impl From<quinn::WriteError> for GetError {
113134
fn from(value: quinn::WriteError) -> Self {
114135
use quinn::WriteError;
115136
match value {
116-
e @ WriteError::Stopped(_) => GetError::RemoteReset(e.into()),
137+
e @ WriteError::Stopped(_) => GetError::RemoteReset { source: e.into() },
117138
WriteError::ConnectionLost(conn_error) => conn_error.into(),
118139
WriteError::ClosedStream | WriteError::ZeroRttRejected => {
119140
// all these errors indicate the peer is not usable at this moment
120-
GetError::Io(value.into())
141+
GetError::Io {
142+
source: value.into(),
143+
}
121144
}
122145
}
123146
}
@@ -129,17 +152,17 @@ impl From<crate::get::fsm::ConnectedNextError> for GetError {
129152
match value {
130153
e @ PostcardSer { .. } => {
131154
// serialization errors indicate something wrong with the request itself
132-
GetError::BadRequest(e.into())
155+
GetError::BadRequest { source: e.into() }
133156
}
134157
e @ RequestTooBig { .. } => {
135158
// request will never be sent, drop it
136-
GetError::BadRequest(e.into())
159+
GetError::BadRequest { source: e.into() }
137160
}
138161
Write { source, .. } => source.into(),
139162
Closed { source, .. } => source.into(),
140163
e @ Io { .. } => {
141164
// io errors are likely recoverable
142-
GetError::Io(e.into())
165+
GetError::Io { source: e.into() }
143166
}
144167
}
145168
}
@@ -149,15 +172,23 @@ impl From<crate::get::fsm::AtBlobHeaderNextError> for GetError {
149172
fn from(value: crate::get::fsm::AtBlobHeaderNextError) -> Self {
150173
use crate::get::fsm::AtBlobHeaderNextError::*;
151174
match value {
152-
e @ NotFound { .. } => {
175+
NotFound {
176+
backtrace,
177+
span_trace,
178+
} => {
153179
// > This indicates that the provider does not have the requested data.
154180
// peer might have the data later, simply retry it
155-
GetError::NotFound(e.into())
181+
GetError::NotFound {
182+
source: GetNotFoundError::AtBlobHeader {
183+
backtrace,
184+
span_trace,
185+
},
186+
}
156187
}
157188
EndpointRead { source, .. } => source.into(),
158189
e @ Io { .. } => {
159190
// io errors are likely recoverable
160-
GetError::Io(e.into())
191+
GetError::Io { source: e.into() }
161192
}
162193
}
163194
}
@@ -168,18 +199,44 @@ impl From<crate::get::fsm::DecodeError> for GetError {
168199
use crate::get::fsm::DecodeError::*;
169200

170201
match value {
171-
e @ ChunkNotFound { .. } => GetError::NotFound(e.into()),
172-
e @ ParentNotFound { .. } => GetError::NotFound(e.into()),
173-
e @ LeafNotFound { .. } => GetError::NotFound(e.into()),
202+
ChunkNotFound {
203+
backtrace,
204+
span_trace,
205+
} => GetError::NotFound {
206+
source: GetNotFoundError::AtBlobHeader {
207+
backtrace,
208+
span_trace,
209+
},
210+
},
211+
ParentNotFound {
212+
backtrace,
213+
span_trace,
214+
..
215+
} => GetError::NotFound {
216+
source: GetNotFoundError::AtBlobHeader {
217+
backtrace,
218+
span_trace,
219+
},
220+
},
221+
LeafNotFound {
222+
backtrace,
223+
span_trace,
224+
..
225+
} => GetError::NotFound {
226+
source: GetNotFoundError::AtBlobHeader {
227+
backtrace,
228+
span_trace,
229+
},
230+
},
174231
e @ ParentHashMismatch { .. } => {
175232
// TODO(@divma): did the peer sent wrong data? is it corrupted? did we sent a wrong
176233
// request?
177-
GetError::NoncompliantNode(e.into())
234+
GetError::NoncompliantNode { source: e.into() }
178235
}
179236
e @ LeafHashMismatch { .. } => {
180237
// TODO(@divma): did the peer sent wrong data? is it corrupted? did we sent a wrong
181238
// request?
182-
GetError::NoncompliantNode(e.into())
239+
GetError::NoncompliantNode { source: e.into() }
183240
}
184241
Read { source, .. } => source.into(),
185242
DecodeIo { source, .. } => source.into(),
@@ -191,6 +248,8 @@ impl From<std::io::Error> for GetError {
191248
fn from(value: std::io::Error) -> Self {
192249
// generally consider io errors recoverable
193250
// we might want to revisit this at some point
194-
GetError::Io(value.into())
251+
GetError::Io {
252+
source: value.into(),
253+
}
195254
}
196255
}

0 commit comments

Comments
 (0)