From ad977f724860bd55abf4f933bac5f96952e1ec08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Thu, 21 Dec 2023 12:09:45 +0000 Subject: [PATCH] Add reset --- README.md | 11 ++++++++--- src/Stamina.hs | 33 +++++++++++++++++---------------- stamina.cabal | 2 +- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 5c8a038..7fee246 100644 --- a/README.md +++ b/README.md @@ -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. \ No newline at end of file +- [retry](https://github.com/Soostone/retry) as case study for what needs to be supported. diff --git a/src/Stamina.hs b/src/Stamina.hs index 79e83ac..49e6b71 100644 --- a/src/Stamina.hs +++ b/src/Stamina.hs @@ -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. -- diff --git a/stamina.cabal b/stamina.cabal index 4530465..f0c2e98 100644 --- a/stamina.cabal +++ b/stamina.cabal @@ -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