Add reset

This commit is contained in:
Domen Kožar 2023-12-21 12:09:45 +00:00
parent 834430954f
commit ad977f7248
3 changed files with 26 additions and 20 deletions

View File

@ -8,6 +8,7 @@ A retry Haskell library for humans:
- Limit the **attempts** of retries and **total** time.
- `Stamina.HTTP` for retrying retriable `Network.HTTP.Client` exceptions.
- Introspectable retry state for logging using `RetryStatus`.
- Support resetting the retry state when the action is long-running and an attempt works.
## API
@ -21,7 +22,8 @@ defaults :: RetrySettings
data RetryStatus = RetryStatus
{ attempts :: Int,
delay :: DiffTime,
totalDelay :: DiffTime
totalDelay :: DiffTime,
reset :: IO ()
}
-- Retry on all sync exceptions
@ -37,7 +39,10 @@ retryOnExceptions :: (Exception e, MonadIO m)
-> (RetryStatus -> m a)
-> m a
data RetryAction = Skip | Retry | RetryAfter Int
data RetryAction =
Skip -- Propagate the exception.
| Retry -- Retry with the delay according to the settings.
| RetryDelay DiffTime -- Retry after the given delay.
```
## Example
@ -64,4 +69,4 @@ main = do
## Credits
- Heavily inspired by [stamina for Python](https://stamina.hynek.me/en/stable/tutorial.html#retries).
- [retry](https://github.com/Soostone/retry) as case study for what needs to be supported.
- [retry](https://github.com/Soostone/retry) as case study for what needs to be supported.

View File

@ -1,11 +1,3 @@
{- A retry library should be able to:
- Wait between your retries: this is called a backoff.
- Not retry simultaneously with all your clients, so you must introduce randomness into your backoff: a jitter.
- Not retry forever. Sometimes a remote service is down indefinitely, and you must deal with it.
Inspired by https://stamina.hynek.me/en/stable/api.html
-}
module Stamina
( retry,
retryOnExceptions,
@ -18,6 +10,7 @@ where
import Control.Exception (Exception, Handler)
import Control.Monad.IO.Class (MonadIO)
import Control.Retry qualified as Retry
import Data.Time.Clock (DiffTime)
data RetrySettings = RetrySettings
@ -34,16 +27,24 @@ data RetrySettings = RetrySettings
-- Tracks the status of a retry
-- All fields will be zero if no retries have been attempted yet.
data RetryStatus = RetryStatus
{ attempts :: Int,
delay :: DiffTime,
totalDelay :: DiffTime
{ attempts :: Int, -- Number of retry attempts so far.
delay :: DiffTime, -- Delay before the next retry.
totalDelay :: DiffTime, -- Total delay so far.
reset :: IO () -- Reset the retry status to the initial state.
}
deriving (Show)
defaults :: RetrySettings
defaults =
-- TODO: Implement reset
RetrySettings
{ initialRetryStatus = RetryStatus {attempts = 0, delay = 0, totalDelay = 0},
{ initialRetryStatus =
RetryStatus
{ attempts = 0,
delay = 0,
totalDelay = 0,
reset = pure ()
},
maxAttempts = 10,
maxTime = 45.0,
backoffInitialRetryDelay = 0.1,
@ -52,10 +53,10 @@ defaults =
backoffExpBase = 2.0
}
data RetryAction =
Skip -- Propagate the exception.
| Retry -- Retry with the delay according to the settings.
| RetryDelay DiffTime -- Retry after the given delay.
data RetryAction
= Skip -- Propagate the exception.
| Retry -- Retry with the delay according to the settings.
| RetryDelay DiffTime -- Retry after the given delay.
-- | Retry on all sync exceptions, async exceptions will still be thrown.
--

View File

@ -73,7 +73,7 @@ library
-- other-extensions:
-- Other library packages from which modules are imported.
build-depends: base, http-client, time
build-depends: base, http-client, time, retry
-- Directories containing source files.
hs-source-dirs: src