Module
pooka/otp
src/pooka/otp.pookaTyped letters, fresh identities, and the small handles that survive a restart. A Subject carries checked send and receive capabilities. Its native mailbox representation never pretends to be a Pooka class. Names and keys are fresh: their text is a label, not a lookup token. Create one at startup and pass it to the children that share it. Repeating name("clock") makes another name.
let inbox: otp.Subject(String) = otp.new_subject()
otp.send(inbox, "hello")
assert otp.receive(inbox, 100) == Some("hello")
API reference
- classSubject
- classTimer
- className
- classKey
- classCallError
- classTimeout
- classDown
- enumLogLevel
- functionme
- functionspawn
- functionspawn_link
- functionis_alive
- functionkill
- functionsleep
- functionsleep_forever
- functionactor_pid
- functionmake_subject
- functionmake_timer
- functionnew_subject
- functionowner
- functionsend
- functionschedule
- functionsend_after
- functioncancel
- functionremaining
- functionreceive
- functionreceive_forever
- functioncall
- functiondescribe
- functionname
- functionname_id
- functionkey
- functionput
- functionget
- functionerase
- functionset_log_level
- classProcessDown
- classMonitor
- functionmonitor
- functionwait_down
- functiondemonitor
- functionlink
- functionunlink
- functionmailbox_size
- functiontrap_exits
- functionreceive_exit
class Subject(m)
Send and receive capabilities over one message type. Only private children construct these values. Receiving is restricted to the owning process.
class Timer
A cancellable scheduled delivery. A successful cancellation prevents delivery; False means it already fired or was cancelled. A delivered message is not removed.
class Name(m)
A fresh server identity. Labels do not establish equality or a message type.
class Key(v)
A fresh typed storage capability. Equal labels never share a storage slot.
class CallError
Why a request received no answer.
class Timeout is CallError
class Down(reason: String) is CallError
reason: String
String
fn(String) -> pooka/otp.Downenum LogLevel
Node-wide Erlang logger verbosity.
LogLevel.Debug
LogLevel.Info
LogLevel.Notice
LogLevel.Warning
LogLevel.Error
LogLevel.Critical
me() -> Pid
fn() -> PidThe current BEAM process.
spawn(work: fn() -> Nil) -> Pid
fn(fn() -> Nil) -> PidStart an unlinked process; completion and failure remain local to it.
spawn_link(work: fn() -> Nil) -> Pid
fn(fn() -> Nil) -> PidStart a linked process. An abnormal exit propagates over the link.
is_alive(pid: Pid) -> Bool
fn(Pid) -> BoolAsk whether a local process is running now; it may stop immediately afterwards.
kill(pid: Pid) -> Nil
fn(Pid) -> NilStop a process without giving it an opportunity to run cleanup.
sleep(milliseconds: Int) -> Nil
fn(Int) -> NilSleep for a nonnegative millisecond duration; negative values clamp to zero.
sleep_forever() -> Nil
fn() -> NilWait indefinitely, usually after starting a long-running application.
actor_pid(handle: a) -> Option(Pid)
fn(a) -> Option(Pid)Inspect the checked native actor handle. Other values return None.
make_subject(
post: fn(m) -> Nil,
read: fn(Int) -> Option(m),
wait: fn() -> m,
owner: fn() -> Option(Pid),
later: fn(Int, m) -> Timer,
request: fn(Pid, m) -> Nil
) -> Subject(m)
fn(fn(a) -> Nil, fn(Int) -> Option(a), fn() -> a, fn() -> Option(Pid), fn(Int, a) -> pooka/otp.Timer, fn(Pid, a) -> Nil) -> pooka/otp.Subject(a)Typed capability constructor for Erlang adapters. The functions themselves preserve m; no arbitrary term is reinterpreted as a Subject.
make_timer(cancel: fn() -> Bool, remaining: fn() -> Option(Int)) -> Timer
fn(fn() -> Bool, fn() -> Option(Int)) -> pooka/otp.TimerTyped timer constructor used by adapters, normally reached through schedule.
new_subject() -> Subject(m)
fn() -> pooka/otp.Subject(a)Create a mailbox owned by this process, with a fresh selective-receive tag.
owner(subject: Subject(m)) -> Option(Pid)
fn(pooka/otp.Subject(a)) -> Option(Pid)The live process receiving these messages, if any.
send(subject: Subject(m), message: m) -> Nil
fn(pooka/otp.Subject(a), a) -> NilSend without waiting. Sending to a stopped process deliberately loses the message.
schedule(subject: Subject(m), milliseconds: Int, message: m) -> Timer
fn(pooka/otp.Subject(a), Int, a) -> pooka/otp.TimerSchedule delivery and return its cancellation handle. Negative delays clamp to zero.
let timer = otp.schedule(inbox, 1000, "wake up")
assert otp.cancel(timer)
send_after(subject: Subject(m), milliseconds: Int, message: m) -> Nil
fn(pooka/otp.Subject(a), Int, a) -> NilSchedule a delivery when the caller does not need a cancellation handle.
cancel(timer: Timer) -> Bool
fn(pooka/otp.Timer) -> BoolCancel a pending timer. Already delivered messages remain in the mailbox.
remaining(timer: Timer) -> Option(Int)
fn(pooka/otp.Timer) -> Option(Int)Remaining milliseconds, or None after cancellation or delivery.
receive(subject: Subject(m), timeout: Int) -> Option(m)
fn(pooka/otp.Subject(a), Int) -> Option(a)Receive from a mailbox owned by this process. Other ownership is a runtime error; casts and reply-only subjects cannot be read through this function.
receive_forever(subject: Subject(m)) -> m
fn(pooka/otp.Subject(a)) -> aReceive without a deadline, subject to the same ownership rule.
call(subject: Subject(m), make: fn(Subject(r)) -> m, timeout: Int) -> Result(
r,
CallError
)
fn(pooka/otp.Subject(a), fn(pooka/otp.Subject(b)) -> a, Int) -> Result(b, pooka/otp.CallError)Make a request with a revocable reply alias. Late responses after a timeout are dropped before reaching the mailbox. The request builder runs in the caller.
describe(problem: CallError) -> String
fn(pooka/otp.CallError) -> StringDescribe a failed request without discarding the original typed error.
name(label: String) -> Name(m)
fn(String) -> pooka/otp.Name(a)Allocate a fresh named-server identity. Keep this value across restarts.
let left: otp.Name(Int) = otp.name("clock")
let right: otp.Name(String) = otp.name("clock")
// Equal labels, separate addresses and separate message types.
name_id(name: Name(m)) -> String
fn(pooka/otp.Name(a)) -> StringAn adapter's binary registry token. name always creates a fresh identity; there is deliberately no inverse function that claims an arbitrary type.
key(label: String) -> Key(v)
fn(String) -> pooka/otp.Key(a)Allocate a fresh persistent storage capability. The label never participates in lookup.
put(key: Key(v), value: v) -> Nil
fn(pooka/otp.Key(a), a) -> NilStore under this capability, replacing its previous value.
get(key: Key(v)) -> Option(v)
fn(pooka/otp.Key(a)) -> Option(a)Read the value belonging to this exact capability.
erase(key: Key(v)) -> Nil
fn(pooka/otp.Key(a)) -> NilRelease persistent storage. Existing holders can still store a new value.
set_log_level(level: LogLevel) -> Nil
fn(pooka/otp.LogLevel) -> NilChange logging for the whole node, not just the calling process.
class ProcessDown(pid: Pid, reason: String)
A process exit, keeping both the identity and its printable reason.
pid: Pid
Pidreason: String
String
fn(Pid, String) -> pooka/otp.ProcessDownclass Monitor
An owner-bound monitor. It observes exits without linking process lifetimes.
monitor(pid: Pid) -> Monitor
fn(Pid) -> pooka/otp.MonitorWatch a process without receiving its exit as a failure of this process.
let watch = otp.monitor(worker)
otp.kill(worker)
let assert Some(stopped) = otp.wait_down(watch, 1000)
assert stopped.pid == worker
wait_down(watch: Monitor, timeout: Int) -> Option(ProcessDown)
fn(pooka/otp.Monitor, Int) -> Option(pooka/otp.ProcessDown)Wait for this monitor's DOWN notification; other mailbox messages stay put.
demonitor(watch: Monitor) -> Bool
fn(pooka/otp.Monitor) -> BoolRemove a monitor and flush its own pending notification, not unrelated ones.
link(pid: Pid) -> Nil
fn(Pid) -> NilLink local process lifetimes. Abnormal exits propagate unless trapped.
unlink(pid: Pid) -> Nil
fn(Pid) -> NilRemove a link without stopping either process.
mailbox_size() -> Int
fn() -> IntCount this process's queued messages. Useful for observing backpressure.
trap_exits(enabled: Bool) -> Bool
fn(Bool) -> BoolChange exit trapping, returning its previous value. Linking is a lifecycle decision: callers that enable trapping must handle the resulting exit messages.
receive_exit(timeout: Int) -> Option(ProcessDown)
fn(Int) -> Option(pooka/otp.ProcessDown)Read one trapped link exit. Monitor DOWN notifications are separate.