lambdaclass / lambdaclass/spawned
Unify MailboxItem<A> across tasks and threads modes
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 59
- Forks
- 5
- PR merge metrics
- No merged PRs in 30d
Description
Why
Two recent PRs introduced ad-hoc paths for non-Handler<M> mailbox traffic, leaving the codebase with two mechanisms solving the same problem:
-
#166 (links + trap_exit) added
ExitEnvelope— aBox<dyn Envelope<A>>that bypassesHandler<M>and callsactor.exit_received()directly. Avoids forcing every linkable actor toimpl Handler<Exit>, but unusual. -
#168 (perf fix for #157) added
MailboxItem<A>enum in threads mode only, withMessage(envelope)andShutdownvariants for the poison-pill wakeup pattern. Works, but introduces divergence between tasks and threads.
Both are essentially "how to deliver something through the mailbox that isn't a user protocol message" — two ad-hoc patterns when one would do.
What to build
Promote MailboxItem<A> to a formal internal type used uniformly in both modes:
pub(crate) enum MailboxItem<A: Actor> {
Message(Box<dyn Envelope<A> + Send>),
Exit(Exit),
Shutdown,
}
The run_actor loop becomes structurally identical across modes — same match on the enum, differing only in await vs sync call.
Key design choices
- Cancellation auto-wake via
on_cancelcallback — register at spawn time so anycancellation_token.cancel()enqueuesMailboxItem::Shutdownautomatically. Removes the hidden coupling wherectx.stop()and theChildHandlecancel closure had to manually enqueue Shutdown. MailboxItem<A>stayspub(crate)— internal abstraction, not a user-facing API.Downis NOT moved into this mechanism — stays asHandler<Down>because monitoring is opt-in.- User-facing API fully preserved:
ctx.link/unlink/trap_exit,Actor::exit_received,start_linked,ctx.monitor/demonitor,Handler<Down>,ctx.stop(),ChildHandle::stop()all unchanged.
What changes internally
ExitEnveloperemoved (replaced byMailboxItem::Exit(Exit)variant)SendExitFnbody changes (signature unchanged) — builds the enum variant instead of a boxed envelope- Mailbox channel type in both modes:
mpsc::Sender<MailboxItem<A>> ctx.stop()in threads mode simplifies back to one line (self.cancellation_token.cancel()) — theon_cancelcallback does the enqueueEnvelope<A>trait no longer needs to support system-message use cases —MessageEnvelope<M>is the only impl
Order of operations
Must land after #166 and #168 to avoid three-way rebase hell. Both are prerequisites:
- #166 introduces
Actor::exit_received(the dispatch point that stays) - #168 introduces the
MailboxItemenum shape (gets promoted)
Design artifacts
Detailed proposal, design, specs, and task breakdown are checked into openspec/changes/unified-mailbox-items/:
proposal.md— whydesign.md— 6 design decisions + risks + open questionsspecs/mailbox-items/spec.md— 7 requirements with testable scenariostasks.md— ~40 implementation tasks
The OpenSpec change can be applied with /opsx:apply unified-mailbox-items once prerequisites are merged.
Acceptance criteria
- All existing tests pass with no modification (proves user-facing behavior is preserved)
grep -r ExitEnvelope concurrency/returns zero matches- Threads-mode shutdown latency is single-digit milliseconds (no polling regression)
- Direct
cancellation_token.cancel()(without callingctx.stop()) wakes the actor — proves theon_cancelpath - At least one regression test covering FIFO ordering of
ExitandMessageitems
Credit
Surfaced during review of #168 — thanks @lakshya-sky for the perf fix that made the unification opportunity visible.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
First read openspec/changes/unified-mailbox-items/proposal.md, design.md, specs/mailbox-items/spec.md, and tasks.md, then confirm prerequisites #166 and #168 are merged. Trace run_actor, SendExitFn, and the mailbox channel definitions in concurrency/ before checking both execution modes. Done means existing tests pass, direct cancellation wakes actors, FIFO ordering is covered, threads shutdown remains single-digit milliseconds, and grep finds no ExitEnvelope matches.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- distributed-systems
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100