Safe Haskell | None |
---|---|
Language | Haskell2010 |
A process broker spawns and monitors child processes.
The child processes are mapped to symbolic identifier values: Child-IDs.
This is the barest, most minimal version of a broker. Children can be started, but not restarted.
Children can efficiently be looked-up by an id-value, and when the broker is shutdown, all children will be shutdown these are actually all the features of this broker implementation.
Also, this minimalist broker only knows how to spawn a single kind of child process.
When a broker spawns a new child process, it expects the
child process to return a ProcessId
. The broker will
monitor
the child process.
This is in stark contrast to how Erlang/OTP handles things;
In the OTP Supervisor, the child has to link to the parent.
This allows the child spec to be more flexible in that no
pid
has to be passed from the child start function to the
broker process, and also, a child may break free from
the broker by unlinking.
Now while this seems nice at first, this might actually cause surprising results, since it is usually expected that stopping a broker also stops the children, or that a child exit shows up in the logging originating from the former broker.
The approach here is to allow any child to link to the broker to realize when the broker was violently killed, and otherwise give the child no chance to unlink itself from its broker.
This module is far simpler than the Erlang/OTP counter part,
of a simple_one_for_one
supervisor.
The future of this broker might not be a-lot more than it currently is. The ability to restart processes might be implemented outside of this broker module.
One way to do that is to implement the restart logic in a separate module, since the child-id can be reused when a child exits.
Since: 0.23.0
Synopsis
- startLink :: forall p e. (HasCallStack, IoLogging (Processes e), TangibleBroker p, Server (Broker p) (Processes e)) => StartArgument (Broker p) -> Eff (Processes e) (Endpoint (Broker p))
- statefulChild :: forall p e. (HasCallStack, IoLogging e, TangibleBroker (Stateful p), Server (Broker (Stateful p)) e) => Timeout -> (ChildId p -> StartArgument p) -> StartArgument (Broker (Stateful p))
- stopBroker :: (HasCallStack, HasProcesses e q, Member Logs e, Lifted IO e, TangibleBroker p) => Endpoint (Broker p) -> Eff e ()
- isBrokerAlive :: forall p q0 e. (HasCallStack, Member Logs e, Typeable p, HasProcesses e q0) => Endpoint (Broker p) -> Eff e Bool
- monitorBroker :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> Eff e MonitorReference
- getDiagnosticInfo :: forall p e q0. (HasCallStack, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> Eff e Text
- spawnChild :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Either (SpawnErr p) (Endpoint (ServerPdu p)))
- spawnOrLookup :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Endpoint (ServerPdu p))
- lookupChild :: forall p e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Maybe (Endpoint (ServerPdu p)))
- callById :: forall destination protocol result e q0. (HasCallStack, Member Logs e, HasProcesses e q0, Lifted IO e, Lifted IO q0, TangibleBroker protocol, TangiblePdu destination (Synchronous result), TangiblePdu protocol (Synchronous result), Embeds (ServerPdu destination) protocol, Ord (ChildId destination), Tangible (ChildId destination), Typeable (ServerPdu destination), Tangible result, NFData (Pdu protocol (Synchronous result)), NFData (Pdu (ServerPdu destination) (Synchronous result)), Show (Pdu (ServerPdu destination) (Synchronous result))) => Endpoint (Broker destination) -> ChildId destination -> Pdu protocol (Synchronous result) -> Timeout -> Eff e result
- castById :: forall destination protocol e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker protocol, TangiblePdu destination Asynchronous, TangiblePdu protocol Asynchronous) => Endpoint (Broker destination) -> ChildId destination -> Pdu protocol Asynchronous -> Eff e ()
- stopChild :: forall p e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> ChildId p -> Eff e Bool
- data ChildNotFound child where
- ChildNotFound :: ChildId child -> Endpoint (Broker child) -> ChildNotFound child
- data Broker (p :: Type)
- data family Pdu protocol (reply :: Synchronicity)
- type family ChildId p
- data family StartArgument a
- brokerConfigChildStopTimeout :: StartArgument (Broker p) -> Timeout
- data SpawnErr p = AlreadyStarted (ChildId p) (Endpoint (ServerPdu p))
- data ChildEvent p where
- OnChildSpawned :: Endpoint (Broker p) -> ChildId p -> Endpoint (ServerPdu p) -> ChildEvent p
- OnChildDown :: Endpoint (Broker p) -> ChildId p -> Endpoint (ServerPdu p) -> Interrupt NoRecovery -> ChildEvent p
- OnBrokerShuttingDown :: Endpoint (Broker p) -> ChildEvent p
Documentation
startLink :: forall p e. (HasCallStack, IoLogging (Processes e), TangibleBroker p, Server (Broker p) (Processes e)) => StartArgument (Broker p) -> Eff (Processes e) (Endpoint (Broker p)) Source #
Start and link a new broker process with the given SpawnFun
unction.
To spawn new child processes use spawnChild
.
Since: 0.23.0
statefulChild :: forall p e. (HasCallStack, IoLogging e, TangibleBroker (Stateful p), Server (Broker (Stateful p)) e) => Timeout -> (ChildId p -> StartArgument p) -> StartArgument (Broker (Stateful p)) Source #
A smart constructor for MkBrokerConfig
that makes it easy to start a Server
instance.
The user needs to instantiate
.ChildId
p
Since: 0.30.0
stopBroker :: (HasCallStack, HasProcesses e q, Member Logs e, Lifted IO e, TangibleBroker p) => Endpoint (Broker p) -> Eff e () Source #
Stop the broker and shutdown all processes.
Block until the broker has finished.
Since: 0.23.0
isBrokerAlive :: forall p q0 e. (HasCallStack, Member Logs e, Typeable p, HasProcesses e q0) => Endpoint (Broker p) -> Eff e Bool Source #
Check if a broker process is still alive.
Since: 0.23.0
monitorBroker :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> Eff e MonitorReference Source #
Monitor a broker process.
Since: 0.23.0
getDiagnosticInfo :: forall p e q0. (HasCallStack, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> Eff e Text Source #
Return a Text
describing the current state of the broker.
Since: 0.23.0
spawnChild :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Either (SpawnErr p) (Endpoint (ServerPdu p))) Source #
Start and monitor a new child process using the SpawnFun
passed
to startLink
.
Since: 0.23.0
spawnOrLookup :: forall p q0 e. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Endpoint (ServerPdu p)) Source #
Start and monitor a new child process using the SpawnFun
passed
to startLink
.
Call spawnChild
and unpack the Either
result,
ignoring the AlreadyStarted
error.
Since: 0.29.2
lookupChild :: forall p e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p, Typeable (ServerPdu p)) => Endpoint (Broker p) -> ChildId p -> Eff e (Maybe (Endpoint (ServerPdu p))) Source #
Lookup the given child-id and return the output value of the SpawnFun
if the client process exists.
Since: 0.23.0
callById :: forall destination protocol result e q0. (HasCallStack, Member Logs e, HasProcesses e q0, Lifted IO e, Lifted IO q0, TangibleBroker protocol, TangiblePdu destination (Synchronous result), TangiblePdu protocol (Synchronous result), Embeds (ServerPdu destination) protocol, Ord (ChildId destination), Tangible (ChildId destination), Typeable (ServerPdu destination), Tangible result, NFData (Pdu protocol (Synchronous result)), NFData (Pdu (ServerPdu destination) (Synchronous result)), Show (Pdu (ServerPdu destination) (Synchronous result))) => Endpoint (Broker destination) -> ChildId destination -> Pdu protocol (Synchronous result) -> Timeout -> Eff e result Source #
castById :: forall destination protocol e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker protocol, TangiblePdu destination Asynchronous, TangiblePdu protocol Asynchronous) => Endpoint (Broker destination) -> ChildId destination -> Pdu protocol Asynchronous -> Eff e () Source #
stopChild :: forall p e q0. (HasCallStack, Member Logs e, HasProcesses e q0, TangibleBroker p) => Endpoint (Broker p) -> ChildId p -> Eff e Bool Source #
data ChildNotFound child where Source #
ChildNotFound :: ChildId child -> Endpoint (Broker child) -> ChildNotFound child |
Instances
(Show (ChildId child), Typeable child) => Show (ChildNotFound child) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker showsPrec :: Int -> ChildNotFound child -> ShowS # show :: ChildNotFound child -> String # showList :: [ChildNotFound child] -> ShowS # | |
NFData (ChildId c) => NFData (ChildNotFound c) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker rnf :: ChildNotFound c -> () # |
data Broker (p :: Type) Source #
The index type of Server
supervisors.
A
manages the life cycle of the processes, running the Broker
p
methods of that specific type.Server
p
The broker maps an identifier value of type
to an ChildId
p
.Endpoint
p
Since: 0.24.0
Instances
data family Pdu protocol (reply :: Synchronicity) Source #
The protocol data unit type for the given protocol.
Instances
data family StartArgument a Source #
The value that defines what is required to initiate a Server
loop.
Instances
data StartArgument (ObservationQueue event) Source # | |
data StartArgument (Broker p) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker | |
data StartArgument (Watchdog child) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Watchdog |
Runtime-Errors occurring when spawning child-processes.
Since: 0.23.0
AlreadyStarted (ChildId p) (Endpoint (ServerPdu p)) |
Instances
Eq (ChildId p) => Eq (SpawnErr p) Source # | |
Ord (ChildId p) => Ord (SpawnErr p) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker | |
(Typeable (ServerPdu p), Show (ChildId p)) => Show (SpawnErr p) Source # | |
Generic (SpawnErr p) Source # | |
NFData (ChildId p) => NFData (SpawnErr p) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker | |
type Rep (SpawnErr p) Source # | |
Defined in Control.Eff.Concurrent.Protocol.Broker type Rep (SpawnErr p) = D1 (MetaData "SpawnErr" "Control.Eff.Concurrent.Protocol.Broker" "extensible-effects-concurrent-0.32.0-GimAdtHOovq4dulPgeQPe9" False) (C1 (MetaCons "AlreadyStarted" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (ChildId p)) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Endpoint (ServerPdu p))))) |
data ChildEvent p where Source #
The event type to indicate that a child was started or stopped.
The need for this type originated for the watchdog functionality introduced
in 0.30.0.
The watch dog shall restart a crashed child, and in order to do so, it
must somehow monitor the child.
Since no order is specified in which processes get the ProcessDown
events,
a watchdog cannot monitor a child and restart it immediately, because it might
have received the process down event before the broker.
So instead the watchdog can simply use the broker events, and monitor only the
broker process.
Since: 0.30.0
OnChildSpawned :: Endpoint (Broker p) -> ChildId p -> Endpoint (ServerPdu p) -> ChildEvent p | |
OnChildDown :: Endpoint (Broker p) -> ChildId p -> Endpoint (ServerPdu p) -> Interrupt NoRecovery -> ChildEvent p | |
OnBrokerShuttingDown | |
|