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
use crate::call_option::{RetrySettings, Retryer};
use google_cloud_googleapis::Status;
use std::future::Future;
pub trait TryAs<T> {
fn try_as(&self) -> Result<&T, ()>;
}
impl TryAs<Status> for Status {
fn try_as(&self) -> Result<&Status, ()> {
Ok(self)
}
}
pub async fn invoke<Setting, T, E, Fut>(
mut f: impl FnMut() -> Fut,
settings: &mut RetrySettings<Setting>,
) -> Result<T, E>
where
E: TryAs<Status>,
Fut: Future<Output = Result<T, E>>,
Setting: Retryer + Clone,
{
let retryer = &mut settings.retryer;
loop {
let err = match f().await {
Ok(s) => return Ok(s),
Err(e) => e,
};
let status = match err.try_as() {
Ok(s) => s,
_ => return Err(err),
};
match retryer.retry(status) {
Some(duration) => tokio::time::sleep(duration).await,
None => return Err(err),
};
}
}
pub async fn invoke_reuse<Setting, T, E, V, Fut>(
mut f: impl FnMut(V) -> Fut,
mut v: V,
settings: &mut RetrySettings<Setting>,
) -> Result<T, E>
where
E: TryAs<Status>,
Fut: Future<Output = Result<T, (E, V)>>,
Setting: Retryer + Clone,
{
let retryer = &mut settings.retryer;
loop {
let result = f(v).await;
let err = match result {
Ok(s) => return Ok(s),
Err(e) => {
v = e.1;
e.0
}
};
let status = match err.try_as() {
Ok(s) => s,
_ => return Err(err),
};
match retryer.retry(status) {
Some(duration) => tokio::time::sleep(duration).await,
None => return Err(err),
};
}
}