Skip to content

Commit f7ae3e6

Browse files
committed
ops: Classify HTTP/2 Go Away response as a retryable transient error
Signed-off-by: Joshua Potts <[email protected]>
1 parent 76f5575 commit f7ae3e6

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

Cargo.lock

+5-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ backoff = "0.4.0"
2525
ed25519-dalek = { version = "2.0.0", features = ["rand_core"] }
2626
fraction = { version = "0.15.1", default-features = false }
2727
futures-core = "0.3.21"
28+
# Transitive dependency of tonic 0.11. Can be removed when tonic is upgraded to 0.12.
29+
h2_03 = { package = "h2", version = "0.3.6" }
30+
# Transitive dependency of tonic 0.12
31+
h2 = "0.4.6"
2832
hedera-proto = { path = "./protobufs", version = "0.13.0", features = [
2933
"time_0_3",
3034
"fraction",

src/execute.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ use tonic::transport::Channel;
4141
use triomphe::Arc;
4242

4343
use crate::client::NetworkData;
44-
use crate::execute::error::is_hyper_canceled;
44+
use crate::execute::error::{
45+
is_hyper_canceled,
46+
is_tonic_status_transient,
47+
};
4548
use crate::ping_query::PingQuery;
4649
use crate::{
4750
client,
@@ -357,6 +360,10 @@ fn map_tonic_error(
357360
}
358361
}
359362

363+
tonic::Code::Internal if is_tonic_status_transient(&status) => {
364+
retry::Error::Transient(status.into())
365+
}
366+
360367
// fail immediately
361368
_ => retry::Error::Permanent(status.into()),
362369
}

src/execute/error.rs

+25
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,28 @@ mod test_is_hyper_canceled {
6767
assert!(!is_hyper_canceled(&input));
6868
}
6969
}
70+
71+
pub(super) fn is_tonic_status_transient(status: &tonic::Status) -> bool {
72+
let source = status
73+
.source()
74+
.and_then(|it| it.downcast_ref::<tonic::transport::Error>())
75+
.and_then(StdError::source);
76+
77+
let Some(source) = source else {
78+
return false;
79+
};
80+
81+
if let Some(hyper_0) = source.downcast_ref::<hyper_0::Error>() {
82+
// tonic 0.11 (current dependency)
83+
let source: Option<&h2_03::Error> = hyper_0.source().and_then(|s| s.downcast_ref());
84+
85+
source.map(|s| s.is_go_away()).unwrap_or_default()
86+
} else if let Some(hyper_1) = source.downcast_ref::<hyper::Error>() {
87+
// tonic 0.12
88+
let source: Option<&h2::Error> = hyper_1.source().and_then(|s| s.downcast_ref());
89+
90+
source.map(|s| s.is_go_away()).unwrap_or_default()
91+
} else {
92+
false
93+
}
94+
}

0 commit comments

Comments
 (0)