polysemy-conc-0.3.0.0: lib/Polysemy/Conc/Retry.hs
-- |Description: Action Retrying
module Polysemy.Conc.Retry where
import qualified Polysemy.Time as Time
import Polysemy.Time (Time, TimeUnit)
import Polysemy.Conc.Effect.Race (Race)
import qualified Polysemy.Conc.Effect.Sync as Sync
import Polysemy.Conc.Interpreter.Sync (interpretSync)
import qualified Polysemy.Conc.Race as Race
-- |Run an action repeatedly until it returns 'Right' or the timout has been exceeded.
retrying ::
∀ e w u t d r a .
TimeUnit w =>
TimeUnit u =>
Members [Race, Time t d] r =>
-- |The timeout after which the attempt is abandoned.
w ->
-- |The waiting interval between two tries.
u ->
Sem r (Either e a) ->
Sem r (Maybe a)
retrying timeout interval action =
Race.timeoutMaybe timeout spin
where
spin =
action >>= \case
Right a ->
pure a
Left _ -> do
Time.sleep @t @d interval
spin
-- |Run an action repeatedly until it returns 'Right' or the timout has been exceeded.
--
-- If the action failed at least once, the last error will be returned in case of timeout.
retryingWithError ::
∀ e w u t d r a .
TimeUnit w =>
TimeUnit u =>
Members [Race, Time t d, Embed IO] r =>
-- |The timeout after which the attempt is abandoned.
w ->
-- |The waiting interval between two tries.
u ->
Sem r (Either e a) ->
Sem r (Maybe (Either e a))
retryingWithError timeout interval action =
interpretSync @e do
Race.timeoutMaybe timeout spin >>= \case
Just a -> pure (Just (Right a))
Nothing -> fmap Left <$> Sync.takeTry
where
spin =
raise action >>= \case
Right a ->
pure a
Left e -> do
void (Sync.takeTry @e)
Sync.putTry e
Time.sleep @t @d interval
spin