As we deal with networking and databases in our day-to-day work, Haskell exceptions frequently arise in our code.
We’ve been using the Haskell retry package for retrying exceptions so far, but it presents several issues:
- The API is cumbersome to remember, so we’ve always built a thin layer on top.
- It lacks built-in support for retrying HTTP exceptions, which requires careful selection of retryable instances and adherence to the retry-after header.
- To log the exception that occurred, one needs to write a logger as an exception handler.
- It’s not possible to reset the retry state when a long-lived task (such as a WebSocket connection) finally succeeds.
Heavily inspired by Hynek’s Stamina for Python, we’re releasing Stamina for Haskell:
- Exponential backoff with random jitter between retries.
- Limit the attempts of retries and total time.
- Stamina.HTTP for retrying retriable
Network.HTTP.Client
exceptions respectingRetry-After
header. - Introspectable retry state for logging using
RetryStatus
, including the last exception that occurred. - Supports resetting the retry state for long-running tasks whenever a retry attempt succeeds.
Basic example
import qualified Stamina
import Control.Monad.Catch (throwM)
go :: IO ()
go = Stamina.retry Stamina.defaults $ \retryStatus -> do
print $ show $ Stamina.lastException retryStatus
throwM $ userError "nope"
For more examples see README.md.
Domen