module Network.Nakadi.Internal.Retry
( retryAction
) where
import Network.Nakadi.Internal.Prelude
import Control.Lens
import Control.Monad.IO.Class
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
invokeHttpErrorCallback :: MonadIO m => Config -> Request -> HttpException -> RetryStatus -> m ()
invokeHttpErrorCallback config req exn retryStatus = liftIO $
case config^.L.httpErrorCallback of
Just cb -> do
finalFailure <- applyPolicy (config^.L.retryPolicy) retryStatus >>= \case
Just _ -> pure False
Nothing -> pure True
cb req exn retryStatus finalFailure
Nothing -> pure ()
retryAction ::
(MonadIO m, MonadMask m)
=> Config
-> Request
-> (Request -> m a)
-> m a
retryAction config req ma =
let policy = config^.L.retryPolicy
nakadiRetryPolicy = RetryPolicyM $ \retryStatus ->
liftIO (getRetryPolicyM policy retryStatus)
in recovering nakadiRetryPolicy [handlerHttp] (const (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