Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 142 additions & 36 deletions src/blocking_retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ where
}

/// Retry struct generated by [`Retryable`].
pub struct BlockingRetry<B: Backoff, T, E, F: FnMut() -> Result<T, E>> {
pub struct BlockingRetry<B: Backoff, T, E, F: FnMut() -> Result<T, E>, RF = (), NF = ()> {
backoff: B,
retryable: fn(&E) -> bool,
notify: fn(&E, Duration),
retryable: RF,
notify: NF,
f: F,
}

Expand All @@ -74,12 +74,130 @@ where
fn new(f: F, backoff: B) -> Self {
BlockingRetry {
backoff,
retryable: |_: &E| true,
notify: |_: &E, _: Duration| {},
retryable: (),
notify: (),
f,
}
}

/// Call the retried function.
///
/// TODO: implment [`std::ops::FnOnce`] after it stable.
pub fn call(mut self) -> Result<T, E> {
loop {
let result = (self.f)();

match result {
Ok(v) => return Ok(v),
Err(err) => match self.backoff.next() {
None => return Err(err),
Some(dur) => {
thread::sleep(dur);
}
},
}
}
}
}

impl<B, T, E, F, NF> BlockingRetry<B, T, E, F, (), NF>
where
B: Backoff,
F: FnMut() -> Result<T, E>,
NF: FnMut(&E, Duration),
{
/// Call the retried function.
///
/// TODO: implment [`std::ops::FnOnce`] after it stable.
pub fn call(mut self) -> Result<T, E> {
loop {
let result = (self.f)();

match result {
Ok(v) => return Ok(v),
Err(err) => match self.backoff.next() {
None => return Err(err),
Some(dur) => {
(self.notify)(&err, dur);
thread::sleep(dur);
}
},
}
}
}
}

impl<B, T, E, F, RF> BlockingRetry<B, T, E, F, RF>
where
B: Backoff,
F: FnMut() -> Result<T, E>,
RF: FnMut(&E) -> bool,
{
/// Call the retried function.
///
/// TODO: implment [`std::ops::FnOnce`] after it stable.
pub fn call(mut self) -> Result<T, E> {
loop {
let result = (self.f)();

match result {
Ok(v) => return Ok(v),
Err(err) => {
if !(self.retryable)(&err) {
return Err(err);
}

match self.backoff.next() {
None => return Err(err),
Some(dur) => {
thread::sleep(dur);
}
}
}
}
}
}
}

impl<B, T, E, F, RF, NF> BlockingRetry<B, T, E, F, RF, NF>
where
B: Backoff,
F: FnMut() -> Result<T, E>,
RF: FnMut(&E) -> bool,
NF: FnMut(&E, Duration),
{
/// Call the retried function.
///
/// TODO: implment [`std::ops::FnOnce`] after it stable.
pub fn call(mut self) -> Result<T, E> {
loop {
let result = (self.f)();

match result {
Ok(v) => return Ok(v),
Err(err) => {
if !(self.retryable)(&err) {
return Err(err);
}

match self.backoff.next() {
None => return Err(err),
Some(dur) => {
(self.notify)(&err, dur);
thread::sleep(dur);
}
}
}
}
}
}
}

impl<B, T, E, F, NF> BlockingRetry<B, T, E, F, (), NF>
where
B: Backoff,
F: FnMut() -> Result<T, E>,
{
/// Set the conditions for retrying.
///
/// If not specified, we treat all errors as retryable.
Expand All @@ -105,11 +223,21 @@ where
/// Ok(())
/// }
/// ```
pub fn when(mut self, retryable: fn(&E) -> bool) -> Self {
self.retryable = retryable;
self
pub fn when<RF: FnMut(&E) -> bool>(self, retryable: RF) -> BlockingRetry<B, T, E, F, RF, NF> {
BlockingRetry {
backoff: self.backoff,
retryable,
notify: self.notify,
f: self.f,
}
}
}

impl<B, T, E, F, RF> BlockingRetry<B, T, E, F, RF, ()>
where
B: Backoff,
F: FnMut() -> Result<T, E>,
{
/// Set to notify for everything retrying.
///
/// If not specified, this is a no-op.
Expand Down Expand Up @@ -140,34 +268,12 @@ where
/// Ok(())
/// }
/// ```
pub fn notify(mut self, notify: fn(&E, Duration)) -> Self {
self.notify = notify;
self
}

/// Call the retried function.
///
/// TODO: implment [`std::ops::FnOnce`] after it stable.
pub fn call(mut self) -> Result<T, E> {
loop {
let result = (self.f)();

match result {
Ok(v) => return Ok(v),
Err(err) => {
if !(self.retryable)(&err) {
return Err(err);
}

match self.backoff.next() {
None => return Err(err),
Some(dur) => {
(self.notify)(&err, dur);
thread::sleep(dur);
}
}
}
}
pub fn notify<NF: FnMut(&E, Duration)>(self, notify: NF) -> BlockingRetry<B, T, E, F, RF, NF> {
BlockingRetry {
backoff: self.backoff,
retryable: self.retryable,
notify,
f: self.f,
}
}
}
Expand Down