-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Result-based retries -- return the last result's error instead of a custom error type #17
Labels
Comments
Looking for a solution like this: #[derive(SmartDefault)]
struct Retry {
#[default = "3"]
attempts: u64,
#[default = "1000"]
interval: u64,
}
impl Retry {
pub fn attempts(mut self, attempts: u64) -> Self {
self.attempts = attempts;
self
}
pub fn interval(mut self, interval: u64) -> Self {
self.interval = interval;
self
}
pub fn retry_until_ok<F, T, E>(&self, mut func: F) -> Result<T, E>
where F: FnMut() -> Result<T, E>
{
let duration = ::std::time::Duration::from_millis(self.interval);
let mut attempt = 0;
loop {
match func() {
Ok(value) => return Ok(value),
Err(why) => {
if attempt == self.attempts {
return Err(why);
} else {
attempt += 1;
::std::thread::sleep(duration);
}
}
}
}
}
} pub fn fsck<P: AsRef<Path>>(part: P, cmd: Option<(&str, &str)>) -> io::Result<()> {
let (cmd, arg) = cmd.unwrap_or(("fsck", "-fy"));
// Attempt this once every second, with up to 3 attempts before giving up.
Retry::default()
.attempts(3)
.interval(1000)
.retry_until_ok(move || exec(cmd, None, None, &[arg.into(), part.as_ref().into()]))
} |
Sounds like a good idea to me! |
This is a great idea. I just implemented this for myself: use ::std::time::Duration;
pub enum RetryResult<T, E> {
Ok(T),
Retry(E),
Err(E),
}
impl<T, E> From<Result<T, E>> for RetryResult<T, E> {
fn from(r : Result<T, E>) -> Self {
match r {
Ok(v) => RetryResult::Ok(v),
Err(e) => RetryResult::Retry(e),
}
}
}
pub struct Retry {
attempts: Option<u64>,
interval: Duration,
}
impl Default for Retry {
fn default() -> Self {
Retry {
attempts: None,
interval: Duration::from_millis(1000),
}
}
}
impl Retry {
pub fn attempts(mut self, attempts: u64) -> Self {
self.attempts = Some(attempts);
self
}
pub fn interval(mut self, interval: u64) -> Self {
self.interval = Duration::from_millis(interval);
self
}
pub fn retry_until_ok<F, T, E, R>(&self, mut func: F) -> Result<T, E>
where F: FnMut() -> R,
R : Into<RetryResult<T, E>>
{
let mut attempt = 0;
loop {
match func().into() {
RetryResult::Ok(value) => return Ok(value),
RetryResult::Err(why) => return Err(why),
RetryResult::Retry(why) => {
if Some(attempt) == self.attempts {
return Err(why);
} else {
attempt += 1;
::std::thread::sleep(self.interval);
}
}
}
}
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No description provided.
The text was updated successfully, but these errors were encountered: