Resource pools · no I/O
A pool that
answers, not acts
moonpool decides which connection to lend, when to open another, which to retire, and when to refuse — and leaves the opening, the closing and the waiting to you. Time and randomness are arguments, so a run through an hour of traffic is a test you can read.
moon add moonbitstack/moonpool
One call, six answers
What take can say
It never blocks and never opens anything. Each answer is an instruction to the caller.
Ready an idle one
Use it, then give it back.
The most recently returned one comes out first: a warm connection is likelier to still be good, and handing out the newest lets the oldest age out.
Stale too old to use
Close it, then take again.
An idle one past keep or life is handed over rather than skipped, so nothing is lost if the eviction timer has not run.
Make there is room
Open one, then call made — or unmade if that fails.
The room is already reserved, so a slow connect does not let the pool overfill while it is in flight.
Wait all in use
Queue the caller.
The pool has no queue of its own: waiting needs a runtime, and this package has none. Whether a caller waits, fails fast, or tries elsewhere is a policy above it.
Later not yet
Try again after that span.
Making is held back by a token bucket that spaces connections out, or by backoff after a make that failed.
Shed refuse
Fail now.
The breaker has seen enough failures from the backend, or the shedder has seen the process go hot with calls still in flight.
The four knobs
Limits
Every pool carries four numbers, and the preset is the one most services end up at.
| field | preset | what it decides |
|---|---|---|
| size | 10 | How many resources may be live at once — idle, lent, and being made. |
| idle | 10 | How many may sit idle. Equal to size, so a pool that grew under load keeps what it made. |
| keep | 30 min | How long an idle resource may sit before it is retired. |
| life | forever | How long a resource may live at all, however busy it has been. |
Zero means no limit for the two ages. Limits::new takes any of them by name;
{ ..limits, size: 32 } changes one and keeps the rest.
In front of the backend
The ward
Four parts, every one optional. A pool with an empty ward behaves exactly as a pool without one.
breaker
Refuses new connections at the rate a failing backend deserves. unmade tells it a make failed; made tells it one worked.
bucket
Spaces makes out. A reconnection storm arrives as a queue instead of a spike.
backoff
After a failed make, holds every make back for a delay that grows with each failure in a row.
shedder
Stops lending while the process is hot and has more calls in flight than it has shown it can finish.
Where to go