Phase 4 — process management
Goal: the everyday management surface that makes a process system usable — a named registry (look processes up by name, not pid), timers (send_after), and a graceful, system-wide shutdown. No new scenario graduates here; it rounds out the single-node API.
Why this matters
Real systems don't pass raw pids around forever — they want stable names, delayed work, and a clean way to stop. These are the small ergonomics that turn the actor core into something you can build on.
What we built (TDD throughout)
- Named registry — a sharded
DashMap(name → pid), so registration and lookup are concurrent and lock-free in the common case:register(name, pid) -> bool(fails if the name is taken),whereis(name) -> Option<Pid>,unregister(name) -> bool,send_named(name, msg) -> bool— resolve and deliver in one step.- Names are reaped automatically when their process exits (the
ProcessGuardderegisters), so a dead name never resolves to a stale pid.
- Timers —
send_after(pid, delay, msg) -> TimerRef— delivers a message afterdelay, on Tokio's hierarchical timer wheel, so thousands of pending timers cost almost nothing.TimerRef::cancel()stops a not-yet-fired timer. - Graceful
shutdown() -> usize— kills every live process and returns the count, so a node can stop cleanly.
How a developer uses it
runtime.register("logger", logger_pid);
runtime.send_named("logger", b"hello".to_vec()); // by name, no pid needed
let t = runtime.send_after(pid, Duration::from_secs(5), b"tick".to_vec());
t.cancel(); // ... or let it fire
let stopped = runtime.shutdown(); // clean teardownDesign notes
- Registry is sharded, like the process table — naming never becomes a global lock, matching the rest of the runtime's concurrency story.
- Timers ride Tokio's wheel, not a task-per-timer — pending timers are nearly free, so timeouts scale with the process count.
- Self-cleaning names — deregistration is part of the same Drop path that reaps the table entry, so there is no stale-name window to manage by hand.
Concepts introduced
No new headline concept — this is the management surface over the process model and the mailbox. See the host ABI reference for the full call list.
Play with it
cargo test -p rusm-otp registry # registry behaviour
cargo test -p rusm-otp timer # send_after / cancel timing (bounded)Verification
cargo test -p rusm-otp green (register/whereis/unregister, name reaped on exit, send_named, timer fires within tolerance, cancel, shutdown count); coverage ≥98%.
Next
Phase 5: connectivity — TCP listen/connect, one process per connection.