smallestMailboxStrategy
此内容尚不支持你的语言。
smallestMailboxStrategy():
RoutingStrategy
Defined in: src/Router.ts:124
Smallest mailbox: one routee per message, the one with the shortest queue.
Balances by backlog instead of by message count, which is the thing round-robin cannot do — one expensive message no longer parks the next 1-in-N arrivals behind it, because a routee that is still working stops being the shallowest and drops out of the running until it catches up. The cost is a read of every routee’s depth per message, so the pool size is now a per-message factor; round-robin remains the cheaper default for workloads whose per-message cost is roughly uniform.
Ties rotate. An idle pool has every depth at 0, so a plain
“first minimum wins” scan would pin every message to routee-1 whenever
the pool drains between arrivals. Starting the scan at
messageIndex % routees.length and keeping the comparison strict (<)
makes an all-equal pool behave exactly like round-robin.
The strategy has no notion of “full” and deliberately does not grow one — refusing to route would invent back-pressure the caller never configured. On the unbounded default (#1148) that costs nothing: there is no “does not fit”, so depth stays a truthful reading of backlog however far behind the pool falls, and the routee that is genuinely least loaded keeps winning.
A pool of bounded routees does eventually saturate, and then the same
tie-break answers it: once every mailbox sits at its capacity the depths
are equal again, so the rotation takes over and the overflow spreads
evenly rather than piling onto one routee. What happens to a message that
does not fit is the mailbox’s own overflow policy (drop-head /
drop-new / reject), not the router’s call to make.
A terminated routee is skipped outright, whatever its depth reads as —
see routableDepthOf for why that is not the same case as a depth
nobody can read. If every routee is terminated the scan falls back to
the rotation and routes into a dead cell anyway: the message is lost either
way, and losing it as a DeadLetter is at least observable, where returning
nothing would drop it without a trace.
The scan stops at the first empty mailbox, which is what keeps the O(N)
worst case off the healthy path: a pool that is keeping up with its load
hits a zero on the first routee it looks at, so the common case is one read
regardless of pool size. Only a pool that is genuinely behind pays for the
full sweep — and that is the pool the strategy exists for.
