Module

pooka/otp/supervisor

src/pooka/otp/supervisor.pooka

Supervisors: 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.

Pooka
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

src/pooka/otp/supervisor.pooka:33
class Supervisor

A running supervisor.

enum

Strategy

src/pooka/otp/supervisor.pooka:43
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.
variant

OneForOne

src/pooka/otp/supervisor.pooka:44
Strategy.OneForOne
variant

OneForAll

src/pooka/otp/supervisor.pooka:45
Strategy.OneForAll
variant

RestForOne

src/pooka/otp/supervisor.pooka:46
Strategy.RestForOne
enum

Restart

src/pooka/otp/supervisor.pooka:54
enum Restart

When to start a child again.

  • Permanent: always.
  • Transient: only after a crash, not after a normal stop.
  • Temporary: never.
variant

Permanent

src/pooka/otp/supervisor.pooka:55
Restart.Permanent
variant

Transient

src/pooka/otp/supervisor.pooka:56
Restart.Transient
variant

Temporary

src/pooka/otp/supervisor.pooka:57
Restart.Temporary
class

Child

src/pooka/otp/supervisor.pooka:62
class Child

One child of a supervisor. Make one with worker, server, actor_child or nested.

field

id

src/pooka/otp/supervisor.pooka:63
let id: String
INFERREDString
field

start

src/pooka/otp/supervisor.pooka:64
let start: fn() -> Result(Pid, String)
INFERREDfn() -> Result(Pid, String)
field

restart

src/pooka/otp/supervisor.pooka:65
let restart: Restart
field

is_supervisor

src/pooka/otp/supervisor.pooka:66
let is_supervisor: Bool
INFERREDBool
field

shutdown

src/pooka/otp/supervisor.pooka:67
let shutdown: Int
INFERREDInt
constructor

new

src/pooka/otp/supervisor.pooka:69
new(
    id: String,
    start: fn() -> Result(Pid, String),
    restart: Restart,
    is_supervisor: Bool,
    shutdown: Int
  )
INFERREDfn(String, fn() -> Result(Pid, String), pooka/otp/supervisor.Restart, Bool, Int) -> pooka/otp/supervisor.Child
method

with_restart

src/pooka/otp/supervisor.pooka:84
with_restart(restart: Restart) -> Child

Choose when this child is started again. The default is Permanent.

method

with_shutdown

src/pooka/otp/supervisor.pooka:90
with_shutdown(milliseconds: Int) -> Child
INFERREDfn(Int) -> pooka/otp/supervisor.Child

Set a worker shutdown deadline. Zero requests an immediate kill; -1 waits indefinitely. Other negative values are rejected by OTP at startup.

function

worker

src/pooka/otp/supervisor.pooka:97
worker(id: String, start: fn() -> Result(Pid, String)) -> Child
INFERREDfn(String, fn() -> Result(Pid, String)) -> pooka/otp/supervisor.Child

A child started by any function that starts a process linked to the caller, and returns it.

function

server

src/pooka/otp/supervisor.pooka:106
server(id: String, spec: servers.Spec(s, m)) -> Child

A 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.

function

actor_child

src/pooka/otp/supervisor.pooka:139
actor_child(id: String, key: Key(a), start: fn() -> a) -> Child
INFERREDfn(String, pooka/otp.Key(a), fn() -> a) -> pooka/otp/supervisor.Child

A 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.

Pooka
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() })
}
function

nested

src/pooka/otp/supervisor.pooka:149
nested(id: String, spec: Spec) -> Child

Another supervisor as a child, to build a tree.

class

Spec

src/pooka/otp/supervisor.pooka:163
class Spec

Everything needed to start a supervisor. Make one with spec.

field

strategy

src/pooka/otp/supervisor.pooka:164
let strategy: Strategy
field

children

src/pooka/otp/supervisor.pooka:165
let children: List(Child)
field

intensity

src/pooka/otp/supervisor.pooka:166
let intensity: Int
INFERREDInt
field

period

src/pooka/otp/supervisor.pooka:167
let period: Int
INFERREDInt
field

name

src/pooka/otp/supervisor.pooka:168
let name: Option(String)
INFERREDOption(String)
constructor

new

src/pooka/otp/supervisor.pooka:170
new(
    strategy: Strategy,
    children: List(Child),
    intensity: Int,
    period: Int,
    name: Option(String)
  )
method

with_intensity

src/pooka/otp/supervisor.pooka:187
with_intensity(restarts: Int, seconds: Int) -> Spec
INFERREDfn(Int, Int) -> pooka/otp/supervisor.Spec

How 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.

method

with_name

src/pooka/otp/supervisor.pooka:192
with_name(name: String) -> Spec
INFERREDfn(String) -> pooka/otp/supervisor.Spec

Register the supervisor under a name.

function

spec

src/pooka/otp/supervisor.pooka:198
spec(strategy: Strategy, children: List(Child)) -> Spec

Describe a supervisor by its strategy and its children, in start order.

function

start

src/pooka/otp/supervisor.pooka:248
start(spec: Spec) -> Result(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.

function

add

src/pooka/otp/supervisor.pooka:260
add(supervisor: Supervisor, child: Child) -> Result(Pid, String)

Start one more child, after the supervisor is running.

function

children

src/pooka/otp/supervisor.pooka:265
children(supervisor: Supervisor) -> List(#(String, Option(Pid)))
INFERREDfn(pooka/otp/supervisor.Supervisor) -> List(#(String, Option(Pid)))

Each child's id, with its process if it is running, in start order.

function

pid

src/pooka/otp/supervisor.pooka:270
pid(supervisor: Supervisor) -> Pid

The supervisor's own process.

function

shutdown

src/pooka/otp/supervisor.pooka:278
shutdown(supervisor: Supervisor) -> Nil

Stop the supervisor and all its children, and wait until they have stopped.

class

Counts

src/pooka/otp/supervisor.pooka:283
class Counts(specs: Int, active: Int, supervisors: Int, workers: Int)

Child specification counts and current live-process counts are distinct.

field

specs

src/pooka/otp/supervisor.pooka:283
specs: Int
INFERREDInt
field

active

src/pooka/otp/supervisor.pooka:283
active: Int
INFERREDInt
field

supervisors

src/pooka/otp/supervisor.pooka:283
supervisors: Int
INFERREDInt
field

workers

src/pooka/otp/supervisor.pooka:283
workers: Int
INFERREDInt
constructor

new

src/pooka/otp/supervisor.pooka:283
INFERREDfn(Int, Int, Int, Int) -> pooka/otp/supervisor.Counts
function

terminate

src/pooka/otp/supervisor.pooka:286
terminate(supervisor: Supervisor, id: String) -> Result(Nil, String)
INFERREDfn(pooka/otp/supervisor.Supervisor, String) -> Result(Nil, String)

Stop a child but retain its specification, allowing an explicit restart.

function

restart_child

src/pooka/otp/supervisor.pooka:291
restart_child(supervisor: Supervisor, id: String) -> Result(Pid, String)
INFERREDfn(pooka/otp/supervisor.Supervisor, String) -> Result(Pid, String)

Restart a stopped child. Restarting an already-running child returns Error.

function

delete

src/pooka/otp/supervisor.pooka:296
delete(supervisor: Supervisor, id: String) -> Result(Nil, String)
INFERREDfn(pooka/otp/supervisor.Supervisor, String) -> Result(Nil, String)

Delete a stopped child's specification. Running children must be stopped first.

function

counts

src/pooka/otp/supervisor.pooka:301
counts(supervisor: Supervisor) -> Counts

Inspect how many specifications and live children the supervisor owns.