Pular para o conteúdo
Português (BR)

Mailbox

Este conteúdo não está disponível em sua língua ainda.

Defined in: src/internal/Mailbox.ts:232

Per-actor message queue. System messages (create, terminate, failure, …) are kept on a separate priority queue and drained before any user message.

Both queues are RingBuffers rather than plain arrays, which is invisible from the outside and load-bearing underneath: every removal used to be an Array.prototype.shift(), and that reindexes the whole backlog. Since #1148 made the unbounded mailbox the default again there is no capacity capping how deep a backlog gets, so an actor that falls behind its producers was paying a memmove of its entire queue for every message it delivered (#408).

The fields stay private, so a subclass sees only the methods — which is why swapping the backing store is not a breaking change even though Mailbox is public and explicitly subclassable since #661 / #1002. The seams a subclass touches are protected removeOldest and removeNewest, and their signatures are unchanged.

T = unknown

new Mailbox<T>(): Mailbox<T>

Mailbox<T>

get size(): number

Defined in: src/internal/Mailbox.ts:406

Number of pending user messages.

number


get suspended(): boolean

Defined in: src/internal/Mailbox.ts:237

boolean

dequeueSystem(): Envelope<unknown> | undefined

Defined in: src/internal/Mailbox.ts:395

Envelope<unknown> | undefined


dequeueUser(): Envelope<T> | undefined

Defined in: src/internal/Mailbox.ts:300

Envelope<T> | undefined


drainSystem(): Envelope<unknown>[]

Defined in: src/internal/Mailbox.ts:424

Envelope<unknown>[]


drainUser(): Envelope<T>[]

Defined in: src/internal/Mailbox.ts:420

Drain all user messages; returns them so the caller can forward to dead letters.

Materialises a fresh array rather than handing out the backing store — a ring is not a dense array, so there is nothing to hand out. The allocation is real but it is on the termination path, where the caller (ActorCell) only iterates the result once.

Envelope<T>[]


enqueue(env): void

Defined in: src/internal/Mailbox.ts:239

Envelope<T>

void


enqueueSignal(env): void

Defined in: src/internal/Mailbox.ts:266

Queue a framework lifecycle notification — see Envelope.undroppable — at the tail of the user lane, exempt from whatever bound this mailbox enforces.

Override this whenever you override enqueue to shed load. The default here delegates, which is right for a queue that never discards anything and wrong for one that does: a subclass that drops on a full queue would drop this too, and the framework has no second copy to send. Delegating rather than pushing straight onto the base queue is deliberate — a subclass may keep its messages somewhere else entirely (PriorityMailbox keeps a priority-ordered array), and an envelope smuggled into a store that subclass never reads is worse than one it dropped: invisible to its dequeueUser, its size and its drainUser, so not even a dead letter comes out of it.

The envelope still arrives at the tail, which is what keeps the documented death-watch ordering intact: every tell already queued is handled first, then the notification. It is not a priority lane and must not become one — the system queue is where the framework puts messages that overtake user traffic, and a Terminated deliberately is not one of those.

Envelope<T>

void


enqueueSystem(env): void

Defined in: src/internal/Mailbox.ts:296

Envelope<unknown>

void


hasMessages(): boolean

Defined in: src/internal/Mailbox.ts:399

boolean


hasSystemMessages(): boolean

Defined in: src/internal/Mailbox.ts:403

boolean


hasUserMessages(): boolean

Defined in: src/internal/Mailbox.ts:402

boolean


prependUser(envs): void

Defined in: src/internal/Mailbox.ts:292

Put envelopes at the FRONT of the user queue, preserving their order.

One bulk move, not a spread: unstashAll replays up to DEFAULT_STASH_CAPACITY envelopes in a single call, and unshift(...envs) would both reindex the backlog once per envelope and push the whole batch onto the call stack as arguments.

Override this whenever you override enqueue to shed load, for the same reason enqueueSignal says so and the opposite conclusion: a signal is exempt from a bound, a replay is not. Leaving the default in place is what made a bounded mailbox unbounded on the stash path — a batch the size of the stash arrived past the capacity check, the overflow policy and the drop accounting, so the ceiling an operator tuned against measured heap was not one (#772). BoundedMailbox and PriorityMailbox both override it, by different routes: the former sheds at the tail to make room at the head, the latter re-enters enqueue so priorities are recomputed.

The base is right to be unconditional here — it never discards anything, so there is nothing to consult.

Envelope<T>[]

void


resume(): void

Defined in: src/internal/Mailbox.ts:409

void


suspend(): void

Defined in: src/internal/Mailbox.ts:408

void