-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Retry combinators for monadic actions that may fail -- @package retry @version 0.6 -- | This module exposes combinators that can wrap arbitrary monadic -- actions. They run the action and potentially retry running it with -- some configurable delay for a configurable number of times. -- -- The express purpose of this library is to make it easier to work with -- IO and especially network IO actions that often experience temporary -- failure that warrant retrying of the original action. For example, a -- database query may time out for a while, in which case we should delay -- a bit and retry the query. module Control.Retry -- | A RetryPolicy is a function that takes an iteration number and -- possibly returns a delay in microseconds. *Nothing* implies we have -- reached the retry limit. -- -- Please note that RetryPolicy is a Monoid. You can -- collapse multiple strategies into one using mappend or -- <>. The semantics of this combination are as follows: -- --
-- > limitedBackoff = exponentialBackoff 50 <> limitRetries 5 ---- -- Naturally, mempty will retry immediately (delay 0) for an -- unlimited number of retries, forming the identity for the -- Monoid. -- -- The default under def implements a constant 50ms delay, up to 5 -- times: -- --
-- > def = constantDelay 50000 <> limitRetries 5 ---- -- For anything more complex, just define your own RetryPolicy: -- --
-- > myPolicy = RetryPolicy $ \ n -> if n > 10 then Just 1000 else Just 10000 --newtype RetryPolicy RetryPolicy :: (Int -> Maybe Int) -> RetryPolicy getRetryPolicy :: RetryPolicy -> Int -> Maybe Int -- | Retry combinator for actions that don't raise exceptions, but signal -- in their type the outcome has failed. Examples are the Maybe, -- Either and EitherT monads. -- -- Let's write a function that always fails and watch this combinator -- retry it 5 additional times following the initial run: -- --
-- >>> import Data.Maybe -- -- >>> let f = putStrLn "Running action" >> return Nothing -- -- >>> retrying def (const $ return . isNothing) f -- Running action -- Running action -- Running action -- Running action -- Running action -- Running action -- Nothing ---- -- Note how the latest failing result is returned after all retries have -- been exhausted. retrying :: MonadIO m => RetryPolicy -> (Int -> b -> m Bool) -> m b -> m b -- | Run an action and recover from a raised exception by potentially -- retrying the action a number of times. recovering :: (MonadIO m, MonadMask m) => RetryPolicy -> [(Int -> Handler m Bool)] -> m a -> m a -- | Retry ALL exceptions that may be raised. To be used with caution; this -- matches the exception on SomeException. -- -- See how the action below is run once and retried 5 more times before -- finally failing for good: -- --
-- >>> let f = putStrLn "Running action" >> error "this is an error" -- -- >>> recoverAll def f -- Running action -- Running action -- Running action -- Running action -- Running action -- Running action -- *** Exception: this is an error --recoverAll :: (MonadIO m, MonadMask m) => RetryPolicy -> m a -> m a -- | Helper function for constructing handler functions of the form -- required by recovering. logRetries :: (Monad m, Show e, Exception e) => (e -> m Bool) -> (String -> m ()) -> Int -> Handler m Bool -- | Implement a constant delay with unlimited retries. constantDelay :: Int -> RetryPolicy -- | Grow delay exponentially each iteration. exponentialBackoff :: Int -> RetryPolicy -- | Implement Fibonacci backoff. fibonacciBackoff :: Int -> RetryPolicy -- | Retry immediately, but only up to n times. limitRetries :: Int -> RetryPolicy -- | Add an upperbound to a policy such that once the given time-delay -- amount has been reached or exceeded, the policy will stop retrying and -- fail. limitRetriesByDelay :: Int -> RetryPolicy -> RetryPolicy -- | Set a time-upperbound for any delays that may be directed by the given -- policy. This function does not terminate the retrying. The policy -- `capDelay maxDelay (exponentialBackoff n)` will never stop retrying. -- It will reach a state where it retries forever with a delay of -- maxDelay between each one. To get termination you need to use -- one of the limitRetries function variants. capDelay :: Int -> RetryPolicy -> RetryPolicy -- | An infix synonym for mappend. -- -- Since: 4.5.0.0 (<>) :: Monoid m => m -> m -> m instance Monoid RetryPolicy instance Default RetryPolicy