Supervisor
The Supervisor module provides supervision trees for managing actor lifecycles. Supervisors monitor child actors and can restart them when they fail, implementing fault-tolerant patterns inspired by Erlang/OTP.
Supervision Trees
Supervisors form a hierarchy where each supervisor manages its children. When a child fails, the supervisor's restart strategy determines how to recover.
Restart Strategies
Supervisors support three restart strategies that determine what happens when a child fails:
:isolate
Only restart the failed child. Other children are unaffected.
This is the default and most common strategy.
:all
Restart all children when one fails.
Useful when children have interdependent state.
:cascade
Restart the failed child and all children started after it.
Useful for dependencies where later children depend on earlier ones.
Child Specifications
Each child is specified as a record with the following fields:
# Child specification record
{
handler: fn(msg, state) => new-state, # Message handler function
state: initial-state, # Initial state for the actor
name: "worker-1" # Optional: name for the child
}
Supervisor API
Supervisor.start
Keyword -> List ChildSpec -> Int
Starts a supervisor with the given restart strategy and child specifications.
Returns the supervisor ID.
handler = fn(-msg, state) => state + 1
children = [
{handler: handler, state: 0, name: "worker-1"},
{handler: handler, state: 0, name: "worker-2"}
]
sup = Supervisor.start :isolate children
Supervisor.stop
Int -> Unit
Stops the supervisor and all its child actors.
Supervisor.stop sup
Supervisor.children
Int -> List Int
Returns a list of all child actor IDs managed by the supervisor.
child-ids = Supervisor.children sup
println "Children: ${child-ids}"
Supervisor.child-count
Int -> Int
Returns the number of children managed by the supervisor.
Supervisor.is-running?
Int -> Bool
Returns true if the supervisor is currently running.
Error Types
type SupervisorError =
| InvalidStrategy String
| InvalidChildSpec String
| StartFailed String
| NotRunning
Complete Example
# Define a worker handler
worker-handler = fn(msg, state) =>
match msg
| :work -> state + 1
| :reset -> 0
| _ -> state
# Create child specifications
children = [
{handler: worker-handler, state: 0, name: "worker-1"},
{handler: worker-handler, state: 0, name: "worker-2"},
{handler: worker-handler, state: 0, name: "worker-3"}
]
# Start supervisor with isolate strategy
sup = Supervisor.start :isolate children
# Get child actors and send them work
workers = Supervisor.children sup
workers |> List.each (fn(w) => w <- :work)
# Check status
println "Supervisor running: ${Supervisor.is-running? sup}"
println "Child count: ${Supervisor.child-count sup}"
# Cleanup
Supervisor.stop sup