packages feed

capataz 0.1.0.1 → 0.2.0.0

raw patch · 18 files changed

+1250/−724 lines, 18 filesdep +prettyprinterdep +riodep −data-defaultdep −microlensdep −protoludedep ~basedep ~bytestringdep ~pretty-showPVP ok

version bump matches the API change (PVP)

Dependencies added: prettyprinter, rio

Dependencies removed: data-default, microlens, protolude, safe-exceptions, stm, tasty-rerun, text, unordered-containers, vector

Dependency ranges changed: base, bytestring, pretty-show, tasty, tasty-hunit, tasty-smallcheck, teardown, time, uuid

API changes (from Hackage documentation)

- Control.Concurrent.Capataz: (.~) :: () => ASetter s t a b -> b -> s -> t
- Control.Concurrent.Capataz: infixr 4 .~
- Control.Concurrent.Capataz: teardown :: ITeardown teardown => teardown -> IO TeardownResult
- Control.Concurrent.Capataz.Internal.Types: instance Control.Teardown.Internal.Types.ITeardown Control.Concurrent.Capataz.Internal.Types.Capataz
- Control.Concurrent.Capataz.Internal.Types: instance Data.Default.Class.Default Control.Concurrent.Capataz.Internal.Types.ProcessTerminationOrder
- Control.Concurrent.Capataz.Internal.Types: instance Data.Default.Class.Default Control.Concurrent.Capataz.Internal.Types.SupervisorRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: instance Data.Default.Class.Default Control.Concurrent.Capataz.Internal.Types.WorkerRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: instance Data.Default.Class.Default Control.Concurrent.Capataz.Internal.Types.WorkerTerminationPolicy
- Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic Control.Concurrent.Capataz.Internal.Types.ControlAction
- Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic Control.Concurrent.Capataz.Internal.Types.SupervisorMessage
- Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic Control.Concurrent.Capataz.Internal.Types.WorkerOptions
- Control.Concurrent.Capataz.Internal.Types: type ProcessThreadId = ThreadId
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorIntensity Control.Concurrent.Capataz.Internal.Types.CapatazOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorIntensity Control.Concurrent.Capataz.Internal.Types.SupervisorOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorPeriodSeconds Control.Concurrent.Capataz.Internal.Types.CapatazOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorPeriodSeconds Control.Concurrent.Capataz.Internal.Types.SupervisorOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorProcessTerminationOrder Control.Concurrent.Capataz.Internal.Types.CapatazOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorProcessTerminationOrder Control.Concurrent.Capataz.Internal.Types.SupervisorOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorRestartStrategy Control.Concurrent.Capataz.Internal.Types.CapatazOptions
- Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorRestartStrategy Control.Concurrent.Capataz.Internal.Types.SupervisorOptions
+ Control.Concurrent.Capataz: data TeardownResult :: *
+ Control.Concurrent.Capataz: terminateCapataz :: MonadIO m => Capataz m -> m TeardownResult
+ Control.Concurrent.Capataz: terminateCapataz_ :: MonadIO m => Capataz m -> m ()
+ Control.Concurrent.Capataz: type SupervisorName = Text
+ Control.Concurrent.Capataz: type WorkerName = Text
+ Control.Concurrent.Capataz.Internal.Core: terminateCapataz :: MonadIO m => Capataz m -> m TeardownResult
+ Control.Concurrent.Capataz.Internal.Core: terminateCapataz_ :: MonadIO m => Capataz m -> m ()
+ Control.Concurrent.Capataz.Internal.Types: PTID :: ThreadId -> ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: buildWorkerOptions1 :: Monad m => WorkerName -> (WorkerId -> m ()) -> (WorkerOptions m -> WorkerOptions m) -> WorkerOptions m
+ Control.Concurrent.Capataz.Internal.Types: defProcessTerminationOrder :: ProcessTerminationOrder
+ Control.Concurrent.Capataz.Internal.Types: defSupervisorRestartStategy :: SupervisorRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: defWorkerRestartStrategy :: WorkerRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: defWorkerTerminationPolicy :: WorkerTerminationPolicy
+ Control.Concurrent.Capataz.Internal.Types: fromAnyException :: Exception e => SomeException -> Maybe e
+ Control.Concurrent.Capataz.Internal.Types: getMaskingState :: MonadIO m => m MaskingState
+ Control.Concurrent.Capataz.Internal.Types: instance Control.Teardown.Internal.Types.HasTeardown (Control.Concurrent.Capataz.Internal.Types.Capataz m)
+ Control.Concurrent.Capataz.Internal.Types: instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Concurrent.Capataz.Internal.Types.CallbackType
+ Control.Concurrent.Capataz.Internal.Types: instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Concurrent.Capataz.Internal.Types.CapatazEvent
+ Control.Concurrent.Capataz.Internal.Types: instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Concurrent.Capataz.Internal.Types.ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Concurrent.Capataz.Internal.Types.ProcessType
+ Control.Concurrent.Capataz.Internal.Types: instance Data.Text.Prettyprint.Doc.Internal.Pretty Control.Concurrent.Capataz.Internal.Types.SupervisorStatus
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Classes.Eq Control.Concurrent.Capataz.Internal.Types.ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic (Control.Concurrent.Capataz.Internal.Types.ControlAction m)
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic (Control.Concurrent.Capataz.Internal.Types.SupervisorMessage m)
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic (Control.Concurrent.Capataz.Internal.Types.WorkerOptions m)
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Generics.Generic Control.Concurrent.Capataz.Internal.Types.ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: instance GHC.Show.Show Control.Concurrent.Capataz.Internal.Types.ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: instance RIO.Prelude.Display.Display Control.Concurrent.Capataz.Internal.Types.CapatazEvent
+ Control.Concurrent.Capataz.Internal.Types: newtype ProcessThreadId
+ Control.Concurrent.Capataz.Internal.Types: unsafeTry :: (Exception e, MonadUnliftIO m) => m a -> m (Either e a)
+ Control.Concurrent.Capataz.Internal.Types: workerSpec1 :: Monad m => WorkerName -> (WorkerId -> m ()) -> (WorkerOptions m -> WorkerOptions m) -> ProcessSpec m
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorIntensity (Control.Concurrent.Capataz.Internal.Types.CapatazOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorIntensity (Control.Concurrent.Capataz.Internal.Types.SupervisorOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorPeriodSeconds (Control.Concurrent.Capataz.Internal.Types.CapatazOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorPeriodSeconds (Control.Concurrent.Capataz.Internal.Types.SupervisorOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorProcessTerminationOrder (Control.Concurrent.Capataz.Internal.Types.CapatazOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorProcessTerminationOrder (Control.Concurrent.Capataz.Internal.Types.SupervisorOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorRestartStrategy (Control.Concurrent.Capataz.Internal.Types.CapatazOptions m)
+ Control.Concurrent.Capataz.Internal.Types.Lens: instance Control.Concurrent.Capataz.Internal.Types.Lens.HasSupervisorRestartStrategy (Control.Concurrent.Capataz.Internal.Types.SupervisorOptions m)
- Control.Concurrent.Capataz: SupervisorSpec :: SupervisorOptions -> ProcessSpec
+ Control.Concurrent.Capataz: SupervisorSpec :: (SupervisorOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz: WorkerSpec :: WorkerOptions -> ProcessSpec
+ Control.Concurrent.Capataz: WorkerSpec :: (WorkerOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz: buildSupervisorOptions :: SupervisorName -> (SupervisorOptions -> SupervisorOptions) -> SupervisorOptions
+ Control.Concurrent.Capataz: buildSupervisorOptions :: Monad m => SupervisorName -> (SupervisorOptions m -> SupervisorOptions m) -> SupervisorOptions m
- Control.Concurrent.Capataz: buildSupervisorOptionsWithDefaults :: SupervisorName -> SupervisorOptions
+ Control.Concurrent.Capataz: buildSupervisorOptionsWithDefaults :: Monad m => SupervisorName -> SupervisorOptions m
- Control.Concurrent.Capataz: buildWorkerOptions :: WorkerName -> IO () -> (WorkerOptions -> WorkerOptions) -> WorkerOptions
+ Control.Concurrent.Capataz: buildWorkerOptions :: Monad m => WorkerName -> m () -> (WorkerOptions m -> WorkerOptions m) -> WorkerOptions m
- Control.Concurrent.Capataz: buildWorkerOptionsWithDefaults :: WorkerName -> IO () -> WorkerOptions
+ Control.Concurrent.Capataz: buildWorkerOptionsWithDefaults :: Monad m => WorkerName -> m () -> WorkerOptions m
- Control.Concurrent.Capataz: data Capataz
+ Control.Concurrent.Capataz: data Capataz m
- Control.Concurrent.Capataz: data CapatazOptions
+ Control.Concurrent.Capataz: data CapatazOptions m
- Control.Concurrent.Capataz: data ProcessSpec
+ Control.Concurrent.Capataz: data ProcessSpec m
- Control.Concurrent.Capataz: data Supervisor
+ Control.Concurrent.Capataz: data Supervisor m
- Control.Concurrent.Capataz: data SupervisorOptions
+ Control.Concurrent.Capataz: data SupervisorOptions m
- Control.Concurrent.Capataz: data WorkerOptions
+ Control.Concurrent.Capataz: data WorkerOptions m
- Control.Concurrent.Capataz: forkCapataz :: Text -> (CapatazOptions -> CapatazOptions) -> IO Capataz
+ Control.Concurrent.Capataz: forkCapataz :: (MonadUnliftIO m, MonadIO m) => Text -> (CapatazOptions m -> CapatazOptions m) -> m (Capataz m)
- Control.Concurrent.Capataz: forkSupervisor :: HasSupervisor parentSupervisor => SupervisorOptions -> parentSupervisor -> IO Supervisor
+ Control.Concurrent.Capataz: forkSupervisor :: (MonadIO m, HasSupervisor parentSupervisor) => SupervisorOptions m -> parentSupervisor m -> m (Supervisor m)
- Control.Concurrent.Capataz: forkWorker :: HasSupervisor supervisor => WorkerOptions -> supervisor -> IO WorkerId
+ Control.Concurrent.Capataz: forkWorker :: (MonadIO m, HasSupervisor supervisor) => WorkerOptions m -> supervisor m -> m WorkerId
- Control.Concurrent.Capataz: getCapatazTeardown :: Capataz -> Teardown
+ Control.Concurrent.Capataz: getCapatazTeardown :: Capataz m -> Teardown
- Control.Concurrent.Capataz: getSupervisor :: HasSupervisor a => a -> Supervisor
+ Control.Concurrent.Capataz: getSupervisor :: HasSupervisor a => a m -> Supervisor m
- Control.Concurrent.Capataz: getSupervisorAsync :: Supervisor -> Async ()
+ Control.Concurrent.Capataz: getSupervisorAsync :: Supervisor m -> Async ()
- Control.Concurrent.Capataz: getSupervisorProcessId :: Supervisor -> ProcessId
+ Control.Concurrent.Capataz: getSupervisorProcessId :: Supervisor m -> ProcessId
- Control.Concurrent.Capataz: joinCapatazThread :: Capataz -> IO ()
+ Control.Concurrent.Capataz: joinCapatazThread :: MonadIO m => Capataz m -> m ()
- Control.Concurrent.Capataz: onSystemEventL :: Functor f => ((CapatazEvent -> IO ()) -> f (CapatazEvent -> IO ())) -> CapatazOptions -> f CapatazOptions
+ Control.Concurrent.Capataz: onSystemEventL :: Functor f => ((CapatazEvent -> m ()) -> f (CapatazEvent -> m ())) -> CapatazOptions m -> f (CapatazOptions m)
- Control.Concurrent.Capataz: supervisorOnFailureL :: (HasSupervisorFailureCallback s, Functor f) => ((SomeException -> IO ()) -> f (SomeException -> IO ())) -> s -> f s
+ Control.Concurrent.Capataz: supervisorOnFailureL :: (HasSupervisorFailureCallback s, Functor f) => ((SomeException -> m ()) -> f (SomeException -> m ())) -> s m -> f (s m)
- Control.Concurrent.Capataz: supervisorOnIntensityReachedL :: (HasSupervisorIntensityReachedCallback s, Functor f) => (IO () -> f (IO ())) -> s -> f s
+ Control.Concurrent.Capataz: supervisorOnIntensityReachedL :: (HasSupervisorIntensityReachedCallback s, Functor f) => (m () -> f (m ())) -> s m -> f (s m)
- Control.Concurrent.Capataz: supervisorProcessSpecListL :: (HasSupervisorProcessSpecList s, Functor f) => ([ProcessSpec] -> f [ProcessSpec]) -> s -> f s
+ Control.Concurrent.Capataz: supervisorProcessSpecListL :: (HasSupervisorProcessSpecList s, Functor f) => ([ProcessSpec m] -> f [ProcessSpec m]) -> s m -> f (s m)
- Control.Concurrent.Capataz: supervisorSpec :: SupervisorName -> (SupervisorOptions -> SupervisorOptions) -> ProcessSpec
+ Control.Concurrent.Capataz: supervisorSpec :: Monad m => SupervisorName -> (SupervisorOptions m -> SupervisorOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz: supervisorSpecWithDefaults :: SupervisorName -> ProcessSpec
+ Control.Concurrent.Capataz: supervisorSpecWithDefaults :: Monad m => SupervisorName -> ProcessSpec m
- Control.Concurrent.Capataz: terminateProcess :: HasSupervisor supervisor => Text -> ProcessId -> supervisor -> IO Bool
+ Control.Concurrent.Capataz: terminateProcess :: (MonadIO m, HasSupervisor supervisor) => Text -> ProcessId -> supervisor m -> m Bool
- Control.Concurrent.Capataz: workerOnCompletionL :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz: workerOnCompletionL :: (Functor f) => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz: workerOnFailureL :: Functor f => ((SomeException -> IO ()) -> f (SomeException -> IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz: workerOnFailureL :: (Functor f) => ((SomeException -> m ()) -> f (SomeException -> m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz: workerOnTerminationL :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz: workerOnTerminationL :: Functor f => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz: workerRestartStrategyL :: Functor f => (WorkerRestartStrategy -> f WorkerRestartStrategy) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz: workerRestartStrategyL :: Functor f => (WorkerRestartStrategy -> f WorkerRestartStrategy) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz: workerSpec :: WorkerName -> IO () -> (WorkerOptions -> WorkerOptions) -> ProcessSpec
+ Control.Concurrent.Capataz: workerSpec :: Monad m => WorkerName -> m () -> (WorkerOptions m -> WorkerOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz: workerSpecWithDefaults :: WorkerName -> IO () -> ProcessSpec
+ Control.Concurrent.Capataz: workerSpecWithDefaults :: Monad m => WorkerName -> m () -> ProcessSpec m
- Control.Concurrent.Capataz: workerTerminationPolicyL :: Functor f => (WorkerTerminationPolicy -> f WorkerTerminationPolicy) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz: workerTerminationPolicyL :: Functor f => (WorkerTerminationPolicy -> f WorkerTerminationPolicy) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Core: forkCapataz :: Text -> (CapatazOptions -> CapatazOptions) -> IO Capataz
+ Control.Concurrent.Capataz.Internal.Core: forkCapataz :: (MonadUnliftIO m, MonadIO m) => Text -> (CapatazOptions m -> CapatazOptions m) -> m (Capataz m)
- Control.Concurrent.Capataz.Internal.Core: forkSupervisor :: HasSupervisor parentSupervisor => SupervisorOptions -> parentSupervisor -> IO Supervisor
+ Control.Concurrent.Capataz.Internal.Core: forkSupervisor :: (MonadIO m, HasSupervisor parentSupervisor) => SupervisorOptions m -> parentSupervisor m -> m (Supervisor m)
- Control.Concurrent.Capataz.Internal.Core: forkWorker :: HasSupervisor supervisor => WorkerOptions -> supervisor -> IO WorkerId
+ Control.Concurrent.Capataz.Internal.Core: forkWorker :: (MonadIO m, HasSupervisor supervisor) => WorkerOptions m -> supervisor m -> m WorkerId
- Control.Concurrent.Capataz.Internal.Core: getCapatazTeardown :: Capataz -> Teardown
+ Control.Concurrent.Capataz.Internal.Core: getCapatazTeardown :: Capataz m -> Teardown
- Control.Concurrent.Capataz.Internal.Core: getSupervisor :: HasSupervisor a => a -> Supervisor
+ Control.Concurrent.Capataz.Internal.Core: getSupervisor :: HasSupervisor a => a m -> Supervisor m
- Control.Concurrent.Capataz.Internal.Core: getSupervisorAsync :: Supervisor -> Async ()
+ Control.Concurrent.Capataz.Internal.Core: getSupervisorAsync :: Supervisor m -> Async ()
- Control.Concurrent.Capataz.Internal.Core: getSupervisorProcessId :: Supervisor -> ProcessId
+ Control.Concurrent.Capataz.Internal.Core: getSupervisorProcessId :: Supervisor m -> ProcessId
- Control.Concurrent.Capataz.Internal.Core: joinCapatazThread :: Capataz -> IO ()
+ Control.Concurrent.Capataz.Internal.Core: joinCapatazThread :: MonadIO m => Capataz m -> m ()
- Control.Concurrent.Capataz.Internal.Core: terminateProcess :: HasSupervisor supervisor => Text -> ProcessId -> supervisor -> IO Bool
+ Control.Concurrent.Capataz.Internal.Core: terminateProcess :: (MonadIO m, HasSupervisor supervisor) => Text -> ProcessId -> supervisor m -> m Bool
- Control.Concurrent.Capataz.Internal.Supervisor: buildSupervisorEnv :: (CapatazEvent -> IO ()) -> (SupervisorMessage -> IO ()) -> STM SupervisorMessage -> SupervisorId -> SupervisorOptions -> IO SupervisorEnv
+ Control.Concurrent.Capataz.Internal.Supervisor: buildSupervisorEnv :: MonadIO m => (CapatazEvent -> m ()) -> (SupervisorMessage m -> m ()) -> STM (SupervisorMessage m) -> SupervisorId -> SupervisorOptions m -> m (SupervisorEnv m)
- Control.Concurrent.Capataz.Internal.Supervisor: calcDiffSeconds :: UTCTime -> IO NominalDiffTime
+ Control.Concurrent.Capataz.Internal.Supervisor: calcDiffSeconds :: MonadIO m => UTCTime -> m NominalDiffTime
- Control.Concurrent.Capataz.Internal.Supervisor: calcRestartAction :: SupervisorEnv -> Int -> NominalDiffTime -> ProcessRestartAction
+ Control.Concurrent.Capataz.Internal.Supervisor: calcRestartAction :: SupervisorEnv m -> Int -> NominalDiffTime -> ProcessRestartAction
- Control.Concurrent.Capataz.Internal.Supervisor: execCapatazRestartStrategy :: SupervisorEnv -> ProcessId -> ProcessSpec -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: execCapatazRestartStrategy :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> ProcessSpec m -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: execRestartAction :: SupervisorEnv -> ProcessId -> ProcessSpec -> Text -> UTCTime -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: execRestartAction :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> ProcessSpec m -> Text -> UTCTime -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: forceRestartProcess :: SupervisorEnv -> Process -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: forceRestartProcess :: MonadIO m => SupervisorEnv m -> Process m -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: forkSupervisor :: ParentSupervisorEnv -> SupervisorOptions -> Maybe (ProcessId, RestartCount) -> IO Supervisor
+ Control.Concurrent.Capataz.Internal.Supervisor: forkSupervisor :: (MonadUnliftIO m) => ParentSupervisorEnv m -> SupervisorOptions m -> Maybe (ProcessId, RestartCount) -> m (Supervisor m)
- Control.Concurrent.Capataz.Internal.Supervisor: haltSupervisor :: Text -> SupervisorEnv -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: haltSupervisor :: (MonadUnliftIO m) => Text -> SupervisorEnv m -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleControlAction :: SupervisorEnv -> ControlAction -> IO Bool
+ Control.Concurrent.Capataz.Internal.Supervisor: handleControlAction :: (MonadUnliftIO m) => SupervisorEnv m -> ControlAction m -> m Bool
- Control.Concurrent.Capataz.Internal.Supervisor: handleMonitorEvent :: SupervisorEnv -> MonitorEvent -> IO Bool
+ Control.Concurrent.Capataz.Internal.Supervisor: handleMonitorEvent :: (MonadUnliftIO m) => SupervisorEnv m -> MonitorEvent -> m Bool
- Control.Concurrent.Capataz.Internal.Supervisor: handleProcessCompleted :: SupervisorEnv -> ProcessId -> UTCTime -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleProcessCompleted :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> UTCTime -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleProcessFailed :: SupervisorEnv -> WorkerId -> SomeException -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleProcessFailed :: (MonadUnliftIO m) => SupervisorEnv m -> WorkerId -> SomeException -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleProcessTerminated :: SupervisorEnv -> ProcessId -> Text -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleProcessTerminated :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> Text -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorFailed :: SupervisorEnv -> Supervisor -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorFailed :: (MonadUnliftIO m) => SupervisorEnv m -> Supervisor m -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorMessage :: SupervisorEnv -> SupervisorMessage -> IO Bool
+ Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorMessage :: (MonadUnliftIO m) => SupervisorEnv m -> SupervisorMessage m -> m Bool
- Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorTerminated :: SupervisorEnv -> Supervisor -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleSupervisorTerminated :: (MonadUnliftIO m) => SupervisorEnv m -> Supervisor m -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerCompleted :: SupervisorEnv -> Worker -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerCompleted :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerFailed :: SupervisorEnv -> Worker -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerFailed :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerTerminated :: SupervisorEnv -> Worker -> Int -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: handleWorkerTerminated :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> Int -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: restartProcessList :: SupervisorEnv -> WorkerId -> RestartCount -> IO [Process]
+ Control.Concurrent.Capataz.Internal.Supervisor: restartProcessList :: (MonadUnliftIO m) => SupervisorEnv m -> WorkerId -> RestartCount -> m [Process m]
- Control.Concurrent.Capataz.Internal.Supervisor: restartSupervisor :: ParentSupervisorEnv -> SupervisorOptions -> ProcessId -> RestartCount -> IO Process
+ Control.Concurrent.Capataz.Internal.Supervisor: restartSupervisor :: (MonadUnliftIO m) => ParentSupervisorEnv m -> SupervisorOptions m -> ProcessId -> RestartCount -> m (Process m)
- Control.Concurrent.Capataz.Internal.Supervisor: restartWorker :: SupervisorEnv -> WorkerOptions -> WorkerId -> RestartCount -> IO Process
+ Control.Concurrent.Capataz.Internal.Supervisor: restartWorker :: (MonadUnliftIO m) => SupervisorEnv m -> WorkerOptions m -> WorkerId -> RestartCount -> m (Process m)
- Control.Concurrent.Capataz.Internal.Supervisor: supervisorLoop :: (forall b. IO b -> IO b) -> ParentSupervisorEnv -> SupervisorEnv -> RestartCount -> IO ()
+ Control.Concurrent.Capataz.Internal.Supervisor: supervisorLoop :: (MonadUnliftIO m) => (forall b. m b -> m b) -> ParentSupervisorEnv m -> SupervisorEnv m -> RestartCount -> m ()
- Control.Concurrent.Capataz.Internal.Supervisor: supervisorMain :: ParentSupervisorEnv -> SupervisorOptions -> SupervisorId -> RestartCount -> IO Supervisor
+ Control.Concurrent.Capataz.Internal.Supervisor: supervisorMain :: (MonadUnliftIO m) => ParentSupervisorEnv m -> SupervisorOptions m -> SupervisorId -> RestartCount -> m (Supervisor m)
- Control.Concurrent.Capataz.Internal.Types: Capataz :: !Supervisor -> !Teardown -> Capataz
+ Control.Concurrent.Capataz.Internal.Types: Capataz :: !(Supervisor m) -> !Teardown -> Capataz m
- Control.Concurrent.Capataz.Internal.Types: CapatazOptions :: !SupervisorName -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> ![ProcessSpec] -> !ProcessTerminationOrder -> !(IO ()) -> !(SomeException -> IO ()) -> !(CapatazEvent -> IO ()) -> CapatazOptions
+ Control.Concurrent.Capataz.Internal.Types: CapatazOptions :: !SupervisorName -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> ![ProcessSpec m] -> !ProcessTerminationOrder -> !(m ()) -> !(SomeException -> m ()) -> !(CapatazEvent -> m ()) -> CapatazOptions m
- Control.Concurrent.Capataz.Internal.Types: ControlAction :: !ControlAction -> SupervisorMessage
+ Control.Concurrent.Capataz.Internal.Types: ControlAction :: !(ControlAction m) -> SupervisorMessage m
- Control.Concurrent.Capataz.Internal.Types: ForkSupervisor :: !SupervisorOptions -> !(Supervisor -> IO ()) -> ControlAction
+ Control.Concurrent.Capataz.Internal.Types: ForkSupervisor :: !(SupervisorOptions m) -> !(Supervisor m -> m ()) -> ControlAction m
- Control.Concurrent.Capataz.Internal.Types: ForkWorker :: !WorkerOptions -> !(WorkerId -> IO ()) -> ControlAction
+ Control.Concurrent.Capataz.Internal.Types: ForkWorker :: !(WorkerOptions m) -> !(WorkerId -> m ()) -> ControlAction m
- Control.Concurrent.Capataz.Internal.Types: MonitorEvent :: !MonitorEvent -> SupervisorMessage
+ Control.Concurrent.Capataz.Internal.Types: MonitorEvent :: !MonitorEvent -> SupervisorMessage m
- Control.Concurrent.Capataz.Internal.Types: ParentSupervisorEnv :: !SupervisorId -> !SupervisorName -> !(SupervisorMessage -> IO ()) -> !(CapatazEvent -> IO ()) -> ParentSupervisorEnv
+ Control.Concurrent.Capataz.Internal.Types: ParentSupervisorEnv :: !SupervisorId -> !SupervisorName -> !(SupervisorMessage m -> m ()) -> !(CapatazEvent -> m ()) -> ParentSupervisorEnv m
- Control.Concurrent.Capataz.Internal.Types: Supervisor :: !SupervisorId -> !SupervisorName -> !SupervisorOptions -> !UTCTime -> !(Async ()) -> (SupervisorMessage -> IO ()) -> !SupervisorEnv -> Supervisor
+ Control.Concurrent.Capataz.Internal.Types: Supervisor :: !SupervisorId -> !SupervisorName -> !(SupervisorOptions m) -> !UTCTime -> !(Async ()) -> (SupervisorMessage m -> m ()) -> !(SupervisorEnv m) -> Supervisor m
- Control.Concurrent.Capataz.Internal.Types: SupervisorEnv :: !SupervisorId -> !SupervisorName -> !(SupervisorMessage -> IO ()) -> !(STM SupervisorMessage) -> !(IORef ProcessMap) -> !(TVar SupervisorStatus) -> !SupervisorOptions -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> !ProcessTerminationOrder -> !(IO ()) -> !(SomeException -> IO ()) -> !(CapatazEvent -> IO ()) -> SupervisorEnv
+ Control.Concurrent.Capataz.Internal.Types: SupervisorEnv :: !SupervisorId -> !SupervisorName -> !(SupervisorMessage m -> m ()) -> !(STM (SupervisorMessage m)) -> !(IORef (ProcessMap m)) -> !(TVar SupervisorStatus) -> !(SupervisorOptions m) -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> !ProcessTerminationOrder -> !(m ()) -> !(SomeException -> m ()) -> !(CapatazEvent -> m ()) -> SupervisorEnv m
- Control.Concurrent.Capataz.Internal.Types: SupervisorOptions :: Text -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> ![ProcessSpec] -> !ProcessTerminationOrder -> !(IO ()) -> !(SomeException -> IO ()) -> SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: SupervisorOptions :: Text -> !Int -> !NominalDiffTime -> !SupervisorRestartStrategy -> ![ProcessSpec m] -> !ProcessTerminationOrder -> !(m ()) -> !(SomeException -> m ()) -> SupervisorOptions m
- Control.Concurrent.Capataz.Internal.Types: SupervisorProcess :: Supervisor -> Process
+ Control.Concurrent.Capataz.Internal.Types: SupervisorProcess :: !(Supervisor m) -> Process m
- Control.Concurrent.Capataz.Internal.Types: SupervisorSpec :: SupervisorOptions -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: SupervisorSpec :: (SupervisorOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: TerminateProcess :: !ProcessId -> !Text -> !(Bool -> IO ()) -> ControlAction
+ Control.Concurrent.Capataz.Internal.Types: TerminateProcess :: !ProcessId -> !Text -> !(Bool -> m ()) -> ControlAction m
- Control.Concurrent.Capataz.Internal.Types: Worker :: !WorkerId -> !(Async ()) -> !UTCTime -> !WorkerName -> !WorkerOptions -> Worker
+ Control.Concurrent.Capataz.Internal.Types: Worker :: !WorkerId -> !(Async ()) -> !UTCTime -> !WorkerName -> !(WorkerOptions m) -> Worker m
- Control.Concurrent.Capataz.Internal.Types: WorkerOptions :: WorkerAction -> !WorkerName -> !(SomeException -> IO ()) -> !(IO ()) -> !(IO ()) -> !WorkerTerminationPolicy -> !WorkerRestartStrategy -> WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: WorkerOptions :: WorkerAction m -> !WorkerName -> !(SomeException -> m ()) -> !(m ()) -> !(m ()) -> !WorkerTerminationPolicy -> !WorkerRestartStrategy -> WorkerOptions m
- Control.Concurrent.Capataz.Internal.Types: WorkerProcess :: Worker -> Process
+ Control.Concurrent.Capataz.Internal.Types: WorkerProcess :: !(Worker m) -> Process m
- Control.Concurrent.Capataz.Internal.Types: WorkerSpec :: WorkerOptions -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: WorkerSpec :: (WorkerOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: [$sel:capatazSupervisor:Capataz] :: Capataz -> !Supervisor
+ Control.Concurrent.Capataz.Internal.Types: [$sel:capatazSupervisor:Capataz] :: Capataz m -> !(Supervisor m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:capatazTeardown:Capataz] :: Capataz -> !Teardown
+ Control.Concurrent.Capataz.Internal.Types: [$sel:capatazTeardown:Capataz] :: Capataz m -> !Teardown
- Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:CapatazOptions] :: CapatazOptions -> !(CapatazEvent -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:CapatazOptions] :: CapatazOptions m -> !(CapatazEvent -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:ParentSupervisorEnv] :: ParentSupervisorEnv -> !(CapatazEvent -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:ParentSupervisorEnv] :: ParentSupervisorEnv m -> !(CapatazEvent -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:SupervisorEnv] :: SupervisorEnv -> !(CapatazEvent -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:notifyEvent:SupervisorEnv] :: SupervisorEnv m -> !(CapatazEvent -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:notifyProcessTermination:ForkWorker] :: ControlAction -> !(Bool -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:notifyProcessTermination:ForkWorker] :: ControlAction m -> !(Bool -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:processId:ForkWorker] :: ControlAction -> !ProcessId
+ Control.Concurrent.Capataz.Internal.Types: [$sel:processId:ForkWorker] :: ControlAction m -> !ProcessId
- Control.Concurrent.Capataz.Internal.Types: [$sel:processTerminationReason:ForkWorker] :: ControlAction -> !Text
+ Control.Concurrent.Capataz.Internal.Types: [$sel:processTerminationReason:ForkWorker] :: ControlAction m -> !Text
- Control.Concurrent.Capataz.Internal.Types: [$sel:returnSupervisor:ForkWorker] :: ControlAction -> !(Supervisor -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:returnSupervisor:ForkWorker] :: ControlAction m -> !(Supervisor m -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:returnWorkerId:ForkWorker] :: ControlAction -> !(WorkerId -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:returnWorkerId:ForkWorker] :: ControlAction m -> !(WorkerId -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorAsync:Supervisor] :: Supervisor -> !(Async ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorAsync:Supervisor] :: Supervisor m -> !(Async ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorCreationTime:Supervisor] :: Supervisor -> !UTCTime
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorCreationTime:Supervisor] :: Supervisor m -> !UTCTime
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorEnv:Supervisor] :: Supervisor -> !SupervisorEnv
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorEnv:Supervisor] :: Supervisor m -> !(SupervisorEnv m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorGetNotification:SupervisorEnv] :: SupervisorEnv -> !(STM SupervisorMessage)
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorGetNotification:SupervisorEnv] :: SupervisorEnv m -> !(STM (SupervisorMessage m))
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:ParentSupervisorEnv] :: ParentSupervisorEnv -> !SupervisorId
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:ParentSupervisorEnv] :: ParentSupervisorEnv m -> !SupervisorId
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:SupervisorEnv] :: SupervisorEnv -> !SupervisorId
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:SupervisorEnv] :: SupervisorEnv m -> !SupervisorId
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:Supervisor] :: Supervisor -> !SupervisorId
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorId:Supervisor] :: Supervisor m -> !SupervisorId
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:CapatazOptions] :: CapatazOptions -> !Int
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:CapatazOptions] :: CapatazOptions m -> !Int
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:SupervisorEnv] :: SupervisorEnv -> !Int
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:SupervisorEnv] :: SupervisorEnv m -> !Int
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:SupervisorOptions] :: SupervisorOptions -> !Int
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorIntensity:SupervisorOptions] :: SupervisorOptions m -> !Int
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:CapatazOptions] :: CapatazOptions -> !SupervisorName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:CapatazOptions] :: CapatazOptions m -> !SupervisorName
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:ParentSupervisorEnv] :: ParentSupervisorEnv -> !SupervisorName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:ParentSupervisorEnv] :: ParentSupervisorEnv m -> !SupervisorName
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:SupervisorEnv] :: SupervisorEnv -> !SupervisorName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:SupervisorEnv] :: SupervisorEnv m -> !SupervisorName
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:SupervisorOptions] :: SupervisorOptions -> Text
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:SupervisorOptions] :: SupervisorOptions m -> Text
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:Supervisor] :: Supervisor -> !SupervisorName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorName:Supervisor] :: Supervisor m -> !SupervisorName
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:ParentSupervisorEnv] :: ParentSupervisorEnv -> !(SupervisorMessage -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:ParentSupervisorEnv] :: ParentSupervisorEnv m -> !(SupervisorMessage m -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:SupervisorEnv] :: SupervisorEnv -> !(SupervisorMessage -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:SupervisorEnv] :: SupervisorEnv m -> !(SupervisorMessage m -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:Supervisor] :: Supervisor -> SupervisorMessage -> IO ()
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorNotify:Supervisor] :: Supervisor m -> SupervisorMessage m -> m ()
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnFailure:CapatazOptions] :: CapatazOptions -> !(SomeException -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnFailure:CapatazOptions] :: CapatazOptions m -> !(SomeException -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnFailure:SupervisorOptions] :: SupervisorOptions -> !(SomeException -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnFailure:SupervisorOptions] :: SupervisorOptions m -> !(SomeException -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:CapatazOptions] :: CapatazOptions -> !(IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:CapatazOptions] :: CapatazOptions m -> !(m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:SupervisorEnv] :: SupervisorEnv -> !(SomeException -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:SupervisorEnv] :: SupervisorEnv m -> !(SomeException -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:SupervisorOptions] :: SupervisorOptions -> !(IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOnIntensityReached:SupervisorOptions] :: SupervisorOptions m -> !(m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:ForkWorker] :: ControlAction -> !SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:ForkWorker] :: ControlAction m -> !(SupervisorOptions m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:SupervisorEnv] :: SupervisorEnv -> !SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:SupervisorEnv] :: SupervisorEnv m -> !(SupervisorOptions m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:Supervisor] :: Supervisor -> !SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorOptions:Supervisor] :: Supervisor m -> !(SupervisorOptions m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:CapatazOptions] :: CapatazOptions -> !NominalDiffTime
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:CapatazOptions] :: CapatazOptions m -> !NominalDiffTime
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:SupervisorEnv] :: SupervisorEnv -> !NominalDiffTime
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:SupervisorEnv] :: SupervisorEnv m -> !NominalDiffTime
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:SupervisorOptions] :: SupervisorOptions -> !NominalDiffTime
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorPeriodSeconds:SupervisorOptions] :: SupervisorOptions m -> !NominalDiffTime
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessMap:SupervisorEnv] :: SupervisorEnv -> !(IORef ProcessMap)
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessMap:SupervisorEnv] :: SupervisorEnv m -> !(IORef (ProcessMap m))
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessSpecList:CapatazOptions] :: CapatazOptions -> ![ProcessSpec]
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessSpecList:CapatazOptions] :: CapatazOptions m -> ![ProcessSpec m]
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessSpecList:SupervisorOptions] :: SupervisorOptions -> ![ProcessSpec]
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessSpecList:SupervisorOptions] :: SupervisorOptions m -> ![ProcessSpec m]
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:CapatazOptions] :: CapatazOptions -> !ProcessTerminationOrder
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:CapatazOptions] :: CapatazOptions m -> !ProcessTerminationOrder
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:SupervisorEnv] :: SupervisorEnv -> !ProcessTerminationOrder
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:SupervisorEnv] :: SupervisorEnv m -> !ProcessTerminationOrder
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:SupervisorOptions] :: SupervisorOptions -> !ProcessTerminationOrder
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorProcessTerminationOrder:SupervisorOptions] :: SupervisorOptions m -> !ProcessTerminationOrder
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:CapatazOptions] :: CapatazOptions -> !SupervisorRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:CapatazOptions] :: CapatazOptions m -> !SupervisorRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:SupervisorEnv] :: SupervisorEnv -> !SupervisorRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:SupervisorEnv] :: SupervisorEnv m -> !SupervisorRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:SupervisorOptions] :: SupervisorOptions -> !SupervisorRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorRestartStrategy:SupervisorOptions] :: SupervisorOptions m -> !SupervisorRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorStatusVar:SupervisorEnv] :: SupervisorEnv -> !(TVar SupervisorStatus)
+ Control.Concurrent.Capataz.Internal.Types: [$sel:supervisorStatusVar:SupervisorEnv] :: SupervisorEnv m -> !(TVar SupervisorStatus)
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerAction:WorkerOptions] :: WorkerOptions -> WorkerAction
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerAction:WorkerOptions] :: WorkerOptions m -> WorkerAction m
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerAsync:Worker] :: Worker -> !(Async ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerAsync:Worker] :: Worker m -> !(Async ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerCreationTime:Worker] :: Worker -> !UTCTime
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerCreationTime:Worker] :: Worker m -> !UTCTime
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerId:Worker] :: Worker -> !WorkerId
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerId:Worker] :: Worker m -> !WorkerId
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerName:WorkerOptions] :: WorkerOptions -> !WorkerName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerName:WorkerOptions] :: WorkerOptions m -> !WorkerName
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerName:Worker] :: Worker -> !WorkerName
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerName:Worker] :: Worker m -> !WorkerName
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnCompletion:WorkerOptions] :: WorkerOptions -> !(IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnCompletion:WorkerOptions] :: WorkerOptions m -> !(m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnFailure:WorkerOptions] :: WorkerOptions -> !(SomeException -> IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnFailure:WorkerOptions] :: WorkerOptions m -> !(SomeException -> m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnTermination:WorkerOptions] :: WorkerOptions -> !(IO ())
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerOnTermination:WorkerOptions] :: WorkerOptions m -> !(m ())
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerOptions:ForkWorker] :: ControlAction -> !WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerOptions:ForkWorker] :: ControlAction m -> !(WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerOptions:Worker] :: Worker -> !WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerOptions:Worker] :: Worker m -> !(WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerRestartStrategy:WorkerOptions] :: WorkerOptions -> !WorkerRestartStrategy
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerRestartStrategy:WorkerOptions] :: WorkerOptions m -> !WorkerRestartStrategy
- Control.Concurrent.Capataz.Internal.Types: [$sel:workerTerminationPolicy:WorkerOptions] :: WorkerOptions -> !WorkerTerminationPolicy
+ Control.Concurrent.Capataz.Internal.Types: [$sel:workerTerminationPolicy:WorkerOptions] :: WorkerOptions m -> !WorkerTerminationPolicy
- Control.Concurrent.Capataz.Internal.Types: buildSupervisorOptions :: SupervisorName -> (SupervisorOptions -> SupervisorOptions) -> SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: buildSupervisorOptions :: Monad m => SupervisorName -> (SupervisorOptions m -> SupervisorOptions m) -> SupervisorOptions m
- Control.Concurrent.Capataz.Internal.Types: buildSupervisorOptionsWithDefaults :: SupervisorName -> SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: buildSupervisorOptionsWithDefaults :: Monad m => SupervisorName -> SupervisorOptions m
- Control.Concurrent.Capataz.Internal.Types: buildWorkerOptions :: WorkerName -> IO () -> (WorkerOptions -> WorkerOptions) -> WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: buildWorkerOptions :: Monad m => WorkerName -> m () -> (WorkerOptions m -> WorkerOptions m) -> WorkerOptions m
- Control.Concurrent.Capataz.Internal.Types: buildWorkerOptionsWithDefaults :: WorkerName -> IO () -> WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: buildWorkerOptionsWithDefaults :: Monad m => WorkerName -> m () -> WorkerOptions m
- Control.Concurrent.Capataz.Internal.Types: data Capataz
+ Control.Concurrent.Capataz.Internal.Types: data Capataz m
- Control.Concurrent.Capataz.Internal.Types: data CapatazOptions
+ Control.Concurrent.Capataz.Internal.Types: data CapatazOptions m
- Control.Concurrent.Capataz.Internal.Types: data ControlAction
+ Control.Concurrent.Capataz.Internal.Types: data ControlAction m
- Control.Concurrent.Capataz.Internal.Types: data ParentSupervisorEnv
+ Control.Concurrent.Capataz.Internal.Types: data ParentSupervisorEnv m
- Control.Concurrent.Capataz.Internal.Types: data Process
+ Control.Concurrent.Capataz.Internal.Types: data Process m
- Control.Concurrent.Capataz.Internal.Types: data ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: data ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: data Supervisor
+ Control.Concurrent.Capataz.Internal.Types: data Supervisor m
- Control.Concurrent.Capataz.Internal.Types: data SupervisorEnv
+ Control.Concurrent.Capataz.Internal.Types: data SupervisorEnv m
- Control.Concurrent.Capataz.Internal.Types: data SupervisorMessage
+ Control.Concurrent.Capataz.Internal.Types: data SupervisorMessage m
- Control.Concurrent.Capataz.Internal.Types: data SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Types: data SupervisorOptions m
- Control.Concurrent.Capataz.Internal.Types: data Worker
+ Control.Concurrent.Capataz.Internal.Types: data Worker m
- Control.Concurrent.Capataz.Internal.Types: data WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types: data WorkerOptions m
- Control.Concurrent.Capataz.Internal.Types: defCapatazOptions :: Text -> (CapatazOptions -> CapatazOptions) -> CapatazOptions
+ Control.Concurrent.Capataz.Internal.Types: defCapatazOptions :: Monad m => Text -> (CapatazOptions m -> CapatazOptions m) -> CapatazOptions m
- Control.Concurrent.Capataz.Internal.Types: supervisorSpec :: SupervisorName -> (SupervisorOptions -> SupervisorOptions) -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: supervisorSpec :: Monad m => SupervisorName -> (SupervisorOptions m -> SupervisorOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: supervisorSpecWithDefaults :: SupervisorName -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: supervisorSpecWithDefaults :: Monad m => SupervisorName -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: type ProcessMap = HashMap ProcessId Process
+ Control.Concurrent.Capataz.Internal.Types: type ProcessMap m = HashMap ProcessId (Process m)
- Control.Concurrent.Capataz.Internal.Types: type WorkerAction = IO ()
+ Control.Concurrent.Capataz.Internal.Types: type WorkerAction m = WorkerId -> m ()
- Control.Concurrent.Capataz.Internal.Types: workerSpec :: WorkerName -> IO () -> (WorkerOptions -> WorkerOptions) -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: workerSpec :: Monad m => WorkerName -> m () -> (WorkerOptions m -> WorkerOptions m) -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types: workerSpecWithDefaults :: WorkerName -> IO () -> ProcessSpec
+ Control.Concurrent.Capataz.Internal.Types: workerSpecWithDefaults :: Monad m => WorkerName -> m () -> ProcessSpec m
- Control.Concurrent.Capataz.Internal.Types.Lens: onSystemEventL :: Functor f => ((CapatazEvent -> IO ()) -> f (CapatazEvent -> IO ())) -> CapatazOptions -> f CapatazOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: onSystemEventL :: Functor f => ((CapatazEvent -> m ()) -> f (CapatazEvent -> m ())) -> CapatazOptions m -> f (CapatazOptions m)
- Control.Concurrent.Capataz.Internal.Types.Lens: supervisorOnFailureL :: (HasSupervisorFailureCallback s, Functor f) => ((SomeException -> IO ()) -> f (SomeException -> IO ())) -> s -> f s
+ Control.Concurrent.Capataz.Internal.Types.Lens: supervisorOnFailureL :: (HasSupervisorFailureCallback s, Functor f) => ((SomeException -> m ()) -> f (SomeException -> m ())) -> s m -> f (s m)
- Control.Concurrent.Capataz.Internal.Types.Lens: supervisorOnIntensityReachedL :: (HasSupervisorIntensityReachedCallback s, Functor f) => (IO () -> f (IO ())) -> s -> f s
+ Control.Concurrent.Capataz.Internal.Types.Lens: supervisorOnIntensityReachedL :: (HasSupervisorIntensityReachedCallback s, Functor f) => (m () -> f (m ())) -> s m -> f (s m)
- Control.Concurrent.Capataz.Internal.Types.Lens: supervisorProcessSpecListL :: (HasSupervisorProcessSpecList s, Functor f) => ([ProcessSpec] -> f [ProcessSpec]) -> s -> f s
+ Control.Concurrent.Capataz.Internal.Types.Lens: supervisorProcessSpecListL :: (HasSupervisorProcessSpecList s, Functor f) => ([ProcessSpec m] -> f [ProcessSpec m]) -> s m -> f (s m)
- Control.Concurrent.Capataz.Internal.Types.Lens: workerOnCompletionL :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: workerOnCompletionL :: (Functor f) => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types.Lens: workerOnFailureL :: Functor f => ((SomeException -> IO ()) -> f (SomeException -> IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: workerOnFailureL :: (Functor f) => ((SomeException -> m ()) -> f (SomeException -> m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types.Lens: workerOnTerminationL :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: workerOnTerminationL :: Functor f => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types.Lens: workerRestartStrategyL :: Functor f => (WorkerRestartStrategy -> f WorkerRestartStrategy) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: workerRestartStrategyL :: Functor f => (WorkerRestartStrategy -> f WorkerRestartStrategy) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Types.Lens: workerTerminationPolicyL :: Functor f => (WorkerTerminationPolicy -> f WorkerTerminationPolicy) -> WorkerOptions -> f WorkerOptions
+ Control.Concurrent.Capataz.Internal.Types.Lens: workerTerminationPolicyL :: Functor f => (WorkerTerminationPolicy -> f WorkerTerminationPolicy) -> WorkerOptions m -> f (WorkerOptions m)
- Control.Concurrent.Capataz.Internal.Util: appendProcessToMap :: SupervisorEnv -> Process -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: appendProcessToMap :: MonadIO m => SupervisorEnv m -> Process m -> m ()
- Control.Concurrent.Capataz.Internal.Util: capatazOptionsToSupervisorOptions :: CapatazOptions -> SupervisorOptions
+ Control.Concurrent.Capataz.Internal.Util: capatazOptionsToSupervisorOptions :: CapatazOptions m -> SupervisorOptions m
- Control.Concurrent.Capataz.Internal.Util: fetchProcess :: SupervisorEnv -> ProcessId -> IO (Maybe Process)
+ Control.Concurrent.Capataz.Internal.Util: fetchProcess :: MonadIO m => SupervisorEnv m -> ProcessId -> m (Maybe (Process m))
- Control.Concurrent.Capataz.Internal.Util: getProcessId :: Process -> ProcessId
+ Control.Concurrent.Capataz.Internal.Util: getProcessId :: Process m -> ProcessId
- Control.Concurrent.Capataz.Internal.Util: readProcessMap :: SupervisorEnv -> IO ProcessMap
+ Control.Concurrent.Capataz.Internal.Util: readProcessMap :: MonadIO m => SupervisorEnv m -> m (ProcessMap m)
- Control.Concurrent.Capataz.Internal.Util: readSupervisorStatus :: SupervisorEnv -> IO SupervisorStatus
+ Control.Concurrent.Capataz.Internal.Util: readSupervisorStatus :: MonadIO m => SupervisorEnv m -> m SupervisorStatus
- Control.Concurrent.Capataz.Internal.Util: removeProcessFromMap :: SupervisorEnv -> ProcessId -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: removeProcessFromMap :: MonadIO m => SupervisorEnv m -> ProcessId -> m ()
- Control.Concurrent.Capataz.Internal.Util: resetProcessMap :: SupervisorEnv -> (ProcessMap -> ProcessMap) -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: resetProcessMap :: MonadIO m => SupervisorEnv m -> (ProcessMap m -> ProcessMap m) -> m ()
- Control.Concurrent.Capataz.Internal.Util: sendControlMsg :: SupervisorEnv -> ControlAction -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: sendControlMsg :: SupervisorEnv m -> ControlAction m -> m ()
- Control.Concurrent.Capataz.Internal.Util: sendSyncControlMsg :: SupervisorEnv -> (IO () -> ControlAction) -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: sendSyncControlMsg :: MonadIO m => SupervisorEnv m -> (m () -> ControlAction m) -> m ()
- Control.Concurrent.Capataz.Internal.Util: setProcessThreadName :: WorkerId -> WorkerName -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: setProcessThreadName :: MonadIO m => WorkerId -> WorkerName -> m ()
- Control.Concurrent.Capataz.Internal.Util: sortProcessesByTerminationOrder :: ProcessTerminationOrder -> ProcessMap -> [Process]
+ Control.Concurrent.Capataz.Internal.Util: sortProcessesByTerminationOrder :: ProcessTerminationOrder -> ProcessMap m -> [Process m]
- Control.Concurrent.Capataz.Internal.Util: toParentSupervisorEnv :: SupervisorEnv -> ParentSupervisorEnv
+ Control.Concurrent.Capataz.Internal.Util: toParentSupervisorEnv :: SupervisorEnv m -> ParentSupervisorEnv m
- Control.Concurrent.Capataz.Internal.Util: writeSupervisorStatus :: SupervisorEnv -> SupervisorStatus -> IO ()
+ Control.Concurrent.Capataz.Internal.Util: writeSupervisorStatus :: MonadIO m => SupervisorEnv m -> SupervisorStatus -> m ()
- Control.Concurrent.Capataz.Internal.Worker: forkWorker :: ParentSupervisorEnv -> WorkerOptions -> Maybe (WorkerId, RestartCount) -> IO Worker
+ Control.Concurrent.Capataz.Internal.Worker: forkWorker :: (MonadUnliftIO m) => ParentSupervisorEnv m -> WorkerOptions m -> Maybe (WorkerId, RestartCount) -> m (Worker m)
- Control.Concurrent.Capataz.Internal.Worker: workerMain :: ParentSupervisorEnv -> WorkerOptions -> WorkerId -> RestartCount -> IO Worker
+ Control.Concurrent.Capataz.Internal.Worker: workerMain :: (MonadUnliftIO m) => ParentSupervisorEnv m -> WorkerOptions m -> WorkerId -> RestartCount -> m (Worker m)

Files

CHANGELOG.md view
@@ -6,6 +6,30 @@ [1]: http://semver.org/spec/v2.0.0.html [2]: https://github.com/roman/capataz/releases +## v0.2.0.0 Bumblebee release++**BREAKING CHANGES**++* Allow the creation of Supervision Trees on Monad Transformer stacks 🎉+* Move to latest stable stackage snapshot (lts-11.10)+* Remove `protolude` in favor of `rio` (closes #9)+* Add convinience module `Capataz`+* Add `Control.Concurrent.Capataz.Util` which provide `ProcessSpec` for normal use-cases+* Add `buildLogWorkerSpec` and `buildLogWorkerOptions` which create a dedicated supervised+  thread that logs messages (sits on top of `rio` logger utilities)+* Add `terminateCapataz` and `terminateCapataz_` , these functions replace the+  re-exported `runTeardown`+* Add re-export of `TeardownResult` from the `teardown` package+* Update the `capataz-simple-example` project to use `typed-process` and `rio`+* Add export for `WorkerName` and `SupervisorName` aliases+* Add new dependency `prettyprinter`+* Add new dependency `pretty-show` to prettify exceptions+* Add `Pretty` instance for `CapatazEvent`+* Add `Display` instance for `CapatazEvent`+* Add `ProcessThreadId` newtype to better render `ThreadId` values+* Add `buildWorkerOptions1` and `workerSpec1` (closes #17)+* Move to CircleCI+ ## v0.1.0.1  * Bump bounds of `async` dependency
README.md view
@@ -4,68 +4,10 @@  ## Table Of Contents -* [Raison d'etre](#raison-detre)+* [Installation](#installation) * [Documentation](#documentation) * [Development](#development) -## Raison d'être--As time progresses, I've come to love developing concurrent applications in-Haskell, its API (STM, MVars, etc.) and light threading RTS bring a lot to the-table. There is another technology that is more famous than Haskell in-regards to concurrency, and that is Erlang, more specifically its OTP library.--If you wonder why that is, you may need to look into the OTP library design,-actors systems (in general) provide an architecture that enables applications to-be tolerant to failure through the enforcement of communication via message-passing and by making use of a critical infrastructure piece called a *Supervisor*.--After trying to replicate Erlang's behavior on Haskell applications by using the-[distributed-process](https://hackage.haskell.org/package/distributed-process)-library (a clone of OTP), and after implementing several (disposable) iterations-of actor systems in Haskell, I've settled with just this library, one that-provides a simple Supervisor API.--This library is intended to be a drop-in replacement to `forkIO` invocations-throughout your codebase, the difference being, you'll need to do a bit more of-setup specifying supervision rules, and also pass along a reference of a-supervisor for every thread you fork.--### Why not [distributed-process](https://hackage.haskell.org/package/distributed-process)?--`distributed-process` is an impressive library, and brings many great utilities-if you need to develop applications that need to be distributed and reliable.-However, it is a heavyweight solution that will enforce serious changes to your-application. This library is intended to provide the reliability benefits of-`distributed-process`, without the constraints imposed by the *distributed*-part.--### Why not a complete actor system?--Actor systems are very pervasive, they impose specific design constraints on-your application which can be rather expensive. This library attempts to bring-some of the reliability benefits of actor systems without the "change all your-application to work with actors" part of the equation.--That said, this library can serve as a basis for a more prominent library that-provides an opinionated Inter-Process communication scheme. If you happen to-attempt at doing exactly that, please let me know, I would love to learn about-such initiatives.--### Why not [async](https://hackage.haskell.org/package/async)?--`async` is a fabulous library that allows Applicative composition of small-asynchronous sub-routines into bigger ones and link errors between them. Given-this, `async` fits the bill perfectly for small operations that happen-concurrently, not necessarily for long living threads that need to be restarted.-This library attempts not to replace async's forte, but rather provides other-benefits not found in `async`, like automatically restarting threads with a given-recipe under error situations.--## Documentation--Documentation can be found [here](https://romanandreg.gitbooks.io/capataz/content/)- ## Installation  [![Hackage](https://img.shields.io/hackage/v/capataz.svg)](https://img.shields.io/hackage/v/capataz.svg)@@ -88,18 +30,24 @@ - capataz ``` +## Documentation++The documentation website can be found+[here](https://romanandreg.gitbooks.io/capataz/content/). Some relevant links:++* [Purpose](https://romanandreg.gitbooks.io/capataz/content/purpose.html)+* [FAQ](https://romanandreg.gitbooks.io/capataz/content/FAQ.html)+ ## Development -[![Build Status](https://travis-ci.org/roman/Haskell-capataz.svg?branch=master)](https://travis-ci.org/roman/Haskell-capataz)-[![Github](https://img.shields.io/github/commits-since/roman/haskell-capataz/v0.1.0.0.svg)](https://img.shields.io/github/commits-since/roman/haskell-capataz/v0.1.0.0.svg)+![Build Status](https://circleci.com/gh/roman/Haskell-teardown.svg?style=svg)+[![Github](https://img.shields.io/github/commits-since/roman/haskell-capataz/v0.2.0.0.svg)](https://img.shields.io/github/commits-since/roman/haskell-capataz/v0.2.0.0.svg) [![Hackage Dependencies](https://img.shields.io/hackage-deps/v/capataz.svg)](http://packdeps.haskellers.com/feed?needle=capataz) -Follow the [developer guidelines](https://romanandreg.gitbooks.io/capataz/content/developer-guidelines.html)+Follow the [developer guidelines](https://romanandreg.gitbooks.io/capataz/content/CONTRIBUTING.html)  ## In future releases  * Replace Protolude in favor of RIO * Documentation of performance analysis-* Documentation improvements-* capataz-dashboard package that provides web-ui with Supervisor statistics * Ensure unit tests always finish on all concurrent scenarios (dejafu experiment)
capataz.cabal view
@@ -1,12 +1,13 @@-name: capataz-version: 0.1.0.1 cabal-version: >=1.10-build-type: Simple+name: capataz+version: 0.2.0.0 license: MIT license-file: LICENSE copyright: © 2018 Roman Gonzalez maintainer: open-source@roman-gonzalez.info+author: Roman Gonzalez stability: alpha (experimental)+tested-with: ghc ==8.0.1 ghc ==8.0.2 ghc ==8.2.1 homepage: https://github.com/roman/Haskell-capataz#readme bug-reports: https://github.com/roman/Haskell-capataz/issues synopsis: OTP-like supervision trees in Haskell@@ -28,8 +29,7 @@     * Complete telemetry on the sub-routine lifecycle of your application (start,     error, restarts, shutdown) category: Control, Concurrency-author: Roman Gonzalez-tested-with: GHC ==8.0.1 GHC ==8.0.2 GHC ==8.2.1+build-type: Simple extra-source-files:     CHANGELOG.md     README.md@@ -40,6 +40,7 @@  library     exposed-modules:+        Capataz         Control.Concurrent.Capataz         Control.Concurrent.Capataz.Event         Control.Concurrent.Capataz.Lens@@ -49,57 +50,48 @@         Control.Concurrent.Capataz.Internal.Supervisor         Control.Concurrent.Capataz.Internal.Util         Control.Concurrent.Capataz.Internal.Worker-    build-depends:-        async >=2.1.1.1 && <2.3,-        base >=4.10.1.0 && <4.11,-        bytestring >=0.10.8.2 && <0.11,-        data-default >=0.7.1.1 && <0.8,-        microlens >=0.4.8.3 && <0.5,-        protolude >=0.2.1 && <0.3,-        safe-exceptions >=0.1.7.0 && <0.2,-        stm >=2.4.4.1 && <2.5,-        teardown >=0.3.0.0 && <0.4,-        text >=1.2.3.0 && <1.3,-        time >=1.8.0.2 && <1.9,-        unordered-containers >=0.2.8.0 && <0.3,-        uuid >=1.3.13 && <1.4,-        vector >=0.12.0.1 && <0.13-    default-language: Haskell2010     hs-source-dirs: src     other-modules:         Control.Concurrent.Capataz.Internal.Process+        Control.Concurrent.Capataz.Util         Paths_capataz-    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates+    default-language: Haskell2010+    ghc-options: -Wall -Wincomplete-uni-patterns+                 -Wincomplete-record-updates+    build-depends:+        async >=2.1.1.1 && <2.3,+        base ==4.*,+        bytestring >=0.10.8,+        pretty-show >=1.6.13,+        prettyprinter >=1.1,+        rio >=0.1.2.0,+        teardown >=0.5.0.0,+        time >=1.6.0,+        uuid >=1.3 -test-suite  capataz-test+test-suite capataz-test     type: exitcode-stdio-1.0     main-is: Main.hs-    build-depends:-        async >=2.1.1.1 && <2.3,-        base >=4.10.1.0 && <4.11,-        bytestring >=0.10.8.2 && <0.11,-        capataz -any,-        data-default >=0.7.1.1 && <0.8,-        microlens >=0.4.8.3 && <0.5,-        pretty-show >=1.6.16 && <1.7,-        protolude >=0.2.1 && <0.3,-        safe-exceptions >=0.1.7.0 && <0.2,-        stm >=2.4.4.1 && <2.5,-        tasty >=0.12.0.1 && <0.13,-        tasty-hunit >=0.10.0.1 && <0.11,-        tasty-rerun >=1.1.9 && <1.2,-        tasty-smallcheck >=0.8.1 && <0.9,-        teardown >=0.3.0.0 && <0.4,-        text >=1.2.3.0 && <1.3,-        time >=1.8.0.2 && <1.9,-        unordered-containers >=0.2.8.0 && <0.3,-        uuid >=1.3.13 && <1.4,-        vector >=0.12.0.1 && <0.13-    default-language: Haskell2010     hs-source-dirs: test/testsuite     other-modules:         Control.Concurrent.Capataz.SupervisorTest         Control.Concurrent.CapatazTest         Test.Util         Paths_capataz-    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -threaded+    default-language: Haskell2010+    ghc-options: -Wall -Wincomplete-uni-patterns+                 -Wincomplete-record-updates -threaded+    build-depends:+        async >=2.1.1.1 && <2.3,+        base ==4.*,+        bytestring >=0.10.8,+        capataz -any,+        pretty-show >=1.7,+        prettyprinter >=1.1,+        rio >=0.1.2.0,+        tasty >=1.0.1.1,+        tasty-hunit >=0.10.0.1,+        tasty-smallcheck >=0.8.1,+        teardown >=0.5.0.0,+        time >=1.6.0,+        uuid >=1.3
+ src/Capataz.hs view
@@ -0,0 +1,13 @@+-- | Convinience module that re-exports modules:+--+-- * "Control.Concurrent.Capataz"+-- * "Control.Concurrent.Capataz.Util"+--+--  @since 0.2.0.0+module Capataz+  (+    module X+  ) where++import Control.Concurrent.Capataz      as X+import Control.Concurrent.Capataz.Util as X
src/Control/Concurrent/Capataz.hs view
@@ -12,6 +12,7 @@ , Control.Concurrent.Capataz.Internal.Types.CallbackType (..)  , Control.Concurrent.Capataz.Internal.Types.WorkerId+, Control.Concurrent.Capataz.Internal.Types.WorkerName , Control.Concurrent.Capataz.Internal.Types.WorkerRestartStrategy (..) , Control.Concurrent.Capataz.Internal.Types.WorkerTerminationPolicy (..) , Control.Concurrent.Capataz.Internal.Types.WorkerOptions@@ -23,6 +24,7 @@ , Control.Concurrent.Capataz.Internal.Types.ProcessError (..)  , Control.Concurrent.Capataz.Internal.Types.SupervisorId+, Control.Concurrent.Capataz.Internal.Types.SupervisorName , Control.Concurrent.Capataz.Internal.Types.Supervisor , Control.Concurrent.Capataz.Internal.Types.SupervisorRestartStrategy (..) , Control.Concurrent.Capataz.Internal.Types.SupervisorStatus (..)@@ -61,6 +63,8 @@ , Control.Concurrent.Capataz.Internal.Core.forkWorker , Control.Concurrent.Capataz.Internal.Core.forkSupervisor , Control.Concurrent.Capataz.Internal.Core.forkCapataz+, Control.Concurrent.Capataz.Internal.Core.terminateCapataz+, Control.Concurrent.Capataz.Internal.Core.terminateCapataz_ , Control.Concurrent.Capataz.Internal.Core.terminateProcess  -- * Utility functions@@ -70,10 +74,9 @@ , Control.Concurrent.Capataz.Internal.Core.getCapatazTeardown  -- * Teardown (re-exported)-, Control.Teardown.teardown+, Control.Teardown.TeardownResult  -- * Lens (re-exported)-, (.~) , (&) , Control.Concurrent.Capataz.Lens.set )@@ -81,6 +84,6 @@  import qualified Control.Concurrent.Capataz.Internal.Core import qualified Control.Concurrent.Capataz.Internal.Types-import           Control.Concurrent.Capataz.Lens           ((&), (.~))+import           Control.Concurrent.Capataz.Lens           ((&)) import qualified Control.Concurrent.Capataz.Lens import qualified Control.Teardown
src/Control/Concurrent/Capataz/Internal/Core.hs view
@@ -17,6 +17,8 @@ , forkSupervisor , forkCapataz , terminateProcess+, terminateCapataz+, terminateCapataz_ , joinCapatazThread , getSupervisorProcessId , getSupervisorAsync@@ -24,11 +26,10 @@ ) where -import Protolude+import RIO -import Control.Concurrent.MVar (newEmptyMVar, takeMVar)-import Control.Teardown        (Teardown, newTeardown)-import Data.Time.Clock         (getCurrentTime)+import Control.Teardown (Teardown, TeardownResult, newTeardown, runTeardown, runTeardown_)+import RIO.Time         (getCurrentTime)  import qualified Data.UUID.V4 as UUID (nextRandom) @@ -43,22 +44,26 @@ -- that contain a supervisor (e.g. Capataz record). class HasSupervisor a where   -- | Fetches a supervisor from a record internals.-  getSupervisor :: a -> Supervisor+  getSupervisor :: a m -> Supervisor m  instance HasSupervisor Capataz where   getSupervisor Capataz {capatazSupervisor} = capatazSupervisor  instance HasSupervisor Supervisor where-  getSupervisor = identity+  getSupervisor = id  -- | Creates a Capataz record, which holds both a root supervisor and a--- "Teardown" to shut down the system. The root supervisor monitors failures on--- process threads defined with "supervisorProcessSpecList" or created--- dynamically using "forkWorker" or "forkSupervisor".-forkCapataz :: Text -> (CapatazOptions -> CapatazOptions) -> IO Capataz+-- 'Teardown' to shut down the system. The root supervisor monitors failures on+-- process threads defined with 'supervisorProcessSpecList' or created+-- dynamically using 'forkWorker' or 'forkSupervisor'.+forkCapataz+  :: (MonadUnliftIO m, MonadIO m)+  => Text+  -> (CapatazOptions m -> CapatazOptions m)+  -> m (Capataz m) forkCapataz capatazName modOptionsFn = do-  capatazId    <- UUID.nextRandom-  supervisorId <- UUID.nextRandom+  capatazId    <- liftIO UUID.nextRandom+  supervisorId <- liftIO UUID.nextRandom   let     capatazOptions@CapatazOptions { notifyEvent } =       defCapatazOptions capatazName modOptionsFn@@ -85,14 +90,14 @@             }            MonitorEvent ProcessCompleted'{} ->-            panic "Capataz completed; this should never happen"+            error "Capataz completed; this should never happen"            MonitorEvent ProcessForcedRestart{} ->-            panic+            error               "Capataz was restarted from a OneForAll strategy; this should never happen"            ControlAction{} ->-            panic "Capataz received a ControlAction message; bad implementation"+            error "Capataz received a ControlAction message; bad implementation"       , notifyEvent       } @@ -100,11 +105,11 @@     parentSupervisorEnv     supervisorOptions     supervisorId-    0+    0 -- initial restart count -  capatazTeardown <- newTeardown+  capatazTeardown <- withRunInIO $ \run -> newTeardown     "capataz"-    ( do+    (run $ do       Supervisor.haltSupervisor "capataz system shutdown" supervisorEnv       eventTime <- getCurrentTime       notifyEvent CapatazTerminated {supervisorId , supervisorName , eventTime }@@ -112,25 +117,25 @@    return Capataz {capatazSupervisor , capatazTeardown } --- | Creates a green thread from an "IO ()" sub-routine. Depending in options--- defined in the "WorkerOptions" record, it will automatically restart this+-- | Creates a green thread from an @IO ()@ sub-routine. Depending in options+-- defined in the 'WorkerOptions' record, it will automatically restart this -- sub-routine in case of failures. -- -- See documentation of related functions: ----- * "buildWorkerOptionsWithDefault"--- * "buildWorkerOptions"+-- * 'buildWorkerOptionsWithDefaults'+-- * 'buildWorkerOptions' -- forkWorker-  :: HasSupervisor supervisor-  => WorkerOptions -- ^ Worker options (restart, name, callbacks, etc)-  -> supervisor    -- ^ "Supervisor" that supervises the worker-  -> IO WorkerId   -- ^ An identifier that can be used to terminate the "Worker"+  :: (MonadIO m, HasSupervisor supervisor)+  => WorkerOptions m -- ^ Worker options (restart, name, callbacks, etc)+  -> supervisor m   -- ^ 'Supervisor' that supervises the worker+  -> m WorkerId   -- ^ An identifier that can be used to terminate the 'Worker' forkWorker workerOptions sup = do   let Supervisor { supervisorNotify } = getSupervisor sup   workerIdVar <- newEmptyMVar   supervisorNotify-    ( ControlAction ForkWorker+    (ControlAction ForkWorker       { workerOptions       , returnWorkerId = putMVar workerIdVar       }@@ -138,24 +143,24 @@   takeMVar workerIdVar  -- | Creates a green thread which monitors other green threads for failures and--- restarts them using settings defined on "SupervisorOptions".+-- restarts them using settings defined on 'SupervisorOptions'. -- -- See documentation of related functions: ----- * "buildSupervisorOptionsWithDefault"--- * "buildSupervisorOptions"+-- * 'buildSupervisorOptionsWithDefault'+-- * 'buildSupervisorOptions' -- forkSupervisor-  :: HasSupervisor parentSupervisor-  => SupervisorOptions -- ^ Supervisor options-  -> parentSupervisor  -- ^ Parent supervisor instance that supervises new supervisor-  -> IO Supervisor     -- ^ A record used to dynamically create and supervise+  :: (MonadIO m, HasSupervisor parentSupervisor)+  => SupervisorOptions m -- ^ Supervisor options+  -> parentSupervisor m  -- ^ Parent supervisor instance that supervises new supervisor+  -> m (Supervisor m)     -- ^ A record used to dynamically create and supervise                        -- other processes forkSupervisor supervisorOptions parentSup = do   let Supervisor { supervisorNotify } = getSupervisor parentSup   supervisorVar <- newEmptyMVar   supervisorNotify-    ( ControlAction ForkSupervisor+    (ControlAction ForkSupervisor       { supervisorOptions       , returnSupervisor  = putMVar supervisorVar       }@@ -165,16 +170,21 @@ -- | Stops the execution of a green thread being supervised by the given -- supervisor. ----- NOTE: If "ProcessId" maps to a worker that is configured with a "Permanent"--- worker restart strategy, the worker green thread __will be restarted again__.+-- __IMPORTANT__ If 'ProcessId' maps to a worker that is configured with a+-- 'Permanent' worker restart strategy, the worker green thread __will be+-- restarted again__. -- terminateProcess-  :: HasSupervisor supervisor => Text -> ProcessId -> supervisor -> IO Bool+  :: (MonadIO m, HasSupervisor supervisor)+  => Text+  -> ProcessId+  -> supervisor m+  -> m Bool terminateProcess processTerminationReason processId supervisor = do   let Supervisor { supervisorNotify } = getSupervisor supervisor   result <- newEmptyMVar   supervisorNotify-    ( ControlAction TerminateProcess+    (ControlAction TerminateProcess       { processId       , processTerminationReason       , notifyProcessTermination = putMVar result@@ -184,22 +194,34 @@  -- | Joins the thread of the root supervisor of the given capataz system to the -- current thread.-joinCapatazThread :: Capataz -> IO ()+joinCapatazThread :: MonadIO m => Capataz m -> m () joinCapatazThread Capataz { capatazSupervisor } =   let Supervisor { supervisorAsync } = capatazSupervisor   in  wait supervisorAsync --- | Gets "Teardown" record of this capataz system.-getCapatazTeardown :: Capataz -> Teardown+-- | Terminates a 'Capataz' system (all supervised threads) and returns a 'TeardownResult'+--+-- @since 0.2.0.0+terminateCapataz :: MonadIO m => Capataz m -> m TeardownResult+terminateCapataz = liftIO . runTeardown++-- | Terminates a 'Capataz' system (all supervised threads)+--+-- @since 0.2.0.0+terminateCapataz_ :: MonadIO m => Capataz m -> m ()+terminateCapataz_ = liftIO . runTeardown_++-- | Gets 'Teardown' record of this capataz system.+getCapatazTeardown :: Capataz m -> Teardown getCapatazTeardown Capataz { capatazTeardown } = capatazTeardown --- | Gets the "Async" of a Supervisor thread.+-- | Gets the 'Async' of a Supervisor thread. ----- NOTE: There is no way to get the "Async" value of the root supervisor; this--- is to avoid error scenarios.-getSupervisorAsync :: Supervisor -> Async ()+-- NOTE: There is no way to get the 'Async' value of the root supervisor; this+-- is done on-purpose to avoid error scenarios.+getSupervisorAsync :: Supervisor m -> Async () getSupervisorAsync Supervisor { supervisorAsync } = supervisorAsync --- | Gets the process identifier of a Supervisor; normally used for termination.-getSupervisorProcessId :: Supervisor -> ProcessId+-- | Gets the process identifier of a 'Supervisor'; normally used for termination.+getSupervisorProcessId :: Supervisor m -> ProcessId getSupervisorProcessId Supervisor { supervisorId } = supervisorId
src/Control/Concurrent/Capataz/Internal/Process.hs view
@@ -6,43 +6,43 @@ -- Worker process types. module Control.Concurrent.Capataz.Internal.Process where -import Protolude+import RIO  import Control.Concurrent.Capataz.Internal.Types import Control.Concurrent.Capataz.Internal.Util     (readProcessMap, sortProcessesByTerminationOrder)-import Data.Time.Clock                           (UTCTime, getCurrentTime)+import RIO.Time                                  (UTCTime, getCurrentTime)  -- | Gets "Async" from a given Process.-getProcessAsync :: Process -> Async ()+getProcessAsync :: Process m -> Async () getProcessAsync process = case process of   WorkerProcess     Worker { workerAsync }         -> workerAsync   SupervisorProcess Supervisor { supervisorAsync } -> supervisorAsync  -- | Gets "ThreadId" from a given Process.-getProcessThreadId :: Process -> ThreadId-getProcessThreadId = asyncThreadId . getProcessAsync+getProcessThreadId :: Process m -> ProcessThreadId+getProcessThreadId = PTID . asyncThreadId . getProcessAsync  -- | Gets "ProcessId" from a given Process.-getProcessId :: Process -> ProcessId+getProcessId :: Process m -> ProcessId getProcessId process = case process of   WorkerProcess     Worker { workerId }         -> workerId   SupervisorProcess Supervisor { supervisorId } -> supervisorId  -- | Gets "ProcessName" from a given "ProcessSpec".-getProcessName :: ProcessSpec -> ProcessName+getProcessName :: ProcessSpec m -> ProcessName getProcessName procSpec = case procSpec of   WorkerSpec     WorkerOptions { workerName }         -> workerName   SupervisorSpec SupervisorOptions { supervisorName } -> supervisorName  -- | Gets "ProcessType" from a given "ProcessSpec".-getProcessType :: ProcessSpec -> ProcessType+getProcessType :: ProcessSpec m -> ProcessType getProcessType processSpec = case processSpec of   WorkerSpec{}     -> WorkerType   SupervisorSpec{} -> SupervisorType  -- | Gets "ProcessSpec" of a given "Process".-getProcessSpec :: Process -> ProcessSpec+getProcessSpec :: Process m -> ProcessSpec m getProcessSpec process = case process of   WorkerProcess Worker { workerOptions } -> WorkerSpec workerOptions   SupervisorProcess Supervisor { supervisorOptions } ->@@ -50,7 +50,8 @@  -- | Utility function to send notifications to the capataz system callback when -- a Process fails.-notifyProcessFailed :: SupervisorEnv -> Process -> SomeException -> IO ()+notifyProcessFailed+  :: MonadIO m => SupervisorEnv m -> Process m -> SomeException -> m () notifyProcessFailed SupervisorEnv { supervisorId, supervisorName, notifyEvent } process processError   = do     eventTime <- getCurrentTime@@ -67,7 +68,8 @@  -- | Utility function to send notifications to the capataz system callback when -- a Process is terminated.-notifyProcessTerminated :: SupervisorEnv -> Process -> Text -> IO ()+notifyProcessTerminated+  :: MonadIO m => SupervisorEnv m -> Process m -> Text -> m () notifyProcessTerminated SupervisorEnv { supervisorId, supervisorName, notifyEvent } process terminationReason   = do     eventTime <- getCurrentTime@@ -85,7 +87,11 @@ -- | Utility function to send notifications to the capataz system callback when -- a Process is started or restarted. notifyProcessStarted-  :: Maybe (ProcessId, RestartCount) -> ParentSupervisorEnv -> Process -> IO ()+  :: MonadIO m+  => Maybe (ProcessId, RestartCount)+  -> ParentSupervisorEnv m+  -> Process m+  -> m () notifyProcessStarted mRestartInfo ParentSupervisorEnv { supervisorId, supervisorName, notifyEvent } process   = do     eventTime <- getCurrentTime@@ -112,7 +118,7 @@  -- | Utility function to send notifications when a Process sub-routine completes -- without errors.-notifyProcessCompleted :: SupervisorEnv -> Process -> UTCTime -> IO ()+notifyProcessCompleted :: SupervisorEnv m -> Process m -> UTCTime -> m () notifyProcessCompleted SupervisorEnv { supervisorId, supervisorName, notifyEvent } process eventTime   = notifyEvent ProcessCompleted     { supervisorId@@ -126,39 +132,41 @@   -- | Utility function to execute a Process onCompletion sub-routine.-callProcessOnCompletion :: ProcessSpec -> IO ()+callProcessOnCompletion :: Monad m => ProcessSpec m -> m () callProcessOnCompletion procSpec = case procSpec of   WorkerSpec WorkerOptions { workerOnCompletion } -> workerOnCompletion   _                                               -> return ()  -- | Utility function to execute a Process onFailure sub-routine.-callProcessOnFailure :: ProcessSpec -> SomeException -> IO ()+callProcessOnFailure :: ProcessSpec m -> SomeException -> m () callProcessOnFailure procSpec err = case procSpec of   WorkerSpec WorkerOptions { workerOnFailure } -> workerOnFailure err   SupervisorSpec SupervisorOptions { supervisorOnFailure } ->     supervisorOnFailure err  -- | Utility function to execute a Process onTermination sub-routine.-callProcessOnTermination :: ProcessSpec -> IO ()+callProcessOnTermination :: Monad m => ProcessSpec m -> m () callProcessOnTermination procSpec = case procSpec of   WorkerSpec WorkerOptions { workerOnTermination } -> workerOnTermination   _                                                -> return ()  -- | Handles errors produced - or thrown to - a process thread. handleProcessException-  :: (IO () -> IO a)-  -> ParentSupervisorEnv-  -> ProcessSpec+  :: (MonadUnliftIO m)+  => (m () -> m a)+  -> ParentSupervisorEnv m+  -> ProcessSpec m   -> ProcessId   -> RestartCount   -> SomeException-  -> IO MonitorEvent+  -> m MonitorEvent handleProcessException unmask ParentSupervisorEnv { supervisorId, supervisorName, notifyEvent } procSpec processId restartCount err   = do     let processName = getProcessName procSpec-    processThreadId  <- myThreadId+    processThreadId  <- PTID <$> myThreadId     monitorEventTime <- getCurrentTime-    case fromException err of++    case fromAnyException err of       Just RestartProcessException -> return ProcessForcedRestart         { processId         , processName@@ -166,7 +174,7 @@         }        Just TerminateProcessException { processTerminationReason } -> do-        eErrResult <- try $ unmask $ callProcessOnTermination procSpec+        eErrResult <- unsafeTry $ unmask $ callProcessOnTermination procSpec          notifyEvent ProcessCallbackExecuted           { supervisorId@@ -180,6 +188,7 @@           , eventTime            = monitorEventTime           } +         case eErrResult of           Left processCallbackError -> return ProcessFailed'             { processId@@ -210,9 +219,8 @@           , processRestartCount      = restartCount           } -      -- This exception was an error from the given sub-routine       _ -> do-        eErrResult <- try $ unmask $ callProcessOnFailure procSpec err+        eErrResult <- unsafeTry $ unmask $ callProcessOnFailure procSpec err          notifyEvent ProcessCallbackExecuted           { supervisorId@@ -249,18 +257,19 @@  -- | Handles completion of a Process sub-routine. handleProcessCompletion-  :: (IO () -> IO a)-  -> ParentSupervisorEnv-  -> ProcessSpec+  :: (MonadUnliftIO m)+  => (m () -> m a)+  -> ParentSupervisorEnv m+  -> ProcessSpec m   -> ProcessId   -> RestartCount-  -> IO MonitorEvent+  -> m MonitorEvent handleProcessCompletion unmask ParentSupervisorEnv { supervisorId, supervisorName, notifyEvent } procSpec processId restartCount   = do     let processName = getProcessName procSpec-    processThreadId  <- myThreadId+    processThreadId  <- PTID <$> myThreadId     monitorEventTime <- getCurrentTime-    eCompResult      <- try $ unmask $ callProcessOnCompletion procSpec+    eCompResult      <- unsafeTry $ unmask $ callProcessOnCompletion procSpec      notifyEvent ProcessCallbackExecuted       { supervisorId@@ -296,10 +305,11 @@ -- function gets executed on the supervisor's thread. -- terminateProcess-  :: Text -- ^ Description that indicates _why_ there is a termination-  -> SupervisorEnv-  -> Process-  -> IO ()+  :: (MonadUnliftIO m)+  => Text -- ^ Description that indicates _why_ there is a termination+  -> SupervisorEnv m+  -> Process m+  -> m () terminateProcess processTerminationReason env process = do   case process of     WorkerProcess worker -> terminateWorker processTerminationReason worker@@ -310,7 +320,7 @@  -- | Internal utility function that manages execution of a termination policy -- for a Worker.-terminateWorker :: Text -> Worker -> IO ()+terminateWorker :: (MonadUnliftIO m) => Text -> Worker m -> m () terminateWorker processTerminationReason Worker { workerId, workerOptions, workerAsync }   = do     let processId = workerId@@ -327,24 +337,29 @@           , processTerminationReason           } -      TimeoutMillis millis -> race_-        ( do-          threadDelay (millis * 1000)-          cancelWith+      TimeoutMillis millis -> do+        -- NOTE: Given Teardown executes teardown operations in an uninterruptible mask+        -- we need to run asyncWithUnmask to come back to a unmasked state, sadly, race+        -- doesn't use asyncWithUnmask_, so we need to use it here+        result <- asyncWithUnmask $ \unmask -> unmask $ race_+          (do+            threadDelay (millis * 1000)+            cancelWith+              workerAsync+              BrutallyTerminateProcessException+                { processId+                , processTerminationReason+                }+          )+          (cancelWith             workerAsync-            BrutallyTerminateProcessException-              { processId-              , processTerminationReason-              }-        )-        ( cancelWith-          workerAsync-          TerminateProcessException {processId , processTerminationReason }-        )+            TerminateProcessException {processId , processTerminationReason }+          )+        wait result  -- | Internal utility function that manages execution of a termination policy -- for a Supervisor.-terminateSupervisor :: Text -> Supervisor -> IO ()+terminateSupervisor :: MonadIO m => Text -> Supervisor m -> m () terminateSupervisor processTerminationReason Supervisor { supervisorId = processId, supervisorAsync }   = cancelWith     supervisorAsync@@ -352,7 +367,7 @@  -- | Internal sub-routine that terminates workers of a supervisor, used when a -- supervisor instance is terminated.-terminateProcessMap :: Text -> SupervisorEnv -> IO ()+terminateProcessMap :: (MonadUnliftIO m) => Text -> SupervisorEnv m -> m () terminateProcessMap terminationReason env@SupervisorEnv { supervisorId, supervisorName, supervisorProcessTerminationOrder, notifyEvent }   = do     eventTime  <- getCurrentTime
src/Control/Concurrent/Capataz/Internal/Supervisor.hs view
@@ -7,16 +7,13 @@ {-# LANGUAGE ScopedTypeVariables   #-} module Control.Concurrent.Capataz.Internal.Supervisor where -import Control.Concurrent.Async      (asyncWithUnmask)-import Control.Concurrent.STM.TQueue (newTQueueIO, readTQueue, writeTQueue)-import Control.Concurrent.STM.TVar   (newTVarIO)-import Data.IORef                    (newIORef)-import Data.Time.Clock               (NominalDiffTime, UTCTime, diffUTCTime, getCurrentTime)-import Protolude+import           RIO+import qualified RIO.HashMap as HashMap -import qualified Data.HashMap.Strict as HashMap-import qualified Data.UUID.V4        as UUID+import RIO.Time (NominalDiffTime, UTCTime, diffUTCTime, getCurrentTime) +import qualified Data.UUID.V4 as UUID+ import Control.Concurrent.Capataz.Internal.Types  import qualified Control.Concurrent.Capataz.Internal.Process as Process@@ -27,14 +24,15 @@ -- from the public @forkSupervisor@ function which sends a message to the -- supervisor loop. forkSupervisor-  :: ParentSupervisorEnv-  -> SupervisorOptions+  :: (MonadUnliftIO m)+  => ParentSupervisorEnv m+  -> SupervisorOptions m   -> Maybe (ProcessId, RestartCount)-  -> IO Supervisor+  -> m (Supervisor m) forkSupervisor parentEnv supervisorOptions mRestartInfo = do   (supervisorId, restartCount) <- case mRestartInfo of     Just (supervisorId, restartCount) -> pure (supervisorId, restartCount)-    Nothing                           -> (,) <$> UUID.nextRandom <*> pure 0+    Nothing                           -> (,) <$> liftIO UUID.nextRandom <*> pure 0     supervisor <- supervisorMain parentEnv@@ -50,12 +48,13 @@ -- | Utility function that builds an utility record which is used on all -- internal APIs of the supervision logic. buildSupervisorEnv-  :: (CapatazEvent -> IO ())-  -> (SupervisorMessage -> IO ())-  -> STM SupervisorMessage+  :: MonadIO m+  => (CapatazEvent -> m ())+  -> (SupervisorMessage m -> m ())+  -> STM (SupervisorMessage m)   -> SupervisorId-  -> SupervisorOptions-  -> IO SupervisorEnv+  -> SupervisorOptions m+  -> m (SupervisorEnv m) buildSupervisorEnv notifyEvent supervisorNotify supervisorGetNotification supervisorId supervisorOptions@SupervisorOptions {..}   = do     supervisorProcessMap <- newIORef mempty@@ -63,7 +62,8 @@     return SupervisorEnv {..}  -- | Handles an event produced by one of the processes this supervisor monitors.-handleMonitorEvent :: SupervisorEnv -> MonitorEvent -> IO Bool+handleMonitorEvent+  :: (MonadUnliftIO m) => SupervisorEnv m -> MonitorEvent -> m Bool handleMonitorEvent env monitorEv = do   case monitorEv of     ProcessForcedRestart{} ->@@ -87,7 +87,8 @@   return True  -- | Handles an action triggered by the public Capataz API.-handleControlAction :: SupervisorEnv -> ControlAction -> IO Bool+handleControlAction+  :: (MonadUnliftIO m) => SupervisorEnv m -> ControlAction m -> m Bool handleControlAction env controlAction = case controlAction of   ForkWorker { workerOptions, returnWorkerId } -> do     worker@Worker { workerId } <- Worker.forkWorker@@ -120,7 +121,7 @@  -- | Executes the shutdown operation of a Supervisor, including the termination -- of its supervised processes.-haltSupervisor :: Text -> SupervisorEnv -> IO ()+haltSupervisor :: (MonadUnliftIO m) => Text -> SupervisorEnv m -> m () haltSupervisor reason env = do   Util.writeSupervisorStatus  env    Halting   Process.terminateProcessMap reason env@@ -130,40 +131,33 @@  -- | Handles all messages that a Supervisor can receive from its monitored -- processes or from the public API.-handleSupervisorMessage :: SupervisorEnv -> SupervisorMessage -> IO Bool+handleSupervisorMessage+  :: (MonadUnliftIO m) => SupervisorEnv m -> SupervisorMessage m -> m Bool handleSupervisorMessage env message = case message of   ControlAction controlAction -> handleControlAction env controlAction   MonitorEvent  monitorEvent  -> handleMonitorEvent env monitorEvent  -- | This sub-routine executes the main thread loop of a "Supervisor" instance. supervisorLoop-  :: (forall b . IO b -> IO b)-  -> ParentSupervisorEnv-  -> SupervisorEnv+  :: (MonadUnliftIO m)+  => (forall b . m b -> m b)+  -> ParentSupervisorEnv m+  -> SupervisorEnv m   -> RestartCount-  -> IO ()+  -> m () supervisorLoop unmask parentEnv@ParentSupervisorEnv { supervisorId, supervisorName, supervisorNotify = notifyParentSupervisor } env@SupervisorEnv { supervisorId = processId, supervisorName = processName, supervisorOptions, supervisorStatusVar, supervisorGetNotification, notifyEvent } restartCount   = do-    processThreadId <- myThreadId+    processThreadId <- PTID <$> myThreadId     loopResult      <--      unmask-      $   try+      unsafeTry+      $   unmask       $   atomically       $   (,)       <$> Util.readSupervisorStatusSTM supervisorStatusVar       <*> supervisorGetNotification      case loopResult of-      Left supervisorError -> do-        haltSupervisor (show supervisorError) env-        result <- Process.handleProcessException-          unmask-          parentEnv-          (SupervisorSpec supervisorOptions)-          processId-          restartCount-          supervisorError-        notifyParentSupervisor (MonitorEvent result)+      Left  supervisorError   -> handleSupervisorLoopError supervisorError        Right (status, message) -> case status of         Initializing -> do@@ -176,18 +170,11 @@           supervisorLoop unmask parentEnv env restartCount          Running -> do-          eContinueLoop <- try $ unmask $ handleSupervisorMessage env message+          eContinueLoop <- unsafeTry $ unmask $ handleSupervisorMessage+            env+            message           case eContinueLoop of-            Left supervisorError -> do-              haltSupervisor (show supervisorError) env-              result <- Process.handleProcessException-                unmask-                parentEnv-                (SupervisorSpec supervisorOptions)-                processId-                restartCount-                supervisorError-              notifyParentSupervisor (MonitorEvent result)+            Left supervisorError -> handleSupervisorLoopError supervisorError              Right continueLoop               | continueLoop -> supervisorLoop unmask parentEnv env restartCount@@ -211,15 +198,27 @@         Halted ->           -- Discard messages when halted           return ()+ where+  handleSupervisorLoopError err = do+    haltSupervisor (tshow err) env+    result <- Process.handleProcessException+      unmask+      parentEnv+      (SupervisorSpec supervisorOptions)+      processId+      restartCount+      err+    notifyParentSupervisor (MonitorEvent result)  -- | This sub-routine starts a Supervisor thread and initializes its -- processList. supervisorMain-  :: ParentSupervisorEnv-  -> SupervisorOptions+  :: (MonadUnliftIO m)+  => ParentSupervisorEnv m+  -> SupervisorOptions m   -> SupervisorId   -> RestartCount-  -> IO Supervisor+  -> m (Supervisor m) supervisorMain parentEnv@ParentSupervisorEnv { notifyEvent } supervisorOptions@SupervisorOptions { supervisorName, supervisorProcessSpecList } supervisorId restartCount   = do     supervisorCreationTime <- getCurrentTime@@ -241,7 +240,7 @@      forM_       supervisorProcessSpecList-      ( \processSpec -> case processSpec of+      (\processSpec -> case processSpec of         WorkerSpec workerOptions -> do           worker <- Worker.forkWorker             (Util.toParentSupervisorEnv supervisorEnv)@@ -273,7 +272,7 @@  -- | Tracks difference between two timestamps so that we keep track of a -- Supervisor error intensity.-calcDiffSeconds :: UTCTime -> IO NominalDiffTime+calcDiffSeconds :: MonadIO m => UTCTime -> m NominalDiffTime calcDiffSeconds creationTime = do   currentTime <- getCurrentTime   return $ diffUTCTime currentTime creationTime@@ -282,7 +281,7 @@ -- error intensity has been breached, see "ProcessRestartAction" for possible -- outcomes. calcRestartAction-  :: SupervisorEnv -> Int -> NominalDiffTime -> ProcessRestartAction+  :: SupervisorEnv m -> Int -> NominalDiffTime -> ProcessRestartAction calcRestartAction SupervisorEnv { supervisorIntensity, supervisorPeriodSeconds } restartCount diffSeconds   = case () of     _@@ -298,7 +297,12 @@  -- | Sub-routine responsible of executing a "SupervisorRestartStrategy". execCapatazRestartStrategy-  :: SupervisorEnv -> ProcessId -> ProcessSpec -> Int -> IO ()+  :: (MonadUnliftIO m)+  => SupervisorEnv m+  -> ProcessId+  -> ProcessSpec m+  -> Int+  -> m () execCapatazRestartStrategy supervisorEnv@SupervisorEnv { supervisorRestartStrategy } processId processSpec processRestartCount   = case supervisorRestartStrategy of     AllForOne -> do@@ -330,13 +334,14 @@ -- | Executes a restart action returned from the invokation of -- "calcRestartAction". execRestartAction-  :: SupervisorEnv+  :: (MonadUnliftIO m)+  => SupervisorEnv m   -> ProcessId-  -> ProcessSpec+  -> ProcessSpec m   -> Text   -> UTCTime   -> Int-  -> IO ()+  -> m () execRestartAction supervisorEnv@SupervisorEnv { supervisorOnIntensityReached } processId processSpec processName processCreationTime processRestartCount   = do     restartAction <- calcRestartAction supervisorEnv processRestartCount@@ -345,7 +350,7 @@     case restartAction of       HaltSupervisor -> do         -- skip exceptions on callback-        (_ :: Either SomeException ()) <- try supervisorOnIntensityReached+        (_ :: Either SomeException ()) <- unsafeTry supervisorOnIntensityReached         throwIO SupervisorIntensityReached           { processId           , processName@@ -359,7 +364,7 @@         supervisorEnv         processId         processSpec-        (succ processRestartCount)+        (processRestartCount + 1)   --------------------------------------------------------------------------------@@ -367,7 +372,12 @@ -- | Restarts _all_ processes that are supervised by Supervisor, invoked when -- one worker green thread fails and causes sibling process threads to get -- restarted as well (e.g. "AllForOne" supervisor restart strategy).-restartProcessList :: SupervisorEnv -> WorkerId -> RestartCount -> IO [Process]+restartProcessList+  :: (MonadUnliftIO m)+  => SupervisorEnv m+  -> WorkerId+  -> RestartCount+  -> m [Process m] restartProcessList supervisorEnv@SupervisorEnv { supervisorProcessTerminationOrder } failingProcessId restartCount   = do     processMap <- Util.readProcessMap supervisorEnv@@ -404,7 +414,7 @@  -- | Sub-routine that is used when there is a restart request sent to a Process -- caused by an "AllForOne" restart from a failing sibling process.-forceRestartProcess :: SupervisorEnv -> Process -> IO ()+forceRestartProcess :: MonadIO m => SupervisorEnv m -> Process m -> m () forceRestartProcess env process = do   Process.notifyProcessTerminated env process "forced restart"   cancelWith (Process.getProcessAsync process) RestartProcessException@@ -412,7 +422,12 @@ -- | Starts a new worker thread taking into account an existing "WorkerId" and -- keeping a "RestartCount" to manage the Supervisor error intensity. restartWorker-  :: SupervisorEnv -> WorkerOptions -> WorkerId -> RestartCount -> IO Process+  :: (MonadUnliftIO m)+  => SupervisorEnv m+  -> WorkerOptions m+  -> WorkerId+  -> RestartCount+  -> m (Process m) restartWorker supervisorEnv workerOptions workerId restartCount =   WorkerProcess <$> Worker.forkWorker     (Util.toParentSupervisorEnv supervisorEnv)@@ -423,11 +438,12 @@ -- "SupervisorId" and keeping a "RestartCount" to manage the parent Supervisor -- error intensity. restartSupervisor-  :: ParentSupervisorEnv-  -> SupervisorOptions+  :: (MonadUnliftIO m)+  => ParentSupervisorEnv m+  -> SupervisorOptions m   -> ProcessId   -> RestartCount-  -> IO Process+  -> m (Process m) restartSupervisor parentEnv supervisorOptions processId restartCount =   SupervisorProcess <$> forkSupervisor parentEnv                                        supervisorOptions@@ -438,7 +454,8 @@  -- | Executes restart strategy for when a worker finishes it execution because -- of a completion (e.g. worker sub-routine finished without any errors).-handleWorkerCompleted :: SupervisorEnv -> Worker -> IO ()+handleWorkerCompleted+  :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> m () handleWorkerCompleted env worker = do   let Worker { workerId, workerOptions, workerCreationTime } = worker       WorkerOptions { workerName, workerRestartStrategy }    = workerOptions@@ -461,7 +478,8 @@  -- | Executes restart strategy for when a process finishes it execution because -- of a completion (e.g. worker sub-routine finished without any errors).-handleProcessCompleted :: SupervisorEnv -> ProcessId -> UTCTime -> IO ()+handleProcessCompleted+  :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> UTCTime -> m () handleProcessCompleted env processId completionTime = do   mProcess <- Util.fetchProcess env processId   case mProcess of@@ -472,14 +490,15 @@       case process of         WorkerProcess worker -> handleWorkerCompleted env worker         _ ->-          panic+          error             $  "ERROR: Supervisor ("             <> show (Process.getProcessId process)             <> ") should never complete"  -- | Executes restart strategy for when a worker finishes it execution because -- of a failure.-handleWorkerFailed :: SupervisorEnv -> Worker -> Int -> IO ()+handleWorkerFailed+  :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> Int -> m () handleWorkerFailed env worker restartCount = do   let Worker { workerId, workerCreationTime, workerOptions } = worker       WorkerOptions { workerName, workerRestartStrategy }    = workerOptions@@ -494,7 +513,8 @@  -- | Executes restart strategy for when a supervisor finishes it execution because -- of a failure.-handleSupervisorFailed :: SupervisorEnv -> Supervisor -> Int -> IO ()+handleSupervisorFailed+  :: (MonadUnliftIO m) => SupervisorEnv m -> Supervisor m -> Int -> m () handleSupervisorFailed env supervisor restartCount = do   let Supervisor { supervisorId, supervisorCreationTime, supervisorOptions } =         supervisor@@ -509,7 +529,12 @@ -- | Executes restart strategy for when a process finishes it execution because -- of a failure. handleProcessFailed-  :: SupervisorEnv -> WorkerId -> SomeException -> Int -> IO ()+  :: (MonadUnliftIO m)+  => SupervisorEnv m+  -> WorkerId+  -> SomeException+  -> Int+  -> m () handleProcessFailed env processId processError restartCount = do   mProcess <- Util.fetchProcess env processId   case mProcess of@@ -524,7 +549,8 @@  -- | Executes restart strategy for when a worker finishes it execution because -- of a termination from its supervisor.-handleWorkerTerminated :: SupervisorEnv -> Worker -> Int -> IO ()+handleWorkerTerminated+  :: (MonadUnliftIO m) => SupervisorEnv m -> Worker m -> Int -> m () handleWorkerTerminated env worker restartCount = do   let Worker { workerId, workerCreationTime, workerOptions } = worker       WorkerOptions { workerName, workerRestartStrategy }    = workerOptions@@ -541,7 +567,8 @@  -- | Executes restart strategy for when a supervisor finishes it execution -- because of a termination from its parent supervisor.-handleSupervisorTerminated :: SupervisorEnv -> Supervisor -> Int -> IO ()+handleSupervisorTerminated+  :: (MonadUnliftIO m) => SupervisorEnv m -> Supervisor m -> Int -> m () handleSupervisorTerminated env supervisor restartCount = do   let Supervisor { supervisorId, supervisorCreationTime, supervisorOptions } =         supervisor@@ -555,7 +582,8 @@  -- | Executes restart strategy for when a process finishes it execution because -- of a termination from its supervisor.-handleProcessTerminated :: SupervisorEnv -> ProcessId -> Text -> Int -> IO ()+handleProcessTerminated+  :: (MonadUnliftIO m) => SupervisorEnv m -> ProcessId -> Text -> Int -> m () handleProcessTerminated env processId terminationReason restartCount = do   mProcess <- Util.fetchProcess env processId   case mProcess of
src/Control/Concurrent/Capataz/Internal/Types.hs view
@@ -2,38 +2,57 @@ {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE NamedFieldPuns        #-} {-# LANGUAGE NoImplicitPrelude     #-}+{-# LANGUAGE OverloadedStrings     #-}  {-| This module contains all the types used across all the other modules -} module Control.Concurrent.Capataz.Internal.Types where -import Protolude+import RIO+import RIO.Time (NominalDiffTime, UTCTime) -import Control.Concurrent.STM.TVar (TVar)-import Control.Teardown            (ITeardown (..), Teardown)-import Data.Default                (Default (..))-import Data.HashMap.Strict         (HashMap)-import Data.IORef                  (IORef)-import Data.Time.Clock             (NominalDiffTime, UTCTime)-import Data.UUID                   (UUID)+import Control.Teardown (HasTeardown (..), Teardown)+import Data.UUID        (UUID) +import qualified Control.Exception as UnsafeE+import           Data.Typeable     (cast)++import           Data.Text.Prettyprint.Doc (Pretty (..), (<+>))+import qualified Data.Text.Prettyprint.Doc as Pretty+import           Text.Show.Pretty          (ppShow)+ type CapatazId = UUID type WorkerId = UUID type SupervisorId = UUID type ProcessId = UUID-type WorkerAction = IO ()-type ProcessThreadId = ThreadId+type WorkerAction m = WorkerId -> m () type ProcessName = Text type CapatazName = Text type SupervisorName = Text type WorkerName = Text type RestartCount = Int-type ProcessMap = HashMap ProcessId Process+type ProcessMap m = HashMap ProcessId (Process m) type ParentSupervisor = Supervisor --- | Event delivered to the "notifyEvent" callback sub-routine; these events can+-- | Wrapper for 'ThreadId'+--+-- @since 0.2.0.0+newtype ProcessThreadId+  = PTID ThreadId+  deriving (Generic, Eq, Show)++-- | @since 0.2.0.0+instance Pretty ProcessThreadId where+  pretty (PTID tid) =+    case words (show tid) of+      (_:threadNumber:_) -> pretty threadNumber+      _                  -> "unknown"++-- | Event delivered to the 'notifyEvent' callback sub-routine; these events can -- be used to monitor the capataz system and track what is doing, providing high -- levels of telemetry for all supervisors and workers of a capataz system, -- ergo, should be used for logging, monitoring and testing purposes.+--+-- @since 0.1.0.0 data CapatazEvent   = InvalidSupervisorStatusReached {     supervisorId   :: !SupervisorId@@ -131,8 +150,212 @@   }   deriving (Generic, Show) --- | Defines how a "Worker" process termination should be handled by its+-- | @since 0.2.0.0+instance Pretty CapatazEvent where+  pretty ev =+    case ev of+      InvalidSupervisorStatusReached {supervisorId, supervisorName} ->+        "Supervisor got into an state that should never have happened, please"+        <+> "report a ticket to"+        <+> "https://github.com/roman/Haskell-capataz/issues/new with title:"+        <+> Pretty.dquotes "InvalidSupervisorStatusReached error"+        <> prettyAttributes [("Supervisor ID"+                             , prettySupervisorId supervisorId supervisorName)]++      SupervisorStatusChanged {+          supervisorId+        , supervisorName+        , prevSupervisorStatus+        , newSupervisorStatus+        } ->+        "Supervisor changed state"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ("Previous State"+                              , Pretty.dquotes $ Pretty.pretty prevSupervisorStatus)+                            , ("New State"+                              , Pretty.dquotes (Pretty.pretty newSupervisorStatus))+                            ]++      ProcessStarted {+          supervisorId+        , supervisorName+        , processId+        , processThreadId+        , processName+        , processType+        } ->+        "Supervisor spawned new process"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ( "Process ID"+                              , prettyProcessId processId processName processThreadId)+                            , ( "Process Type",+                                pretty processType)+                            ]++      ProcessFailed {+          processId+        , processThreadId+        , processName+        , processType+        , processError+        } ->+        "Process failed with error"+        <> prettyAttributes [ ( "Process ID"+                              , prettyProcessId processId processName processThreadId)+                            , ( "Process Type", pretty processType)+                            , ( "Error"+                              , Pretty.nest 2 (Pretty.hardline+                                               <> "|" <+> pretty (ppShow processError)))+                            ]++      ProcessRestarted {+          supervisorId+        , supervisorName+        , processId+        , processThreadId+        , processName+        , processType+        } ->+        "Supervisor restarted failed process"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ( "Process ID"+                              , prettyProcessId processId processName processThreadId)+                            , ( "Process Type", pretty processType)+                            ]++      ProcessTerminated {+          supervisorId+        , supervisorName+        , processId+        , processThreadId+        , processName+        , processType+        , terminationReason+        } ->+        "Supervisor terminated process"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ( "Process ID"+                              , prettyProcessId processId processName processThreadId)+                            , ( "Process Type", pretty processType)+                            , ( "Reason"+                              , Pretty.nest 2+                                  (Pretty.fillBreak 10 $ pretty terminationReason))+                            ]+++      ProcessCompleted {+          processId+        , processThreadId+        , processName+        , processType+        } ->+        "Process completed execution with no errors"+        <> prettyAttributes [ ( "Process ID"+                              , prettyProcessId processId processName processThreadId)+                            , ( "Process Type", pretty processType)+                            ]++      ProcessCallbackExecuted {+          processId+        , processThreadId+        , processName+        , processType+        , processCallbackError+        , processCallbackType+        } ->+        case processCallbackError of+          Nothing ->+            "Process executed callback"+             <> prettyAttributes [ ( "Process ID"+                                   , prettyProcessId processId processName processThreadId)+                                 , ( "Process Type", pretty processType)+                                 , ( "Callback", pretty processCallbackType)+                                 ]+          Just err ->+            "Process executed callback and it failed"+             <> prettyAttributes [ ( "Process ID"+                                   , prettyProcessId processId processName processThreadId)+                                 , ( "Process Type", pretty processType)+                                 , ( "Callback", pretty processCallbackType)+                                 , ( "Error"+                                   , Pretty.nest 2+                                       (Pretty.hardline+                                         <> "|"+                                         <+> pretty (ppShow err)))+                                 ]++      ProcessTerminationStarted {+          supervisorId+        , supervisorName+        , terminationReason+        } ->+        "Supervisor started termination of its children"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ( "Reason"+                              , Pretty.nest 2+                                  (Pretty.fillBreak 10 $ pretty terminationReason))+                            ]++      ProcessTerminationFinished {+          supervisorId+        , supervisorName+        } ->+        "Supervisor finished termination of its children"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            ]++      CapatazFailed {+          supervisorId+        , supervisorName+        , supervisorError+        } ->+        "Root Supervisor had a fatal failure"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            , ( "Error"+                              , Pretty.nest 2+                                  (Pretty.hardline+                                    <> "|"+                                    <+> pretty (ppShow supervisorError)))+                            ]++      CapatazTerminated {+          supervisorId+        , supervisorName+        } ->+        "Root supervisor was terminated"+        <> prettyAttributes [ ("Supervisor ID"+                              , prettySupervisorId supervisorId supervisorName)+                            ]+    where+      prettyAttributes attrList =+        Pretty.nest 4+          (Pretty.hardline+           <> Pretty.vsep (map (\(k, v) -> Pretty.fill 20 (k <> ":") <+> v)+                                attrList))++      prettySupervisorId supId supName =+        Pretty.angles+        $ pretty (show supId) <> "/" <> pretty supName++      prettyProcessId procId procName procTid =+        Pretty.angles+        $ pretty (show procId) <> "/" <> pretty procName <> "/" <> pretty procTid++-- | @since 0.2.0.0+instance Display CapatazEvent where+  display = displayShow . pretty++-- | Defines how a 'Worker' process termination should be handled by its -- supervisor.+--+-- @since 0.0.0.0 data WorkerTerminationPolicy   -- | Supervisor waits until infinity for the worker termination callback to   -- finish execution.@@ -148,9 +371,11 @@   | TimeoutMillis !Int   deriving (Generic, Show, Eq, Ord) -instance Default WorkerTerminationPolicy where-  -- | Default worker termination is a timeout of three (3) seconds.-  def = TimeoutMillis 3000+-- | Default worker termination is a timeout of three (3) seconds.+--+-- @since 0.2.0.0+defWorkerTerminationPolicy :: WorkerTerminationPolicy+defWorkerTerminationPolicy = TimeoutMillis 3000  instance NFData WorkerTerminationPolicy @@ -174,6 +399,8 @@  -- | Specifies the order in which supervised process should be terminated by a -- Supervisor in case of a restart or shutdown.+--+-- @since 0.0.0.0 data ProcessTerminationOrder   -- | Supervisor terminates supervised process from most recent to oldest.   = NewestFirst@@ -181,13 +408,17 @@   | OldestFirst   deriving (Generic, Show, Eq, Ord) -instance Default ProcessTerminationOrder where-  -- | default is "OldestFirst".-  def = OldestFirst+-- | Default termination order is 'OldestFirst'.+--+-- @since 0.2.0.0+defProcessTerminationOrder :: ProcessTerminationOrder+defProcessTerminationOrder = OldestFirst  instance NFData ProcessTerminationOrder  -- | Specifies how a Supervisor restarts a failing process.+--+-- @since 0.0.0.0 data SupervisorRestartStrategy   -- | Supervisor terminates all sibling supervised processes that didn't fail,   -- and then restarts all of them together. This strategy serves best when all@@ -198,31 +429,34 @@   | OneForOne   deriving (Generic, Show, Eq, Ord) -instance Default SupervisorRestartStrategy where-  -- | Default restart strategy is "OneForOne".-  def = OneForOne+-- | Default restart strategy is 'OneForOne'.+--+-- @since 0.2.0.0+defSupervisorRestartStategy :: SupervisorRestartStrategy+defSupervisorRestartStategy = OneForOne  instance NFData SupervisorRestartStrategy  -- | Allows to: ----- * Specify options for The root supervisor of a capataz system.+-- * Specify options for the root 'Supervisor' of a capataz system. ----- * Provie a "notifyEvent" callback to monitor or log a capataz system.+-- * Provide a 'notifyEvent' callback to monitor or log a capataz system. ---data CapatazOptions+-- @since 0.1.0.0+data CapatazOptions m   = CapatazOptions {     supervisorName                    :: !SupervisorName   , supervisorIntensity               :: !Int   , supervisorPeriodSeconds           :: !NominalDiffTime   , supervisorRestartStrategy         :: !SupervisorRestartStrategy-  , supervisorProcessSpecList         :: ![ProcessSpec]+  , supervisorProcessSpecList         :: ![ProcessSpec m]   , supervisorProcessTerminationOrder :: !ProcessTerminationOrder-  , supervisorOnIntensityReached      :: !(IO ())+  , supervisorOnIntensityReached      :: !(m ())     -- | Callback sub-routine that gets executed when the root supervisor fails.-  , supervisorOnFailure               :: !(SomeException -> IO ())+  , supervisorOnFailure               :: !(SomeException -> m ())     -- | Callback used for telemetry purposes.-  , notifyEvent                       :: !(CapatazEvent -> IO ())+  , notifyEvent                       :: !(CapatazEvent -> m ())   }  @@ -243,26 +477,29 @@   deriving (Generic, Show, Eq)  instance NFData WorkerRestartStrategy-instance Default WorkerRestartStrategy where-  -- |  A worker default restart strategy is "Transient".-  def = Transient +-- |  A worker default restart strategy is "Transient".+defWorkerRestartStrategy :: WorkerRestartStrategy+defWorkerRestartStrategy = Transient+ -- | Specifies all options that can be used to create a Worker Process. You may--- create a record of this type via the smart constructor "buildWorkerOptions".-data WorkerOptions+-- create a record of this type via the smart constructor 'buildWorkerOptions'.+--+-- @since 0.1.0.0+data WorkerOptions m   = WorkerOptions {     -- | An @IO ()@ sub-routine that will be executed when the worker     -- thread is created, this attribute is lazy given we want to this     -- value on a worker thread environment.-    workerAction            :: WorkerAction+    workerAction            :: WorkerAction m     -- | Name of the Worker (present on "CapatazEvent" records)   , workerName              :: !WorkerName     -- | Callback used when the worker fails with an error-  , workerOnFailure         :: !(SomeException -> IO ())+  , workerOnFailure         :: !(SomeException -> m ())     -- | Callback used when the worker completes execution without error-  , workerOnCompletion      :: !(IO ())+  , workerOnCompletion      :: !(m ())     -- | Callback used when the worker is terminated-  , workerOnTermination     :: !(IO ())+  , workerOnTermination     :: !(m ())     -- | Indicates how a worker should be terminated   , workerTerminationPolicy :: !WorkerTerminationPolicy     -- | Indicates how a worker should be restarted@@ -271,7 +508,9 @@   deriving (Generic)  -- | Record that contains the "Async" record (thread reference) of a worker-data Worker+--+-- @since 0.1.0.0+data Worker m   = Worker {     -- | Unique identifier for a worker that is executing     workerId           :: !WorkerId@@ -283,7 +522,7 @@   , workerName         :: !WorkerName     -- | "WorkerOptions" contains all the options around restart and termination     -- policies-  , workerOptions      :: !WorkerOptions+  , workerOptions      :: !(WorkerOptions m)   }  data ProcessEnv@@ -295,7 +534,7 @@   , processRestartStrategy :: !WorkerRestartStrategy   } -data SupervisorOptions+data SupervisorOptions m   = SupervisorOptions {     -- | Name of the Supervisor (present on "CapatazEvent" records)     supervisorName                    :: Text@@ -308,40 +547,40 @@     -- | What is the "SupervisorRestartStrategy" for this Capataz   , supervisorRestartStrategy         :: !SupervisorRestartStrategy     -- | Static set of workers that start as soon as the "Capataz" is created-  , supervisorProcessSpecList         :: ![ProcessSpec]+  , supervisorProcessSpecList         :: ![ProcessSpec m]     -- | In which order the "Supervisor" record is going to terminate it's workers   , supervisorProcessTerminationOrder :: !ProcessTerminationOrder     -- | Callback used when the error intensity is reached-  , supervisorOnIntensityReached      :: !(IO ())-  , supervisorOnFailure               :: !(SomeException -> IO ())+  , supervisorOnIntensityReached      :: !(m ())+  , supervisorOnFailure               :: !(SomeException -> m ())   } -data Supervisor+data Supervisor m   = Supervisor {     supervisorId           :: !SupervisorId   , supervisorName         :: !SupervisorName-  , supervisorOptions      :: !SupervisorOptions+  , supervisorOptions      :: !(SupervisorOptions m)   , supervisorCreationTime :: !UTCTime   , supervisorAsync        :: !(Async ())-  , supervisorNotify       :: SupervisorMessage -> IO ()-  , supervisorEnv          :: !SupervisorEnv+  , supervisorNotify       :: SupervisorMessage m -> m ()+  , supervisorEnv          :: !(SupervisorEnv m)   }  -- | Internal record that represents an action being sent from threads using -- the Capataz public API.-data ControlAction+data ControlAction m   = ForkWorker {-    workerOptions  :: !WorkerOptions-  , returnWorkerId :: !(WorkerId -> IO ())+    workerOptions  :: !(WorkerOptions m)+  , returnWorkerId :: !(WorkerId -> m ())   }   | ForkSupervisor {-    supervisorOptions :: !SupervisorOptions-  , returnSupervisor  :: !(Supervisor -> IO ())+    supervisorOptions :: !(SupervisorOptions m)+  , returnSupervisor  :: !(Supervisor m -> m ())   }   | TerminateProcess {     processId                :: !ProcessId   , processTerminationReason :: !Text-  , notifyProcessTermination :: !(Bool -> IO ())+  , notifyProcessTermination :: !(Bool -> m ())   }   deriving (Generic) @@ -384,11 +623,20 @@   | OnTermination   deriving (Generic, Show, Eq) +instance Pretty CallbackType where+  pretty = Pretty.pretty . show+ data ProcessType   = SupervisorType   | WorkerType   deriving (Show, Eq) +instance Pretty ProcessType  where+  pretty ty =+    case ty of+      SupervisorType -> "Supervisor"+      WorkerType     -> "Worker"+ -- | Internal exception triggered when a callback of a Worker fails data ProcessError   = ProcessCallbackFailed {@@ -448,97 +696,108 @@  instance NFData SupervisorStatus +instance Pretty SupervisorStatus where+  pretty =+    pretty . show+ -- | Internal message delivered to a supervisor process that can either be a -- call from public API or an event from its monitored worker process.-data SupervisorMessage+data SupervisorMessage m   -- | Represents a request from done to the supervisor thread from another   -- thread using the public API-  = ControlAction !ControlAction+  = ControlAction !(ControlAction m)   -- | Represents an event (failure, completion, etc) from a monitored worker   -- process to the supervisor   | MonitorEvent !MonitorEvent   deriving (Generic) --- | Internal Type to manage both Worker and Supervisor processes-data Process-  = WorkerProcess  Worker-  | SupervisorProcess Supervisor+-- | Internal Type to manage both 'Worker' and 'Supervisor' processes+--+-- @since 0.1.0.0+data Process m+  = WorkerProcess  !(Worker m)+  | SupervisorProcess !(Supervisor m) --- | Record used to specify how to __build__ a runtime "Process" in a static+-- | Record used to specify how to __build__ a runtime 'Process' in a static -- supervision tree; to create values of this type, you must use: ----- * "workerSpec" or "workerSpecWithDefaults" to build a worker process+-- * 'workerSpec' or 'workerSpecWithDefaults' to build a worker process ----- * "supervisorSpec" or "supervisorSpecWithDefaults" to build a supervisor+-- * 'supervisorSpec' or 'supervisorSpecWithDefaults' to build a supervisor -- process ---data ProcessSpec-  = WorkerSpec WorkerOptions-  | SupervisorSpec SupervisorOptions+-- @since 0.1.0.0+data ProcessSpec m+  = WorkerSpec (WorkerOptions m)+  | SupervisorSpec (SupervisorOptions m)  -- | Record that contains the environment of a capataz monitor, this is used as -- the main record to create workers and to stop the supervisor thread.-data Capataz+--+-- @since 0.0.0.0+data Capataz m   = Capataz {-    capatazSupervisor :: !Supervisor+    capatazSupervisor :: !(Supervisor m)   , capatazTeardown   :: !Teardown   } -instance ITeardown Capataz where-  teardown Capataz {capatazTeardown} =-    teardown capatazTeardown+instance HasTeardown (Capataz m) where+  getTeardown Capataz {capatazTeardown} =+    capatazTeardown  -- | Internal utility record used to hold part of the runtime information of a -- supervisor that acts as a parent of another supervisor.-data ParentSupervisorEnv+data ParentSupervisorEnv m   = ParentSupervisorEnv {     supervisorId     :: !SupervisorId   , supervisorName   :: !SupervisorName-  , supervisorNotify :: !(SupervisorMessage -> IO ())-  , notifyEvent      :: !(CapatazEvent -> IO ())+  , supervisorNotify :: !(SupervisorMessage m -> m ())+  , notifyEvent      :: !(CapatazEvent -> m ())   }  -- | Convenience internal utility record that contains all values related to a -- supervisor process.-data SupervisorEnv+data SupervisorEnv m   = SupervisorEnv {     supervisorId                      :: !SupervisorId   , supervisorName                    :: !SupervisorName-  , supervisorNotify                  :: !(SupervisorMessage -> IO ())-  , supervisorGetNotification         :: !(STM SupervisorMessage)-  , supervisorProcessMap              :: !(IORef ProcessMap)+  , supervisorNotify                  :: !(SupervisorMessage m -> m ())+  , supervisorGetNotification         :: !(STM (SupervisorMessage m))+  , supervisorProcessMap              :: !(IORef (ProcessMap m))   , supervisorStatusVar               :: !(TVar SupervisorStatus)-  , supervisorOptions                 :: !SupervisorOptions+  , supervisorOptions                 :: !(SupervisorOptions m)   , supervisorIntensity               :: !Int     -- ^ http://erlang.org/doc/design_principles/sup_princ.html#max_intensity   , supervisorPeriodSeconds           :: !NominalDiffTime   , supervisorRestartStrategy         :: !SupervisorRestartStrategy   , supervisorProcessTerminationOrder :: !ProcessTerminationOrder-  , supervisorOnIntensityReached      :: !(IO ())-  , supervisorOnIntensityReached      :: !(SomeException -> IO ())-  , notifyEvent                       :: !(CapatazEvent -> IO ())+  , supervisorOnIntensityReached      :: !(m ())+  , supervisorOnIntensityReached      :: !(SomeException -> m ())+  , notifyEvent                       :: !(CapatazEvent -> m ())   } --- | Builds a "CapatazOptions" record with defaults on how to create a capataz+-- | Builds a 'CapatazOptions' record with defaults on how to create a capataz -- root supervisor, these defaults are: -- -- * Intensity error tolerance is set to 1 error every 5 seconds ----- * A "SupervisorRestartStrategy" of "OneForOne"+-- * A 'SupervisorRestartStrategy' of 'OneForOne' ----- * A "ProcessTerminationOrder" of "OldestFirst"+-- * A 'ProcessTerminationOrder' of 'OldestFirst' ----- This function is intended to be used in combination with "forkCapataz".+-- This function is intended to be used in combination with 'forkCapataz'. --+-- @since 0.1.0.0 defCapatazOptions-  :: Text-  -> (CapatazOptions -> CapatazOptions) -- ^ Function to modify root supervisor-  -> CapatazOptions+  :: Monad m+  => Text+  -> (CapatazOptions m -> CapatazOptions m) -- ^ Function to modify root supervisor+  -> CapatazOptions m defCapatazOptions supervisorName modFn = modFn CapatazOptions   { supervisorName   , supervisorIntensity               = 2   , supervisorPeriodSeconds           = 5-  , supervisorRestartStrategy         = def+  , supervisorRestartStrategy         = defSupervisorRestartStategy   , supervisorProcessSpecList         = []   , supervisorProcessTerminationOrder = OldestFirst   , supervisorOnIntensityReached      = return ()@@ -546,78 +805,106 @@   , notifyEvent                       = const $ return ()   } --- | Builds a "ProcessSpec" record for a supervisor process with defaults from--- "supervisorSpecWithDefaults". This function allows overrides of these+-- | Builds a 'ProcessSpec' record for a supervisor process with defaults from+-- 'supervisorSpecWithDefaults'. This function allows overrides of these -- defaults using lenses. -- -- This function is used when building a supervisor branch in a static -- supervision trees. --+-- @since 0.1.0.0 supervisorSpec-  :: SupervisorName -- ^ Name used for telemetry purposes-  -> (SupervisorOptions -> SupervisorOptions) -- ^ Function to modify default-                                              -- supervisor options-  -> ProcessSpec+  :: Monad m+  => SupervisorName -- ^ Name used for telemetry purposes+  -> (SupervisorOptions m -> SupervisorOptions m) -- ^ 'SupervisorOptions' modifier+  -> ProcessSpec m supervisorSpec sName modFn =   SupervisorSpec (buildSupervisorOptions sName modFn) {-# INLINE supervisorSpec #-} --- | Builds a "ProcessSpec" record for a supervisor process with defaults from---  "buildSupervisorOptionsWithDefaults".+-- | Builds a 'ProcessSpec' record for a supervisor process with defaults from+--  'buildSupervisorOptionsWithDefaults'. -- -- This function is used when building a supervisor branch in a static -- supervision trees. --+-- @since 0.1.0.0 supervisorSpecWithDefaults-  :: SupervisorName -- ^ Name used for telemetry purposes-  -> ProcessSpec-supervisorSpecWithDefaults sName = supervisorSpec sName identity+  :: Monad m+  => SupervisorName -- ^ Name used for telemetry purposes+  -> ProcessSpec m+supervisorSpecWithDefaults sName = supervisorSpec sName id {-# INLINE supervisorSpecWithDefaults #-} --- | Builds a "ProcessSpec" record for a worker process with defaults from--- "workerSpecWithDefaults". This function allows overrides of these+-- | Builds a 'ProcessSpec' record for a worker process with defaults from+-- 'workerSpecWithDefaults'. This function allows overrides of these -- defaults using lenses. -- -- This function is used when building a worker in a static supervision tree. --+-- @since 0.1.0.0 workerSpec-  :: WorkerName -- ^ Name used for telemetry purposes-  -> IO () -- ^ IO sub-routine to be supervised-  -> (WorkerOptions -> WorkerOptions) -- ^ Function to modify default worker+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> m () -- ^ 'IO' sub-routine to be supervised+  -> (WorkerOptions m -> WorkerOptions m) -- ^ Function to modify default worker                                       -- options-  -> ProcessSpec+  -> ProcessSpec m workerSpec wName wAction modFn =   WorkerSpec (buildWorkerOptions wName wAction modFn) {-# INLINE workerSpec #-} --- | Builds a "ProcessSpec" record for a worker process with defaults from--- "buildSupervisorOptionsWithDefaults".+-- | Builds a 'ProcessSpec' record for a worker process with defaults from+-- 'workerSpecWithDefaults'. This function allows overrides of these+-- defaults using lenses. -- -- This function is used when building a worker in a static supervision tree.+-- The given sub-routine will receive the 'WorkerId' as a parameter --+-- @since 0.2.0.0+workerSpec1+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> (WorkerId -> m ()) -- ^ sub-routine to be supervised+  -> (WorkerOptions m -> WorkerOptions m) -- ^ Function to modify default worker+                                      -- options+  -> ProcessSpec m+workerSpec1 wName wAction modFn =+  WorkerSpec (buildWorkerOptions1 wName wAction modFn)+{-# INLINE workerSpec1 #-}++-- | Builds a 'ProcessSpec' record for a worker process with defaults from+-- 'buildSupervisorOptionsWithDefaults'.+--+-- This function is used when building a worker in a static supervision tree.+--+-- @since 0.1.0.0 workerSpecWithDefaults-  :: WorkerName -- ^ Name used for telemetry purposes-  -> IO () -- ^ IO sub-routine to be supervised-  -> ProcessSpec-workerSpecWithDefaults wName wAction = workerSpec wName wAction identity+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> m () -- ^ IO sub-routine to be supervised+  -> ProcessSpec m+workerSpecWithDefaults wName wAction = workerSpec wName wAction id {-# INLINE workerSpecWithDefaults #-} --- | Builds a "SupervisorOptions" record with defaults from--- "buildSupervisorOptionsWithDefaults". This function allows overrides of these+-- | Builds a 'SupervisorOptions' record with defaults from+-- 'buildSupervisorOptionsWithDefaults'. This function allows overrides of these -- defaults using lenses. ----- This function is intended to be used in combination with "forkSupervisor".+-- This function is intended to be used in combination with 'forkSupervisor'. --+-- @since 0.1.0.0 buildSupervisorOptions-  :: SupervisorName -- ^ Name used for telemetry purposes-  -> (SupervisorOptions -> SupervisorOptions) -- ^ Function to modify default+  :: Monad m+  => SupervisorName -- ^ Name used for telemetry purposes+  -> (SupervisorOptions m -> SupervisorOptions m) -- ^ Function to modify default                                               -- supervisor options-  -> SupervisorOptions+  -> SupervisorOptions m buildSupervisorOptions supervisorName modFn = modFn SupervisorOptions   { supervisorName   , supervisorIntensity               = 2   , supervisorPeriodSeconds           = 5-  , supervisorRestartStrategy         = def+  , supervisorRestartStrategy         = defSupervisorRestartStategy   , supervisorProcessSpecList         = []   , supervisorProcessTerminationOrder = OldestFirst   , supervisorOnIntensityReached      = return ()@@ -625,52 +912,77 @@   } {-# INLINE buildSupervisorOptions #-} --- | Builds a "SupervisorOptions" record with defaults to create a supervisor+-- | Builds a 'SupervisorOptions' record with defaults to create a supervisor -- process, these defaults are: -- -- * Intensity error tolerance is set to 1 error every 5 seconds ----- * A "SupervisorRestartStrategy" of "OneForOne"+-- * A 'SupervisorRestartStrategy' of 'OneForOne' ----- * A "ProcessTerminationOrder" of "OldestFirst"+-- * A 'ProcessTerminationOrder' of 'OldestFirst' ----- This function is intended to be used in combination with "forkSupervisor".+-- This function is intended to be used in combination with 'forkSupervisor'. --+-- @since 0.1.0.0 buildSupervisorOptionsWithDefaults-  :: SupervisorName -- ^ Name used for telemetry purposes-  -> SupervisorOptions-buildSupervisorOptionsWithDefaults = flip buildSupervisorOptions identity+  :: Monad m+  => SupervisorName -- ^ Name used for telemetry purposes+  -> SupervisorOptions m+buildSupervisorOptionsWithDefaults = flip buildSupervisorOptions id {-# INLINE buildSupervisorOptionsWithDefaults #-} --- | Builds a "WorkerOptions" record, keeps the defaults from---   "buildWorkerOptionsWithDefaults" but allows overrides using lenses.+-- | Builds a 'WorkerOptions' record, keeps the defaults from+--   'buildWorkerOptionsWithDefaults' but allows overrides using lenses. ----- This function is intended to be used in combination with "forkWorker". See--- the ... example in the examples directory for a demonstration.+-- This function is intended to be used in combination with 'forkWorker'. See the+-- capataz-simple-example project in the examples directory for a demonstration. --+-- @since 0.1.0.0 buildWorkerOptions-  :: WorkerName -- ^ Name used for telemetry purposes-  -> IO () -- ^ IO sub-routine to be supervised-  -> (WorkerOptions -> WorkerOptions) -- ^ Function to modify default worker+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> m () -- ^ Process sub-routine to be supervised+  -> (WorkerOptions m -> WorkerOptions m) -- ^ Function to modify default worker                                       -- options-  -> WorkerOptions-buildWorkerOptions workerName workerAction f = f WorkerOptions+  -> WorkerOptions m+buildWorkerOptions workerName workerAction f =+  buildWorkerOptions1 workerName (const workerAction) f+{-# INLINE buildWorkerOptions #-}++-- | Builds a 'WorkerOptions' record, keeps the defaults from+--   'buildWorkerOptionsWithDefaults' but allows overrides using lenses.+--+-- This function is intended to be used in combination with 'forkWorker'. See the+-- capataz-simple-example project in the examples directory for a demonstration.+--+-- The given sub-routine will receive the 'WorkerId' as a parameter.+--+-- @since 0.2.0.0+buildWorkerOptions1+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> (WorkerId -> m ()) -- ^ Process sub-routine to be supervised+  -> (WorkerOptions m -> WorkerOptions m) -- ^ Function to modify default worker+                                      -- options+  -> WorkerOptions m+buildWorkerOptions1 workerName workerAction f = f WorkerOptions   { workerName-  , workerAction+  , workerAction            = workerAction   , workerOnFailure         = const $ return ()   , workerOnCompletion      = return ()   , workerOnTermination     = return ()-  , workerTerminationPolicy = def-  , workerRestartStrategy   = def+  , workerTerminationPolicy = defWorkerTerminationPolicy+  , workerRestartStrategy   = defWorkerRestartStrategy   }-{-# INLINE buildWorkerOptions #-}+{-# INLINE buildWorkerOptions1 #-} --- | Builds a "WorkerOptions" record with defaults to create a worker process,++-- | Builds a 'WorkerOptions' record with defaults to create a worker process, -- the defaults are: ----- * A "Transient" "WorkerRestartStrategy"+-- * A 'Transient' 'WorkerRestartStrategy' ----- * A "WorkerTerminationPolicy" of a 3 seconds timeout+-- * A 'WorkerTerminationPolicy' of a 3 seconds timeout -- -- * A _completion_ callback that just returns unit --@@ -678,14 +990,36 @@ -- -- * A _failure_ callback that just returns unit ----- This function is intended to be used in combination with "forkWorker", for--- creating a worker in an static supervision tree, use "workerSpecWithDefaults"--- instead. See the ... example for a demonstration.+-- This function is intended to be used in combination with 'forkWorker', for creating a+-- worker in an static supervision tree, use 'workerSpecWithDefaults' instead. See the+-- capataz-simple-example project in the examples directory for a demonstration. --+-- @since 0.1.0.0 buildWorkerOptionsWithDefaults-  :: WorkerName -- ^ Name used for telemetry purposes-  -> IO () -- ^ IO sub-routine to be supervised-  -> WorkerOptions+  :: Monad m+  => WorkerName -- ^ Name used for telemetry purposes+  -> m () -- ^ 'IO' sub-routine to be supervised+  -> WorkerOptions m buildWorkerOptionsWithDefaults wName wAction =-  buildWorkerOptions wName wAction identity+  buildWorkerOptions wName wAction id {-# INLINE buildWorkerOptionsWithDefaults #-}++-- | Used for debugging purposes+getMaskingState :: MonadIO m => m UnsafeE.MaskingState+getMaskingState = liftIO UnsafeE.getMaskingState++-- | Given we want to capture async exceptions to send them back to a supervisor+-- and we are running on masked states, we need to have a try that catches all+-- kinds of exceptions+unsafeTry :: (Exception e, MonadUnliftIO m) => m a -> m (Either e a)+unsafeTry action = withRunInIO $ \run -> UnsafeE.try (run action)++-- | Given unliftio wraps exceptions in 3 layers of Exceptions, and we are using+-- vanilla exceptions, we need to make sure that we account for all different+-- exception types+fromAnyException :: Exception e => SomeException -> Maybe e+fromAnyException ex = case UnsafeE.fromException ex of+  Just (UnsafeE.SomeAsyncException innerEx1) -> case cast innerEx1 of+    Just (AsyncExceptionWrapper innerEx2) -> cast innerEx2+    Nothing                               -> cast innerEx1+  Nothing -> fromException ex
src/Control/Concurrent/Capataz/Internal/Types/Lens.hs view
@@ -3,9 +3,10 @@ {-# LANGUAGE RecordWildCards   #-} module Control.Concurrent.Capataz.Internal.Types.Lens where +import RIO+ import Control.Concurrent.Capataz.Internal.Types-import Data.Time.Clock                           (NominalDiffTime)-import Protolude+import RIO.Time                                  (NominalDiffTime)  -------------------------------------------------------------------------------- @@ -40,9 +41,9 @@   -- supervisor.   supervisorProcessSpecListL     :: Functor f-    => ([ProcessSpec] -> f [ProcessSpec])-    -> s-    -> f s+    => ([ProcessSpec m] -> f [ProcessSpec m])+    -> s m+    -> f (s m)  class HasSupervisorProcessTerminationOrder s where   -- | Specifies order in which a supervisor is going to terminate its@@ -58,31 +59,31 @@   -- breach in a supervisor's error intensity.   supervisorOnIntensityReachedL     :: Functor f-    => (IO () -> f (IO ()))-    -> s-    -> f s+    => (m () -> f (m ()))+    -> s m+    -> f (s m)  class HasSupervisorFailureCallback s where   -- | Specifies callback sub-routine that gets executed when a supervisor   -- fails.   supervisorOnFailureL     :: Functor f-    => ((SomeException -> IO ()) -> f (SomeException -> IO ()))-    -> s-    -> f s+    => ((SomeException -> m ()) -> f (SomeException -> m ()))+    -> s m+    -> f (s m)  -instance HasSupervisorIntensity SupervisorOptions where+instance HasSupervisorIntensity (SupervisorOptions m) where   supervisorIntensityL k SupervisorOptions {supervisorIntensity, ..} =     fmap (\newSupIntensity -> SupervisorOptions { supervisorIntensity = newSupIntensity, .. })          (k supervisorIntensity) -instance HasSupervisorPeriodSeconds SupervisorOptions where+instance HasSupervisorPeriodSeconds (SupervisorOptions m) where   supervisorPeriodSecondsL k SupervisorOptions {supervisorPeriodSeconds, ..} =     fmap (\newSupPeriodSeconds -> SupervisorOptions { supervisorPeriodSeconds = newSupPeriodSeconds, .. })          (k supervisorPeriodSeconds) -instance HasSupervisorRestartStrategy SupervisorOptions where+instance HasSupervisorRestartStrategy (SupervisorOptions m) where   supervisorRestartStrategyL k SupervisorOptions {supervisorRestartStrategy, ..} =     fmap (\newSupRestartStrategy ->             SupervisorOptions { supervisorRestartStrategy = newSupRestartStrategy, .. })@@ -94,7 +95,7 @@             SupervisorOptions { supervisorProcessSpecList = newSupProcessSpecList, .. })          (k supervisorProcessSpecList) -instance HasSupervisorProcessTerminationOrder SupervisorOptions where+instance HasSupervisorProcessTerminationOrder (SupervisorOptions m) where   supervisorProcessTerminationOrderL k SupervisorOptions {supervisorProcessTerminationOrder, ..} =     fmap (\newSupProcessTerminationOrder ->             SupervisorOptions { supervisorProcessTerminationOrder = newSupProcessTerminationOrder, .. })@@ -112,17 +113,17 @@  -------------------- -instance HasSupervisorIntensity CapatazOptions where+instance HasSupervisorIntensity (CapatazOptions m) where   supervisorIntensityL k CapatazOptions {supervisorIntensity, ..} =     fmap (\newSupIntensity -> CapatazOptions { supervisorIntensity = newSupIntensity, .. })          (k supervisorIntensity) -instance HasSupervisorPeriodSeconds CapatazOptions where+instance HasSupervisorPeriodSeconds (CapatazOptions m) where   supervisorPeriodSecondsL k CapatazOptions {supervisorPeriodSeconds, ..} =     fmap (\newSupPeriodSeconds -> CapatazOptions { supervisorPeriodSeconds = newSupPeriodSeconds, .. })          (k supervisorPeriodSeconds) -instance HasSupervisorRestartStrategy CapatazOptions where+instance HasSupervisorRestartStrategy (CapatazOptions m) where   supervisorRestartStrategyL k CapatazOptions {supervisorRestartStrategy, ..} =     fmap (\newSupRestartStrategy ->             CapatazOptions { supervisorRestartStrategy = newSupRestartStrategy, .. })@@ -134,7 +135,7 @@             CapatazOptions { supervisorProcessSpecList = newSupProcessSpecList, .. })          (k supervisorProcessSpecList) -instance HasSupervisorProcessTerminationOrder CapatazOptions where+instance HasSupervisorProcessTerminationOrder (CapatazOptions m) where   supervisorProcessTerminationOrderL k CapatazOptions {supervisorProcessTerminationOrder, ..} =     fmap (\newSupProcessTerminationOrder ->             CapatazOptions { supervisorProcessTerminationOrder = newSupProcessTerminationOrder, .. })@@ -155,9 +156,9 @@   -- telemetry purposes (e.g. logging, monitoring, etc). onSystemEventL   :: Functor f-  => ((CapatazEvent -> IO ()) -> f (CapatazEvent -> IO ()))-  -> CapatazOptions-  -> f CapatazOptions+  => ((CapatazEvent -> m ()) -> f (CapatazEvent -> m ()))+  -> CapatazOptions m+  -> f (CapatazOptions m) onSystemEventL k CapatazOptions { notifyEvent, ..} = fmap   (\newNotifyEvent -> CapatazOptions {notifyEvent = newNotifyEvent, ..})   (k notifyEvent)@@ -171,10 +172,10 @@ -- worker "WorkerTerminationPolicy". -- workerOnFailureL-  :: Functor f-  => ((SomeException -> IO ()) -> f (SomeException -> IO ()))-  -> WorkerOptions-  -> f WorkerOptions+  :: (Functor f)+  => ((SomeException -> m ()) -> f (SomeException -> m ()))+  -> WorkerOptions m+  -> f (WorkerOptions m) workerOnFailureL k WorkerOptions { workerOnFailure, ..} = fmap   (\newWorkerAction -> WorkerOptions {workerOnFailure = newWorkerAction, ..})   (k workerOnFailure)@@ -186,7 +187,7 @@ -- worker "WorkerTerminationPolicy". -- workerOnCompletionL-  :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions+  :: (Functor f) => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m) workerOnCompletionL k WorkerOptions { workerOnCompletion, ..} = fmap   (\newWorkerAction -> WorkerOptions {workerOnCompletion = newWorkerAction, ..})   (k workerOnCompletion)@@ -199,10 +200,9 @@ -- worker "WorkerTerminationPolicy". -- workerOnTerminationL-  :: Functor f => (IO () -> f (IO ())) -> WorkerOptions -> f WorkerOptions+  :: Functor f => (m () -> f (m ())) -> WorkerOptions m -> f (WorkerOptions m) workerOnTerminationL k WorkerOptions { workerOnTermination, ..} = fmap-  ( \newWorkerAction ->-    WorkerOptions {workerOnTermination = newWorkerAction, ..}+  (\newWorkerAction -> WorkerOptions {workerOnTermination = newWorkerAction, ..}   )   (k workerOnTermination) @@ -211,10 +211,10 @@ workerTerminationPolicyL   :: Functor f   => (WorkerTerminationPolicy -> f WorkerTerminationPolicy)-  -> WorkerOptions-  -> f WorkerOptions+  -> WorkerOptions m+  -> f (WorkerOptions m) workerTerminationPolicyL k WorkerOptions { workerTerminationPolicy, ..} = fmap-  ( \newWorkerAction ->+  (\newWorkerAction ->     WorkerOptions {workerTerminationPolicy = newWorkerAction, ..}   )   (k workerTerminationPolicy)@@ -224,10 +224,10 @@ workerRestartStrategyL   :: Functor f   => (WorkerRestartStrategy -> f WorkerRestartStrategy)-  -> WorkerOptions-  -> f WorkerOptions+  -> WorkerOptions m+  -> f (WorkerOptions m) workerRestartStrategyL k WorkerOptions { workerRestartStrategy, ..} = fmap-  ( \newWorkerAction ->+  (\newWorkerAction ->     WorkerOptions {workerRestartStrategy = newWorkerAction, ..}   )   (k workerRestartStrategy)
src/Control/Concurrent/Capataz/Internal/Util.hs view
@@ -12,30 +12,28 @@ -} module Control.Concurrent.Capataz.Internal.Util where -import Protolude+import           RIO+import qualified RIO.HashMap as HashMap+import qualified RIO.List    as List+import qualified RIO.Text    as T -import           Control.Concurrent.STM      (STM, atomically, retry)-import           Control.Concurrent.STM.TVar (TVar, readTVar, writeTVar)-import           Data.IORef                  (atomicModifyIORef', readIORef)-import qualified Data.Text                   as T-import           Data.Time.Clock             (getCurrentTime)+import RIO.Time (getCurrentTime) -import qualified Data.HashMap.Strict as HashMap-import           GHC.Conc            (labelThread)+import GHC.Conc (labelThread)  import Control.Concurrent.Capataz.Internal.Types  -- | Returns only the number of the ThreadId. getTidNumber :: ThreadId -> Maybe Text-getTidNumber tid = case T.words $ show tid of-  (_:tidNumber:_) -> Just tidNumber-  _               -> Nothing+getTidNumber tid = case T.words $ tshow tid of+  (_ : tidNumber : _) -> Just tidNumber+  _                   -> Nothing  --------------------------------------------------------------------------------  -- | Internal functions that overwrites the GHC thread name, for increasing -- traceability on GHC internals.-setProcessThreadName :: WorkerId -> WorkerName -> IO ()+setProcessThreadName :: MonadIO m => WorkerId -> WorkerName -> m () setProcessThreadName workerId workerName = do   tid <- myThreadId   let workerIdentifier =@@ -43,55 +41,57 @@           ""           T.unpack           (getTidNumber tid)-  labelThread tid workerIdentifier+  liftIO $ labelThread tid workerIdentifier --- | Gets the "ProcessId" of both a Worker or Supervisor process.-getProcessId :: Process -> ProcessId+-- | Gets the 'ProcessId' of both a Worker or Supervisor process.+getProcessId :: Process m -> ProcessId getProcessId process = case process of   WorkerProcess     Worker { workerId }         -> workerId   SupervisorProcess Supervisor { supervisorId } -> supervisorId --- | Gets a supervised "Process" from a "Supervisor" instance.-fetchProcess :: SupervisorEnv -> ProcessId -> IO (Maybe Process)+-- | Gets a supervised 'Process' from a 'Supervisor' instance.+fetchProcess+  :: MonadIO m => SupervisorEnv m -> ProcessId -> m (Maybe (Process m)) fetchProcess SupervisorEnv { supervisorProcessMap } processId = do   processMap <- readIORef supervisorProcessMap   case HashMap.lookup processId processMap of     Just process -> return $ Just process     _            -> return Nothing --- | Appends a new "Process" to the "Supervisor" existing process map.-appendProcessToMap :: SupervisorEnv -> Process -> IO ()+-- | Appends a new 'Process' to the 'Supervisor' existing process map.+appendProcessToMap :: MonadIO m => SupervisorEnv m -> Process m -> m () appendProcessToMap SupervisorEnv { supervisorProcessMap } process =   atomicModifyIORef' supervisorProcessMap                      (\processMap -> (appendProcess processMap, ()))  where   appendProcess = HashMap.alter (const $ Just process) (getProcessId process) --- | Removes a "Process" from a "Supervisor" existing process map.-removeProcessFromMap :: SupervisorEnv -> ProcessId -> IO ()+-- | Removes a 'Process' from a 'Supervisor' existing process map.+removeProcessFromMap :: MonadIO m => SupervisorEnv m -> ProcessId -> m () removeProcessFromMap SupervisorEnv { supervisorProcessMap } processId =   atomicModifyIORef'     supervisorProcessMap-    ( \processMap -> maybe (processMap, ())-                           (const (HashMap.delete processId processMap, ()))-                           (HashMap.lookup processId processMap)+    (\processMap -> maybe (processMap, ())+                          (const (HashMap.delete processId processMap, ()))+                          (HashMap.lookup processId processMap)     ) --- | Function to modify a "Supervisor" process map using a pure function.-resetProcessMap :: SupervisorEnv -> (ProcessMap -> ProcessMap) -> IO ()+-- | Function to modify a 'Supervisor' process map using a pure function.+resetProcessMap+  :: MonadIO m => SupervisorEnv m -> (ProcessMap m -> ProcessMap m) -> m () resetProcessMap SupervisorEnv { supervisorProcessMap } processMapFn =   atomicModifyIORef' supervisorProcessMap                      (\processMap -> (processMapFn processMap, ())) --- | Function to get a snapshot of a "Supervisor" process map.-readProcessMap :: SupervisorEnv -> IO ProcessMap+-- | Function to get a snapshot of a 'Supervisor' process map.+readProcessMap :: MonadIO m => SupervisorEnv m -> m (ProcessMap m) readProcessMap SupervisorEnv { supervisorProcessMap } =   readIORef supervisorProcessMap --- | Returns all processes of a "Supervisor" by "ProcessTerminationOrder". This--- is used on "AllForOne" restarts and shutdown operations.+-- | Returns all processes of a 'Supervisor' by 'ProcessTerminationOrder'. This+-- is used on 'AllForOne' restarts and shutdown operations. sortProcessesByTerminationOrder-  :: ProcessTerminationOrder -> ProcessMap -> [Process]+  :: ProcessTerminationOrder -> ProcessMap m -> [Process m] sortProcessesByTerminationOrder terminationOrder processMap =   case terminationOrder of     OldestFirst -> workers@@ -103,28 +103,30 @@   processCreationTime (SupervisorProcess Supervisor { supervisorCreationTime })     = supervisorCreationTime -  workers = sortBy (comparing processCreationTime) (HashMap.elems processMap)+  workers =+    List.sortBy (comparing processCreationTime) (HashMap.elems processMap)  -------------------------------------------------------------------------------- --- | Returns the "SupervisorStatus", this sub-routine will retry transaction--- until its associated "Supervisor" has a status different from "Initializing".+-- | Returns the 'SupervisorStatus', this sub-routine will retry transaction+-- until its associated 'Supervisor' has a status different from 'Initializing'. readSupervisorStatusSTM :: TVar SupervisorStatus -> STM SupervisorStatus readSupervisorStatusSTM statusVar = do   status <- readTVar statusVar-  if status == Initializing then retry else return status+  if status == Initializing then retrySTM else return status --- | Executes transaction that returns the "SupervisorStatus".-readSupervisorStatus :: SupervisorEnv -> IO SupervisorStatus+-- | Executes transaction that returns the 'SupervisorStatus'.+readSupervisorStatus :: MonadIO m => SupervisorEnv m -> m SupervisorStatus readSupervisorStatus SupervisorEnv { supervisorStatusVar } =   atomically $ readTVar supervisorStatusVar --- | Modifes the "Supervisor" status.+-- | Modifes the 'Supervisor' status. ----- IMPORTANT: this is the only function that should be used for this purpose+-- __IMPORTANT__ This is the only function that should be used for this purpose -- given it has the side-effect of notifying a status change via the--- "notifyEvent" sub-routine, orginally given in the "CapatazOption" record.-writeSupervisorStatus :: SupervisorEnv -> SupervisorStatus -> IO ()+-- 'notifyEvent' sub-routine, orginally given in the 'CapatazOption' record.+writeSupervisorStatus+  :: MonadIO m => SupervisorEnv m -> SupervisorStatus -> m () writeSupervisorStatus SupervisorEnv { supervisorId, supervisorName, supervisorStatusVar, notifyEvent } newSupervisorStatus   = do @@ -142,9 +144,9 @@       , eventTime       } --- | Used from public API functions to send "ControlAction" messages to a+-- | Used from public API functions to send 'ControlAction' messages to a -- Supervisor thread loop.-sendControlMsg :: SupervisorEnv -> ControlAction -> IO ()+sendControlMsg :: SupervisorEnv m -> ControlAction m -> m () sendControlMsg SupervisorEnv { supervisorNotify } ctrlMsg =   supervisorNotify (ControlAction ctrlMsg) @@ -152,22 +154,23 @@ -- Supervisor thread loop, it receives an IO sub-routine that expects an IO -- operation that blocks a thread until the message is done. sendSyncControlMsg-  :: SupervisorEnv-  -> (IO () -> ControlAction) -- ^ Blocking sub-routine used from the caller-  -> IO ()+  :: MonadIO m+  => SupervisorEnv m+  -> (m () -> ControlAction m) -- ^ Blocking sub-routine used from the caller+  -> m () sendSyncControlMsg SupervisorEnv { supervisorNotify } mkCtrlMsg = do   result <- newEmptyMVar   supervisorNotify (ControlAction $ mkCtrlMsg (putMVar result ()))   takeMVar result --- | Utility function to transform a "CapatazOptions" record to a--- "SupervisorOptions" record.-capatazOptionsToSupervisorOptions :: CapatazOptions -> SupervisorOptions+-- | Utility function to transform a 'CapatazOptions' record to a+-- 'SupervisorOptions' record.+capatazOptionsToSupervisorOptions :: CapatazOptions m -> SupervisorOptions m capatazOptionsToSupervisorOptions CapatazOptions {..} = SupervisorOptions {..} --- | Utility function to transform a "SupervisorEnv" record to a--- "ParentSupervisorEnv" record; used on functions where supervision of+-- | Utility function to transform a 'SupervisorEnv' record to a+-- 'ParentSupervisorEnv' record; used on functions where supervision of -- supervisors is managed.-toParentSupervisorEnv :: SupervisorEnv -> ParentSupervisorEnv+toParentSupervisorEnv :: SupervisorEnv m -> ParentSupervisorEnv m toParentSupervisorEnv SupervisorEnv { supervisorId, supervisorName, supervisorNotify, notifyEvent }   = ParentSupervisorEnv {..}
src/Control/Concurrent/Capataz/Internal/Worker.hs view
@@ -7,10 +7,9 @@ -} module Control.Concurrent.Capataz.Internal.Worker where -import Protolude+import RIO -import Control.Concurrent.Async (asyncWithUnmask)-import Data.Time.Clock          (getCurrentTime)+import RIO.Time (getCurrentTime)  import qualified Data.UUID.V4 as UUID @@ -21,19 +20,18 @@  -- | Decorates the given @IO ()@ sub-routine with failure handling workerMain-  :: ParentSupervisorEnv-  -> WorkerOptions+  :: (MonadUnliftIO m)+  => ParentSupervisorEnv m+  -> WorkerOptions m   -> WorkerId   -> RestartCount-  -> IO Worker+  -> m (Worker m) workerMain env@ParentSupervisorEnv { supervisorNotify } workerOptions@WorkerOptions { workerName, workerAction } workerId restartCount   = do     workerCreationTime <- getCurrentTime     workerAsync        <- asyncWithUnmask $ \unmask -> do--      eResult <- try $ do-        Util.setProcessThreadName workerId workerName-        unmask workerAction+      Util.setProcessThreadName workerId workerName+      eResult     <- unsafeTry $ unmask (workerAction workerId)        resultEvent <- case eResult of         Left err -> Process.handleProcessException unmask@@ -62,14 +60,15 @@ -- this is different from the public @forkWorker@ function which sends a message -- to the capataz loop forkWorker-  :: ParentSupervisorEnv-  -> WorkerOptions+  :: (MonadUnliftIO m)+  => ParentSupervisorEnv m+  -> WorkerOptions m   -> Maybe (WorkerId, RestartCount)-  -> IO Worker+  -> m (Worker m) forkWorker env workerOptions mRestartInfo = do   (workerId, restartCount) <- case mRestartInfo of     Just (workerId, restartCount) -> pure (workerId, restartCount)-    Nothing                       -> (,) <$> UUID.nextRandom <*> pure 0+    Nothing                       -> (,) <$> liftIO UUID.nextRandom <*> pure 0    worker <- workerMain env workerOptions workerId restartCount   Process.notifyProcessStarted mRestartInfo env (WorkerProcess worker)
src/Control/Concurrent/Capataz/Lens.hs view
@@ -17,5 +17,4 @@     , workerRestartStrategyL     , workerTerminationPolicyL     )-import Lens.Micro                                     as X (set, (&), (.~), (^.))-import Lens.Micro.Extras                              as X (view)+import RIO                                            as X (set, view, (&), (^.))
+ src/Control/Concurrent/Capataz/Util.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE NamedFieldPuns    #-}++{-# LANGUAGE NoImplicitPrelude #-}+module Control.Concurrent.Capataz.Util (+    buildLogWorkerSpec+  , buildLogWorkerOptions+  ) where++import Control.Concurrent.Capataz+    ( ProcessSpec+    , WorkerName+    , WorkerOptions+    , WorkerRestartStrategy (Permanent)+    , buildWorkerOptions+    , workerRestartStrategyL+    , workerSpec+    )+import RIO++data LogMsg+  = LogMsg+  {+    lmCallStack :: !CallStack+  , lmLogSource :: !LogSource+  , lmLogLevel  :: !LogLevel+  , lmPayload   :: !Utf8Builder+  }+++runLoggerThread :: MonadUnliftIO m => LogOptions -> TBQueue LogMsg -> m a+runLoggerThread logOptions inputQueue = withLogFunc logOptions $ \logFunc ->+  runRIO logFunc $ forever $ do+    logMsg <- atomically $ readTBQueue inputQueue+    let LogMsg { lmLogSource, lmLogLevel, lmPayload } = logMsg+    -- TODO: create a ticket for a logGenericWithStack function in rio+    logGeneric lmLogSource lmLogLevel lmPayload++-- | Builds a 'ProcessSpec' that spawns a thread that logs messages written with+-- the returned 'LogFunc'. Use this function when your want your logger to be+-- part of a static supervision tree.+--+--+-- __IMPORTANT__ If you use the returned 'LogFunc' to log functions and the+-- 'ProcessSpec' is not used in a supervision tree, your logging won't work and+-- your application will eventually block the current thread when logging.+--+-- A minimal example:+--+-- @+-- {-# LANGUAGE OverloadedStrings #-}+-- {-# LANGUAGE NoImplicitPrelude #-}+-- import RIO+-- import Capataz+--+-- main :: IO ()+-- main = do+--   logOptions <- logOptionsHandle stdout True+--   (loggerSpec, logFunc) <- buildLogWorkerSpec logOptions "app-logger" 100 id+--   runRIO logFunc $ do+--     bracket (forkCapataz "application" (set supervisorProcessSpecListL [loggerSpec]))+--             terminateCapataz_ $ \_capataz -> do+--       logInfo "this log message is written by a dedicated supervised thread"+--       threadDelay 1000100+-- @+--+-- @since 0.2.0.0+buildLogWorkerSpec+  :: (MonadUnliftIO m, MonadIO m0)+  => LogOptions  -- ^ options for the 'LogFunc' instance+  -> WorkerName  -- ^ name of the logger worker process+  -> Int         -- ^ how many log messages can be in-flight when writer is slow?+  -> (WorkerOptions m -> WorkerOptions m) -- ^ worker process modifier+  -> m0 (ProcessSpec m, LogFunc)+buildLogWorkerSpec logOptions procName bufferSize modOptions = do+  inputQueue <- newTBQueueIO bufferSize+  let myLogFunc =+        mkLogFunc $ \lmCallStack lmLogSource lmLogLevel lmPayload -> atomically+          (writeTBQueue+            inputQueue+            LogMsg {lmCallStack , lmLogSource , lmLogLevel , lmPayload }+          )++      loggerSpec = workerSpec+        procName+        (runLoggerThread logOptions inputQueue)+        (modOptions . set workerRestartStrategyL Permanent)++  return (loggerSpec, myLogFunc)++-- | Builds a 'WorkerOptions' record that spawns a thread that logs messages+-- written with the returned 'LogFunc'. Use this function if you want to build a+-- logger thread dynamically via 'forkWorker'.+--+--+-- __IMPORTANT__ If you use the returned 'LogFunc' to log functions and the+-- 'WorkerOptions' is not used in a 'forkWorker' call, your logging won't work+-- and your application will eventually block the current thread when logging.+--+-- A minimal example:+--+-- @+-- {-# LANGUAGE OverloadedStrings #-}+-- {-# LANGUAGE NoImplicitPrelude #-}+-- import RIO+-- import Capataz+--+-- main :: IO ()+-- main = do+--   logOptions <- logOptionsHandle stdout True+--   (loggerOptions, logFunc) <- buildLogWorkerOptions logOptions "app-logger" 100 id+--   runRIO logFunc $ do+--     bracket (forkCapataz "application" id)+--             terminateCapataz_ $ \capataz -> do+--       _workerId <- forkWorker loggerOptions capataz+--       logInfo "this log message is written by a dedicated supervised thread"+--       threadDelay 1000100+-- @+--+-- @since 0.2.0.0+buildLogWorkerOptions+  :: (MonadUnliftIO m, MonadIO m0)+  => LogOptions+  -> WorkerName+  -> Int+  -> (WorkerOptions m -> WorkerOptions m)+  -> m0 (WorkerOptions m, LogFunc)+buildLogWorkerOptions logOptions procName bufferSize modOptions = do+  inputQueue <- newTBQueueIO bufferSize+  let myLogFunc =+        mkLogFunc $ \lmCallStack lmLogSource lmLogLevel lmPayload -> atomically+          (writeTBQueue+            inputQueue+            LogMsg {lmCallStack , lmLogSource , lmLogLevel , lmPayload }+          )++      loggerSpec = buildWorkerOptions+        procName+        (runLoggerThread logOptions inputQueue)+        (modOptions . set workerRestartStrategyL Permanent)++  return (loggerSpec, myLogFunc)
test/testsuite/Control/Concurrent/Capataz/SupervisorTest.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings     #-} module Control.Concurrent.Capataz.SupervisorTest where -import Protolude+import RIO  import           Control.Concurrent.Capataz (set) import qualified Control.Concurrent.Capataz as SUT@@ -17,11 +17,11 @@   "supervision trees"   [ testCase "initialize and teardown of supervision tree works as expected"     $ testCapatazStreamWithOptions-        ( & set+        (& set           SUT.supervisorProcessSpecListL           [ SUT.supervisorSpec             "tree-1"-            ( set+            (set               SUT.supervisorProcessSpecListL               [ SUT.workerSpecWithDefaults "1-A"                                            (forever $ threadDelay 10001000)@@ -31,7 +31,7 @@             )           , SUT.supervisorSpec             "tree-2"-            ( set+            (set               SUT.supervisorProcessSpecListL               [ SUT.workerSpecWithDefaults "2-A"                                            (forever $ threadDelay 10001000)@@ -85,7 +85,7 @@   , testCase "supervision sub-tree gets restarted on failure" $ do     failingAction <- mkFailingSubRoutine 2     testCapatazStreamWithOptions-      ( set SUT.supervisorIntensityL 3 . set+      (set SUT.supervisorIntensityL 3 . set         SUT.supervisorProcessSpecListL         [ SUT.supervisorSpec             "tree-1"@@ -123,11 +123,11 @@             )           , SUT.supervisorSpec             "tree-2"-            ( set+            (set               SUT.supervisorProcessSpecListL               [ SUT.workerSpec "stable-worker"                                (forever $ threadDelay 1000100)-                               identity+                               id               ]             )           ]
test/testsuite/Control/Concurrent/CapatazTest.hs view
@@ -20,13 +20,13 @@ -} module Control.Concurrent.CapatazTest (tests) where -import Protolude+import RIO +import Control.Exception (ErrorCall (..))+ import Test.Tasty       (TestTree, testGroup) import Test.Tasty.HUnit (testCase) -import Control.Concurrent.STM.TVar (modifyTVar', newTVarIO, readTVar)- import           Control.Concurrent.Capataz (set) import qualified Control.Concurrent.Capataz as SUT @@ -63,10 +63,10 @@     "capataz with processSpecList"     [ testCase "initialize and teardown of workers works as expected"       $ testCapatazStreamWithOptions-          ( set+          (set             SUT.supervisorProcessSpecListL-            [ SUT.workerSpec "A" (forever $ threadDelay 10001000) identity-            , SUT.workerSpec "B" (forever $ threadDelay 10001000) identity+            [ SUT.workerSpec "A" (forever $ threadDelay 10001000) id+            , SUT.workerSpec "B" (forever $ threadDelay 10001000) id             ]           )           [ assertWorkerStarted "A"@@ -100,11 +100,11 @@           testCapatazStreamWithOptions             (set SUT.supervisorOnIntensityReachedL signalIntensityReached)             []-            ( \capataz -> do+            (\capataz -> do               _workerId <- SUT.forkWorker-                ( SUT.buildWorkerOptions "test-worker"-                                         (throwIO RestartingWorkerError)-                                         identity+                (SUT.buildWorkerOptions "test-worker"+                                        (throwIO RestartingWorkerError)+                                        id                 )                 capataz               waitTillIntensityReached@@ -126,9 +126,9 @@               "does execute callback when worker sub-routine is completed"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (return ())                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -147,11 +147,11 @@           , testCase "does not execute callback when worker sub-routine fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions "test-worker"-                                             (throwIO RestartingWorkerError)-                                             identity+                    (SUT.buildWorkerOptions "test-worker"+                                            (throwIO RestartingWorkerError)+                                            id                     )                     capataz                   return ()@@ -163,7 +163,7 @@                 , assertEventType ProcessFailed                 ]                 [assertEventType CapatazTerminated]-                ( Just $ not . andP+                (Just $ not . andP                   [ assertEventType ProcessCallbackExecuted                   , assertCallbackType SUT.OnCompletion                   ]@@ -172,9 +172,9 @@               "does not execute callback when worker sub-routine is terminated"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 1000100)                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -189,7 +189,7 @@                 )                 [assertEventType ProcessTerminated]                 [assertEventType CapatazTerminated]-                ( Just $ not . andP+                (Just $ not . andP                   [ assertEventType ProcessCallbackExecuted                   , assertCallbackType SUT.OnCompletion                   ]@@ -197,9 +197,9 @@           , testCase "treats as worker sub-routine failed if callback fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (return ())                       ( set SUT.workerRestartStrategyL SUT.Temporary@@ -228,9 +228,9 @@           [ testCase "does execute callback when worker sub-routine fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (throwIO RestartingWorkerError)                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -250,9 +250,9 @@               "does not execute callback when worker sub-routine is completed"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (return ())                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -278,9 +278,9 @@               "does not execute callback when worker sub-routine is terminated"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 1000100)                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -303,9 +303,9 @@           , testCase "treats as worker sub-routine failed if callback fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (throwIO RestartingWorkerError)                       ( set SUT.workerRestartStrategyL SUT.Temporary@@ -337,9 +337,9 @@               "gets brutally killed when TimeoutSeconds termination policy is not met"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 10001000)                       ( set SUT.workerRestartStrategyL   SUT.Temporary@@ -372,9 +372,9 @@               "does execute callback when worker sub-routine is terminated"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 1000100)                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -398,9 +398,9 @@               "does not execute callback when worker sub-routine is completed"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (return ())                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -410,7 +410,7 @@                 )                 [assertEventType ProcessCompleted]                 []-                ( Just $ not . andP+                (Just $ not . andP                   [ assertEventType ProcessCallbackExecuted                   , assertCallbackType SUT.OnTermination                   ]@@ -418,9 +418,9 @@           , testCase "does not execute callback when worker sub-routine fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   _workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (throwIO (ErrorCall "surprise!"))                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -430,7 +430,7 @@                 )                 [assertEventType ProcessFailed]                 []-                ( Just $ not . andP+                (Just $ not . andP                   [ assertEventType ProcessCallbackExecuted                   , assertCallbackType SUT.OnTermination                   ]@@ -438,9 +438,9 @@           , testCase "treats as worker sub-routine failed if callback fails"             $ testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 10001000)                       ( set SUT.workerRestartStrategyL SUT.Temporary@@ -472,9 +472,9 @@         "with transient strategy"         [ testCase "does not restart worker on completion" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             _workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 (return ())                 (set SUT.workerRestartStrategyL SUT.Transient)@@ -487,9 +487,9 @@           (Just $ not . assertEventType ProcessRestarted)         , testCase "does not restart worker on termination" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 (forever $ threadDelay 1000100)                 (set SUT.workerRestartStrategyL SUT.Transient)@@ -502,10 +502,10 @@           (Just $ not . assertEventType ProcessRestarted)         , testCase "does restart on failure" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             subRoutineAction <- mkFailingSubRoutine 1             _workerId        <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 subRoutineAction                 (set SUT.workerRestartStrategyL SUT.Transient)@@ -522,10 +522,10 @@         , testCase "does increase restart count on multiple worker failures"           $ testCapatazStream               []-              ( \capataz -> do+              (\capataz -> do                 subRoutineAction <- mkFailingSubRoutine 2                 _workerId        <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "test-worker"                     subRoutineAction                     (set SUT.workerRestartStrategyL SUT.Transient)@@ -545,10 +545,10 @@         "with permanent strategy"         [ testCase "does restart worker on completion" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             subRoutineAction <- mkCompletingOnceSubRoutine             _workerId        <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 subRoutineAction                 (set SUT.workerRestartStrategyL SUT.Permanent)@@ -566,13 +566,13 @@             "does not increase restart count on multiple worker completions"           $ testCapatazStream               []-              ( \capataz -> do+              (\capataz -> do               -- Note the number is two (2) given the assertion list has two `ProcessRestarted` assertions                 let expectedRestartCount = 2                 subRoutineAction <- mkCompletingBeforeNRestartsSubRoutine                   expectedRestartCount                 _workerId <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "test-worker"                     subRoutineAction                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -589,9 +589,9 @@               Nothing         , testCase "does restart on worker termination" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 (forever $ threadDelay 10001000)                 (set SUT.workerRestartStrategyL SUT.Permanent)@@ -611,12 +611,12 @@                     atomically (modifyTVar' terminationCountVar (+ 1))                   waitWorkerTermination i = atomically $ do                     n <- readTVar terminationCountVar-                    when (n /= i) retry+                    when (n /= i) retrySTM               testCapatazStream                 []-                ( \capataz -> do+                (\capataz -> do                   workerId <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "test-worker"                       (forever $ threadDelay 10001000)                       ( set SUT.workerRestartStrategyL SUT.Permanent@@ -645,10 +645,10 @@                 Nothing         , testCase "does restart on worker failure" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             subRoutineAction <- mkFailingSubRoutine 1             _workerId        <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 subRoutineAction                 (set SUT.workerRestartStrategyL SUT.Permanent)@@ -665,10 +665,10 @@         , testCase "does increase restart count on multiple worker failures"           $ testCapatazStream               []-              ( \capataz -> do+              (\capataz -> do                 subRoutineAction <- mkFailingSubRoutine 2                 _workerId        <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "test-worker"                     subRoutineAction                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -688,9 +688,9 @@         "with temporary strategy"         [ testCase "does not restart on worker completion" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             _workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 (return ())                 (set SUT.workerRestartStrategyL SUT.Temporary)@@ -703,9 +703,9 @@           (Just $ not . assertEventType ProcessRestarted)         , testCase "does not restart on worker termination" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "test-worker"                 (forever $ threadDelay 1000100)                 (set SUT.workerRestartStrategyL SUT.Temporary)@@ -719,11 +719,11 @@           (Just $ not . assertEventType ProcessRestarted)         , testCase "does not restart on worker failure" $ testCapatazStream           []-          ( \capataz -> do+          (\capataz -> do             _workerId <- SUT.forkWorker-              ( SUT.buildWorkerOptions+              (SUT.buildWorkerOptions                 "failing-worker"-                (panic "worker failed!")+                (error "worker failed!")                 (set SUT.workerRestartStrategyL SUT.Temporary)               )               capataz@@ -739,9 +739,9 @@       [ testCase "terminates all supervised worker sub-routines on teardown"         $ testCapatazStream             []-            ( \capataz -> do+            (\capataz -> do               _workerA <- SUT.forkWorker-                ( SUT.buildWorkerOptions+                (SUT.buildWorkerOptions                   "A"                   (forever $ threadDelay 1000100)                   (set SUT.workerRestartStrategyL SUT.Permanent)@@ -750,7 +750,7 @@                 _workerB <- SUT.forkWorker-                ( SUT.buildWorkerOptions+                (SUT.buildWorkerOptions                   "B"                   (forever $ threadDelay 1000100)                   (set SUT.workerRestartStrategyL SUT.Permanent)@@ -773,9 +773,9 @@             $ testCapatazStreamWithOptions                 (set SUT.supervisorRestartStrategyL SUT.OneForOne)                 []-                ( \capataz -> do+                (\capataz -> do                   _workerA <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "A"                       (forever $ threadDelay 1000100)                       (set SUT.workerRestartStrategyL SUT.Temporary)@@ -785,7 +785,7 @@                   ioB      <- mkFailingSubRoutine 1                    _workerB <- SUT.forkWorker-                    ( SUT.buildWorkerOptions+                    (SUT.buildWorkerOptions                       "B"                       (forever $ ioB >> threadDelay 1000100)                       (set SUT.workerRestartStrategyL SUT.Permanent)@@ -796,7 +796,7 @@                 )                 [andP [assertEventType ProcessRestarted, assertProcessName "B"]]                 []-                ( Just $ not . andP+                (Just $ not . andP                   [assertEventType ProcessRestarted, assertProcessName "A"]                 )         ]@@ -804,20 +804,20 @@         "with all for one supervisor restart strategy with newest first order"         [ testCase "does terminate all other workers that did not fail"           $ testCapatazStreamWithOptions-              ( \supOptions ->+              (\supOptions ->                 supOptions                   & set SUT.supervisorRestartStrategyL         SUT.AllForOne                   & set SUT.supervisorProcessTerminationOrderL SUT.OldestFirst               )               []-              ( \capataz -> do+              (\capataz -> do               -- This lockVar guarantees that workerB executes before workerA                 lockVar  <- newEmptyMVar                  ioA      <- mkFailingSubRoutine 1                  _workerA <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "A"                     (forever $ readMVar lockVar >> ioA)                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -825,7 +825,7 @@                   capataz                  _workerB <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "B"                     (putMVar lockVar () >> forever (threadDelay 10))                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -845,19 +845,19 @@               Nothing         , testCase "does not restart workers that are temporary"           $ testCapatazStreamWithOptions-              ( \supOptions ->+              (\supOptions ->                 supOptions                   & set SUT.supervisorRestartStrategyL         SUT.AllForOne                   & set SUT.supervisorProcessTerminationOrderL SUT.OldestFirst               )               []-              ( \capataz -> do+              (\capataz -> do                 lockVar  <- newEmptyMVar                  ioA      <- mkFailingSubRoutine 1                  _workerA <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "A"                     (forever $ readMVar lockVar >> ioA)                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -865,7 +865,7 @@                   capataz                  _workerB <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "B"                     (putMVar lockVar () >> forever (threadDelay 10))                     (set SUT.workerRestartStrategyL SUT.Temporary)@@ -881,24 +881,24 @@               , andP [assertEventType ProcessTerminated, assertProcessName "B"]               ]               []-              ( Just $ not . andP+              (Just $ not . andP                 [assertEventType ProcessRestarted, assertProcessName "B"]               )         , testCase "restarts workers that are not temporary"           $ testCapatazStreamWithOptions-              ( \supOptions ->+              (\supOptions ->                 supOptions                   & set SUT.supervisorRestartStrategyL         SUT.AllForOne                   & set SUT.supervisorProcessTerminationOrderL SUT.NewestFirst               )               []-              ( \capataz -> do+              (\capataz -> do                 ioA      <- mkFailingSubRoutine 1                  lockVar  <- newEmptyMVar                  _workerA <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "A"                     (forever $ readMVar lockVar >> ioA)                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -906,7 +906,7 @@                   capataz                  _workerB <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "B"                     (putMVar lockVar () >> forever (threadDelay 10))                     (set SUT.workerRestartStrategyL SUT.Transient)@@ -925,20 +925,20 @@         "with all for one capataz restart strategy with oldest first order"         [ testCase "does not restart workers that are temporary"           $ testCapatazStreamWithOptions-              ( \supOptions ->+              (\supOptions ->                 supOptions                   & set SUT.supervisorRestartStrategyL         SUT.AllForOne                   & set SUT.supervisorProcessTerminationOrderL SUT.OldestFirst               )               []-              ( \capataz -> do+              (\capataz -> do                 ioA      <- mkFailingSubRoutine 1                  -- This lockVar guarantees that workerB executes before workerA                 lockVar  <- newEmptyMVar                  _workerA <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "A"                     (forever $ readMVar lockVar >> ioA)                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -946,7 +946,7 @@                   capataz                  _workerB <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "B"                     (putMVar lockVar () >> forever (threadDelay 10))                     (set SUT.workerRestartStrategyL SUT.Temporary)@@ -957,25 +957,25 @@               )               [andP [assertEventType ProcessRestarted, assertProcessName "A"]]               []-              ( Just $ not . andP+              (Just $ not . andP                 [assertEventType ProcessRestarted, assertProcessName "B"]               )         , testCase "restarts workers that are not temporary"           $ testCapatazStreamWithOptions-              ( \supOptions ->+              (\supOptions ->                 supOptions                   & set SUT.supervisorRestartStrategyL         SUT.AllForOne                   & set SUT.supervisorProcessTerminationOrderL SUT.OldestFirst               )               []-              ( \capataz -> do+              (\capataz -> do                 ioA      <- mkFailingSubRoutine 1                  -- This lockVar guarantees that workerB executes before workerA                 lockVar  <- newEmptyMVar                  _workerA <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "A"                     (forever $ readMVar lockVar >> ioA)                     (set SUT.workerRestartStrategyL SUT.Permanent)@@ -983,7 +983,7 @@                   capataz                  _workerB <- SUT.forkWorker-                  ( SUT.buildWorkerOptions+                  (SUT.buildWorkerOptions                     "B"                     (putMVar lockVar () >> forever (threadDelay 10))                     (set SUT.workerRestartStrategyL SUT.Transient)
test/testsuite/Main.hs view
@@ -5,17 +5,16 @@ {-# LANGUAGE ScopedTypeVariables   #-} module Main where -import Protolude+import RIO  import qualified Control.Concurrent.Capataz.SupervisorTest as Supervisor import qualified Control.Concurrent.CapatazTest            as Capataz import           Test.Tasty     (defaultMainWithIngredients, testGroup)-import           Test.Tasty.Ingredients.Rerun              (rerunningTests) import           Test.Tasty.Runners     (consoleTestReporter, listingTests)  main :: IO () main = defaultMainWithIngredients-  [rerunningTests [listingTests, consoleTestReporter]]+  [listingTests, consoleTestReporter]   (testGroup "capataz" [Capataz.tests, Supervisor.tests])
test/testsuite/Test/Util.hs view
@@ -4,14 +4,12 @@ {-# LANGUAGE OverloadedStrings     #-} module Test.Util where -import Protolude+import           RIO+import qualified RIO.Text as T -import Control.Concurrent.STM.TQueue (newTQueueIO, readTQueue, writeTQueue)-import Data.IORef                    (atomicModifyIORef', newIORef, readIORef, writeIORef)-import Test.Tasty.HUnit              (assertBool, assertFailure)-import Text.Show.Pretty              (ppShow)+import Test.Tasty.HUnit (assertBool, assertFailure)+import Text.Show.Pretty (ppShow) -import qualified Data.Text as T  import qualified Control.Concurrent.Capataz       as SUT import qualified Control.Concurrent.Capataz.Event as SUT@@ -22,7 +20,7 @@ -- | Utility function that gets the type name of a Record through it's Show -- output. fetchRecordName :: Show a => a -> Text-fetchRecordName = T.takeWhile (/= ' ') . show+fetchRecordName = T.takeWhile (/= ' ') . tshow  -- | Composes two predicate functions together with a boolean AND andP :: [a -> Bool] -> a -> Bool@@ -235,14 +233,15 @@ -- | Utility function to create a Worker sub-routine that fails at least a -- number of times mkFailingSubRoutine-  :: Int  -- ^ Number of times the Worker sub-routine will fail-  -> IO (IO ()) -- ^ Sub-routine used on worker creation+  :: (MonadIO m, MonadThrow m1, MonadIO m1)+  => Int  -- ^ Number of times the Worker sub-routine will fail+  -> m (m1 ()) -- ^ Sub-routine used on worker creation mkFailingSubRoutine failCount = do   countRef <- newIORef failCount   let subRoutine = do         shouldFail <- atomicModifyIORef' countRef-                                         (\count -> (pred count, count > 0))-        when shouldFail (throwIO RestartingWorkerError)+                                         (\count -> (count - 1, count > 0))+        when shouldFail (throwM RestartingWorkerError)    return subRoutine @@ -250,19 +249,19 @@ -- function works great when testing `Permanent` strategies, as you would like -- to assert restart events once (if it keeps completing it will fill up the log -- with restart events)-mkCompletingBeforeNRestartsSubRoutine :: Int -> IO (IO ())+mkCompletingBeforeNRestartsSubRoutine :: MonadIO m => Int -> m (m ()) mkCompletingBeforeNRestartsSubRoutine initCount = do   countRef <- newIORef initCount   let subRoutine = do         shouldStop <- atomicModifyIORef' countRef-                                         (\count -> (pred count, count > 0))+                                         (\count -> (count - 1, count > 0))         if shouldStop then return () else forever $ threadDelay 1000100   return subRoutine  -- | A sub-routine that will complete once. This function works great when -- testing `Permanent` strategies, as you would like to assert restart events -- once (if it keeps completing it will fill up the log with restart events)-mkCompletingOnceSubRoutine :: IO (IO ())+mkCompletingOnceSubRoutine :: MonadIO m => m (m ()) mkCompletingOnceSubRoutine = mkCompletingBeforeNRestartsSubRoutine 1  -- | Utility function to build a test environment for a Capataz execution.@@ -274,11 +273,12 @@ -- * A function to modify the default "CapatazOptions", this utility function injects --   a special @notifyEvent@ callback to execute given assertions. testCapatazStreamWithOptions-  :: (SUT.CapatazOptions -> SUT.CapatazOptions) -- ^ Function to modify default+  :: (MonadUnliftIO m)+  => (SUT.CapatazOptions (RIO LogFunc) -> SUT.CapatazOptions (RIO LogFunc)) -- ^ Function to modify default                                                 -- @CapatazOptions@   -> [SUT.CapatazEvent -> Bool] -- ^ Assertions happening before setup function                                 -- is called-  -> (SUT.Capataz -> IO ()) -- ^ Function used to test public the supervisor+  -> (SUT.Capataz (RIO LogFunc) -> RIO LogFunc ()) -- ^ Function used to test public the supervisor                             -- public API (a.k.a setup function)   -> [SUT.CapatazEvent -> Bool] -- ^ Assertions happening after the setup                                 -- function@@ -288,69 +288,75 @@                                       -- @CapatazEvents@ that happened in a                                       -- test, great when testing that an event                                       -- __did not__ happen-  -> IO ()+  -> m () testCapatazStreamWithOptions optionModFn preSetupAssertion setupFn postSetupAssertions postTeardownAssertions mAllEventsAssertion   = do      eventStream     <- newTQueueIO     accRef          <- newIORef []     pendingCountVar <- newIORef-      ( sum $ fmap+      (sum $ fmap         length         [preSetupAssertion, postSetupAssertions, postTeardownAssertions]       ) -    capataz <- SUT.forkCapataz-      rootSupervisorName-      (SUT.set SUT.onSystemEventL (trackEvent accRef eventStream) . optionModFn)+    logOptions <- logOptionsHandle stdout False+    withLogFunc logOptions $ \logFunc -> runRIO logFunc $ do+      capataz <- SUT.forkCapataz+        rootSupervisorName+        ( set+            SUT.onSystemEventL+            (\ev -> logDebug (display ev) >> trackEvent accRef eventStream ev)+        . optionModFn+        ) -    -- We check preSetup assertions are met before we execute the setup-    -- function. This serves to test initialization of capataz instance-    runAssertions "PRE-SETUP"-                  (eventStream, accRef)-                  pendingCountVar-                  preSetupAssertion-                  capataz+      -- We check preSetup assertions are met before we execute the setup+      -- function. This serves to test initialization of capataz instance+      runAssertions "PRE-SETUP"+                    (eventStream, accRef)+                    pendingCountVar+                    preSetupAssertion+                    capataz -    -- We execute the setup sub-routine, which is going to use the Capataz public-    -- API to assert events-    setupResult <- try (setupFn capataz)+      -- We execute the setup sub-routine, which is going to use the Capataz public+      -- API to assert events+      setupResult <- try (setupFn capataz) -    case setupResult of-      -- If the sub-routine fails, show exception-      Left  err -> assertFailure (show (err :: SomeException))-      Right _   -> do-        -- We now run post-setup assertions-        runAssertions "POST-SETUP"-                      (eventStream, accRef)-                      pendingCountVar-                      postSetupAssertions-                      capataz+      case setupResult of+        -- If the sub-routine fails, show exception+        Left  err -> liftIO $ assertFailure (show (err :: SomeException))+        Right _   -> do+          -- We now run post-setup assertions+          runAssertions "POST-SETUP"+                        (eventStream, accRef)+                        pendingCountVar+                        postSetupAssertions+                        capataz -        -- We now shutdown the capataz instance-        void $ SUT.teardown capataz+          -- We now shutdown the capataz instance+          SUT.terminateCapataz_ capataz -        -- We run assertions for after the capataz has been shut down-        runAssertions "POST-TEARDOWN"-                      (eventStream, accRef)-                      pendingCountVar-                      postTeardownAssertions-                      capataz+          -- We run assertions for after the capataz has been shut down+          runAssertions "POST-TEARDOWN"+                        (eventStream, accRef)+                        pendingCountVar+                        postTeardownAssertions+                        capataz -        -- Lastly, we check if there is a function that we want to execute-        -- across all events that happened in the test, this is to assert the-        -- absence of an event-        case mAllEventsAssertion of-          Nothing                 -> return ()-          Just allEventsAssertion -> do-            events <- reverse <$> readIORef accRef-            assertBool-              ( "On AFTER-TEST, expected all events to match predicate, but didn't ("-              <> show (length events)-              <> " events tried)\n"-              <> ppShow (zip ([0 ..] :: [Int]) events)-              )-              (all allEventsAssertion events)+          -- Lastly, we check if there is a function that we want to execute+          -- across all events that happened in the test, this is to assert the+          -- absence of an event+          case mAllEventsAssertion of+            Nothing                 -> return ()+            Just allEventsAssertion -> do+              events <- reverse <$> readIORef accRef+              liftIO $ assertBool+                ("On AFTER-TEST, expected all events to match predicate, but didn't ("+                <> show (length events)+                <> " events tried)\n"+                <> ppShow (zip ([0 ..] :: [Int]) events)+                )+                (all allEventsAssertion events)  where   -- Utility functions that runs the readEventLoop function with a timeout   -- of a second, this way we can guarantee assertions are met without having@@ -358,14 +364,14 @@   runAssertions stageName (eventStream, accRef) pendingCountVar assertions capataz     = do       raceResult <- race-        (threadDelay 1000100)+        (liftIO $ threadDelay 1000100)         (readEventLoop eventStream pendingCountVar assertions)       case raceResult of         Left _ -> do           events       <- reverse <$> readIORef accRef           pendingCount <- readIORef pendingCountVar-          void $ SUT.teardown capataz-          assertFailure+          SUT.terminateCapataz_ capataz+          liftIO $ assertFailure             (  "On "             <> stageName             <> " stage, expected all assertions to match, but didn't ("@@ -389,8 +395,8 @@   readEventLoop eventStream pendingCount assertions = do     writeIORef pendingCount (length assertions)     case assertions of-      []                        -> return ()-      (assertionFn:assertions1) -> do+      []                          -> return ()+      (assertionFn : assertions1) -> do         event <- atomically $ readTQueue eventStream         if assertionFn event           then readEventLoop eventStream pendingCount assertions1@@ -400,9 +406,10 @@ -- | A version of "testCapatazStreamWithOptions" that does not receive the -- function that modifies a "CapatazOptions" record. testCapatazStream-  :: [SUT.CapatazEvent -> Bool] -- ^ Assertions happening before setup function+  :: (MonadUnliftIO m)+  => [SUT.CapatazEvent -> Bool] -- ^ Assertions happening before setup function                                 -- is called-  -> (SUT.Capataz -> IO ()) -- ^ Function used to test public the supervisor+  -> (SUT.Capataz (RIO LogFunc) -> RIO LogFunc ()) -- ^ Function used to test public the supervisor                             -- public API (a.k.a setup function)   -> [SUT.CapatazEvent -> Bool] -- ^ Assertions happening after the setup                                 -- function@@ -412,6 +419,5 @@                                       -- @CapatazEvents@ that happened in a                                       -- test, great when testing that an event                                       -- __did not__ happen-  -> IO ()-testCapatazStream preSetupAssertions =-  testCapatazStreamWithOptions identity preSetupAssertions+  -> m ()+testCapatazStream = testCapatazStreamWithOptions id