module Network.Nakadi.Internal.Retry
( retryAction
) where
import Network.Nakadi.Internal.Prelude
import Control.Lens
import Control.Retry
import Network.HTTP.Client
import Network.HTTP.Types.Status
import qualified Network.Nakadi.Internal.Lenses as L
import Network.Nakadi.Internal.Types.Config
invokeHttpErrorCallback ::
(MonadIO b)
=> Config b
-> Request
-> HttpException
-> RetryStatus
-> b ()
invokeHttpErrorCallback config req exn retryStatus =
case config^.L.httpErrorCallback of
Just cb -> do
finalFailure <- isFinalFailure
cb req exn retryStatus finalFailure
Nothing -> pure ()
where isFinalFailure = do
let policy = liftIORetryPolicy (config^.L.retryPolicy)
applyPolicy policy retryStatus >>= \case
Just _ -> pure False
Nothing -> pure True
liftIORetryPolicy :: MonadIO b => RetryPolicyM IO -> RetryPolicyM b
liftIORetryPolicy rp = RetryPolicyM $ liftIO . getRetryPolicyM rp
retryAction ::
(MonadIO b, MonadMask b)
=> Config b
-> Request
-> (Request -> b a)
-> b a
retryAction config req ma =
let policy = liftIORetryPolicy (config^.L.retryPolicy)
in recovering policy [handlerHttp] (\_retryStatus -> ma req)
where handlerHttp retryStatus = Handler $ \exn -> do
invokeHttpErrorCallback config req exn retryStatus
pure $ shouldRetry exn
shouldRetry (HttpExceptionRequest _ exceptionContent) =
case exceptionContent of
StatusCodeException response _ ->
responseStatus response `elem` [status500, status503]
ResponseTimeout ->
True
ConnectionTimeout ->
True
ConnectionFailure _ ->
True
InternalException _ ->
True
ConnectionClosed ->
True
_ ->
False
shouldRetry _ = False