Implement Erlang-style named process registry and scheduled messaging to make joerl more feature-complete for Erlang developers. This includes:
whereis/1- Look up processes by registered nameregister/2- Register a process with a nameunregister/1- Unregister a named processsend/2- Send to named process or Pidsend_after/3- Schedule a message to be sent after a delay
joerl currently only supports addressing actors by Pid. The ActorSystem maintains a DashMap registry mapping Pid to ActorEntry (joerl/src/system.rs:279). Messages are sent via ActorSystem::send() and ActorRef::send() methods which only accept Pid as the recipient.
There is no timer/scheduler subsystem, and all message sending is immediate.
Create joerl/src/registry.rs for name registration functionality.
- Use
DashMap<String, Pid>for thread-safe name-to-Pid mapping - Use
DashMap<Pid, String>for reverse lookup (Pid-to-name) - Support both local and distributed names (node-scoped)
- Automatic cleanup when actors terminate
RegisteredName- Newtype wrapper for registered names with validationRegistrationError- Specific errors for name conflicts, invalid names
register(name: String, pid: Pid) -> Result<()>- Register name (error if already registered)unregister(name: &str) -> Result<Pid>- Remove registration, return Pidwhereis(name: &str) -> Option<Pid>- Look up Pid by nameregistered() -> Vec<String>- List all registered namescleanup_pid(pid: Pid)- Internal cleanup when actor dies
Add registry field to ActorSystem (joerl/src/system.rs:278).
- Add
registry: Arc<Registry>field - Initialize registry in
new()andnew_distributed() - Expose public API methods that delegate to registry:
register(&self, name: impl Into<String>, pid: Pid) -> Result<()>unregister(&self, name: &str) -> Result<Pid>whereis(&self, name: &str) -> Option<Pid>registered(&self) -> Vec<String>
- Call
registry.cleanup_pid()incleanup_actor()(system.rs:717)
- Create
Destinationenum:Pid(Pid) | Name(String) - Add
send_to(&self, dest: Destination, msg: Message) -> Result<()> - Modify existing
send()to work through this abstraction - Update ActorRef to support named sends
Create joerl/src/scheduler.rs for delayed message scheduling.
- Use tokio's time utilities (
tokio::time::sleep,Instant) - Store scheduled messages as heap-ordered by delivery time
- Each scheduled message spawns a tokio task that sleeps then sends
ScheduledMessage- Contains destination, message, delivery timeSchedulerHandle- Cancellable reference to scheduled messageTimerRef- Erlang-style timer reference for cancellation
send_after(dest: Destination, msg: Message, duration: Duration) -> TimerRefcancel_timer(timer_ref: TimerRef) -> Result<bool>- Returns true if cancelledsend_interval(dest: Destination, msg: Message, interval: Duration) -> TimerRef(bonus)
- Each
send_afterspawns a detached tokio task - Task sleeps for duration, then calls
ActorSystem::send_to() - Store cancellation tokens in
DashMap<TimerRef, CancellationToken> - Use
tokio_util::sync::CancellationTokenfor cancellation
Add timer-related message types to joerl/src/message.rs if needed for timer expiry notifications.
Add convenience methods to ActorContext (joerl/src/actor.rs:100):
send_after(&self, dest: Destination, msg: Message, duration: Duration) -> Result<TimerRef>whereis(&self, name: &str) -> Option<Pid>- Allow actors to easily schedule messages from within their context
Add new error variants to ActorError (joerl/src/error.rs):
NameAlreadyRegistered(String)NameNotRegistered(String)InvalidName(String)TimerNotFound(u64)
Add metrics for registry and scheduler (if telemetry feature enabled):
joerl_registry_size- Current number of registered namesjoerl_registry_lookups_total- Registry lookup counterjoerl_registry_conflicts_total- Registration conflict counterjoerl_scheduled_messages_total- Messages scheduledjoerl_scheduled_messages_cancelled_total- Timers cancelled
Add section on named processes and scheduled messaging with examples.
examples/named_processes.rs- Registry demonstrationexamples/scheduled_messaging.rs- Timer demonstration- Update existing examples to show optional use of names
Add to README.md (line 301):
register(Name, Pid)->system.register(name, pid)unregister(Name)->system.unregister(name)whereis(Name)->system.whereis(name)registered()->system.registered()erlang:send_after(Time, Pid, Msg)->system.send_after(dest, msg, duration)erlang:cancel_timer(TRef)->system.cancel_timer(tref)
Document the new registry and scheduler modules in the Architecture section.
- Test basic register/unregister/whereis
- Test name conflicts (should error)
- Test automatic cleanup on actor death
- Test concurrent registration attempts
- Test distributed name registration (node-scoped)
- Property tests for registry consistency
- Test basic send_after delivery
- Test timer cancellation before delivery
- Test message ordering with multiple scheduled messages
- Test scheduled message to named destination
- Test scheduled messages survive actor restarts
- Test timer behaviour when destination dies
- Named processes with supervision trees
- Scheduled messages in distributed systems
- Registry with monitors and links
Update joerl/src/lib.rs:
- Add
pub mod registry; - Add
pub mod scheduler; - Re-export key types:
RegisteredName,Destination,TimerRef - Update documentation with new capabilities