Module
pooka/otp/supervisor
src/pooka/otp/supervisor.pookaSupervisors: processes whose only job is to keep other processes running.
A supervisor starts its children in order, watches them, and starts again any that crash, following a strategy. Children can be servers, native Pooka actors, other supervisors, or anything with a start function.
import pooka/otp/supervisor.{Strategy}
main() {
let children = [
supervisor.server("clock", clock()),
supervisor.server("archive", archive())
]
let assert Ok(tree) = supervisor.start(
supervisor.spec(Strategy.OneForOne, children)
)
}
Underneath is a real OTP supervisor, so the tree shows up in observer
like any other.
API reference
class Supervisor
A running supervisor.
enum Strategy
What to do when a child crashes.
OneForOne: start that child again, and leave the others alone.OneForAll: stop all the children, and start them all again.RestForOne: start again the child and every child started after it. Use it when later children depend on earlier ones.
Strategy.OneForOne
Strategy.OneForAll
Strategy.RestForOne
enum Restart
When to start a child again.
Permanent: always.Transient: only after a crash, not after a normal stop.Temporary: never.
Restart.Permanent
Restart.Transient
Restart.Temporary
class Child
One child of a supervisor. Make one with worker, server, actor_child
or nested.
let id: String
Stringlet start: fn() -> Result(Pid, String)
fn() -> Result(Pid, String)let restart: Restart
pooka/otp/supervisor.Restartlet is_supervisor: Bool
Boollet shutdown: Int
Intnew(
id: String,
start: fn() -> Result(Pid, String),
restart: Restart,
is_supervisor: Bool,
shutdown: Int
)
fn(String, fn() -> Result(Pid, String), pooka/otp/supervisor.Restart, Bool, Int) -> pooka/otp/supervisor.Childwith_restart(restart: Restart) -> Child
fn(pooka/otp/supervisor.Restart) -> pooka/otp/supervisor.ChildChoose when this child is started again. The default is Permanent.
with_shutdown(milliseconds: Int) -> Child
fn(Int) -> pooka/otp/supervisor.ChildSet a worker shutdown deadline. Zero requests an immediate kill; -1 waits indefinitely. Other negative values are rejected by OTP at startup.
worker(id: String, start: fn() -> Result(Pid, String)) -> Child
fn(String, fn() -> Result(Pid, String)) -> pooka/otp/supervisor.ChildA child started by any function that starts a process linked to the caller, and returns it.
server(id: String, spec: servers.Spec(s, m)) -> Child
fn(String, pooka/otp/server.Spec(a, b)) -> pooka/otp/supervisor.ChildA server as a child. The supervisor starts it with server.start, so it
is linked to the supervisor.
Give the spec a name with with_name if other processes need to reach the
server, so they keep reaching it after a restart.
actor_child(id: String, key: Key(a), start: fn() -> a) -> Child
fn(String, pooka/otp.Key(a), fn() -> a) -> pooka/otp/supervisor.ChildA native Pooka actor as a child.
start must return an actor, made with its constructor. The supervisor
links to it, and stores the newest one under key, so the rest of the
program can find it with otp.get after a restart. A restarted actor
starts with fresh state.
import pooka/otp.{Key}
import pooka/otp/supervisor
actor Kettle {
var cups: Int = 0
}
kettle() -> Key(Kettle) {
otp.key("kettle")
}
main() {
let child = supervisor.actor_child("kettle", kettle(), fn() { Kettle() })
}
nested(id: String, spec: Spec) -> Child
fn(String, pooka/otp/supervisor.Spec) -> pooka/otp/supervisor.ChildAnother supervisor as a child, to build a tree.
class Spec
Everything needed to start a supervisor. Make one with spec.
let strategy: Strategy
pooka/otp/supervisor.Strategylet children: List(Child)
List(pooka/otp/supervisor.Child)let intensity: Int
Intlet period: Int
Intlet name: Option(String)
Option(String)new(
strategy: Strategy,
children: List(Child),
intensity: Int,
period: Int,
name: Option(String)
)
fn(pooka/otp/supervisor.Strategy, List(pooka/otp/supervisor.Child), Int, Int, Option(String)) -> pooka/otp/supervisor.Specwith_intensity(restarts: Int, seconds: Int) -> Spec
fn(Int, Int) -> pooka/otp/supervisor.SpecHow many restarts are allowed in how many seconds. One more, and the supervisor gives up: it stops its children and then itself, and its own supervisor decides what to do. The default is 3 restarts in 5 seconds.
with_name(name: String) -> Spec
fn(String) -> pooka/otp/supervisor.SpecRegister the supervisor under a name.
spec(strategy: Strategy, children: List(Child)) -> Spec
fn(pooka/otp/supervisor.Strategy, List(pooka/otp/supervisor.Child)) -> pooka/otp/supervisor.SpecDescribe a supervisor by its strategy and its children, in start order.
start(spec: Spec) -> Result(Supervisor, String)
fn(pooka/otp/supervisor.Spec) -> Result(pooka/otp/supervisor.Supervisor, String)Start a supervisor and all its children, linked to this process. If a child fails to start, the children already started are stopped, and the error names the child.
add(supervisor: Supervisor, child: Child) -> Result(Pid, String)
fn(pooka/otp/supervisor.Supervisor, pooka/otp/supervisor.Child) -> Result(Pid, String)Start one more child, after the supervisor is running.
children(supervisor: Supervisor) -> List(#(String, Option(Pid)))
fn(pooka/otp/supervisor.Supervisor) -> List(#(String, Option(Pid)))Each child's id, with its process if it is running, in start order.
pid(supervisor: Supervisor) -> Pid
fn(pooka/otp/supervisor.Supervisor) -> PidThe supervisor's own process.
shutdown(supervisor: Supervisor) -> Nil
fn(pooka/otp/supervisor.Supervisor) -> NilStop the supervisor and all its children, and wait until they have stopped.
class Counts(specs: Int, active: Int, supervisors: Int, workers: Int)
Child specification counts and current live-process counts are distinct.
specs: Int
Intactive: Int
Intsupervisors: Int
Intworkers: Int
Int
fn(Int, Int, Int, Int) -> pooka/otp/supervisor.Countsterminate(supervisor: Supervisor, id: String) -> Result(Nil, String)
fn(pooka/otp/supervisor.Supervisor, String) -> Result(Nil, String)Stop a child but retain its specification, allowing an explicit restart.
restart_child(supervisor: Supervisor, id: String) -> Result(Pid, String)
fn(pooka/otp/supervisor.Supervisor, String) -> Result(Pid, String)Restart a stopped child. Restarting an already-running child returns Error.
delete(supervisor: Supervisor, id: String) -> Result(Nil, String)
fn(pooka/otp/supervisor.Supervisor, String) -> Result(Nil, String)Delete a stopped child's specification. Running children must be stopped first.
counts(supervisor: Supervisor) -> Counts
fn(pooka/otp/supervisor.Supervisor) -> pooka/otp/supervisor.CountsInspect how many specifications and live children the supervisor owns.