Skip to content

Add upper-limit support to WorkerPool size — Closes #132#133

Merged
conradbzura merged 3 commits intowool-labs:mainfrom
conradbzura:132-workerpool-size-upper-limit
Mar 27, 2026
Merged

Add upper-limit support to WorkerPool size — Closes #132#133
conradbzura merged 3 commits intowool-labs:mainfrom
conradbzura:132-workerpool-size-upper-limit

Conversation

@conradbzura
Copy link
Copy Markdown
Contributor

@conradbzura conradbzura commented Mar 27, 2026

Summary

Add a lease parameter to WorkerPool that caps how many additional discovered workers the pool will accept. The total pool capacity is size + lease when both are set, or just lease for durable (discovery-only) pools. Zero is allowed when size is set (caps at exactly the spawn count) but rejected for discovery-only pools. The lease count is a cap on admission, not a reservation — discovered workers may serve multiple pools simultaneously, and there is no guarantee that a leased slot will remain filled for the life of the pool. Omitting lease preserves existing behavior (unbounded).

The cap is enforced at the WorkerProxy sentinel level — the single point through which all discovered workers flow into the loadbalancer. WorkerProxy enforces lease > 0 independently since it always receives the computed total (size + lease), never the raw zero. The sentinel guards worker-updated events for never-added workers to prevent stale updates leaking through the cap. The lease value survives pickling via __reduce__ so the cap is preserved across nested routine dispatch.

Size resolution is extracted to a typed module-level _resolve_size helper to eliminate duplicated validation across match arms.

Closes #132

Proposed changes

Lease parameter and validation (pool.py)

Add lease: int | None = None to all three __init__ overloads and the implementation signature. Reject negative lease values universally; reject zero lease only for discovery-only pools where it would be nonsensical. Extract a _resolve_size(size: int) -> int module-level helper that resolves size=0 to CPU count and validates size >= 0. Compute max_workers = size + lease in each match arm after size resolution, forwarding the total to WorkerProxy in all four branches — including the durable branch which passes the raw lease since there is no spawn count to add.

Cap enforcement in the worker sentinel (proxy.py)

Add a lease: int | None parameter to WorkerProxy with its own < 1 validation and :param documentation. In the sentinel, skip "worker-added" discovery events when the loadbalancer already holds >= lease workers. Guard "worker-updated" events so updates for never-added workers (rejected by the cap) are silently dropped rather than passed to the loadbalancer. Include lease in __reduce__ so the cap survives pickling for nested routine dispatch.

Documentation (README.md, src/wool/runtime/worker/README.md)

Update both the root README and worker subpackage README to explain the lease parameter with code examples for hybrid and durable pool modes. Clarify that the lease count is a cap on admission, not a reservation.

Test cases

# Test Suite Given When Then Coverage Target
1 TestWorkerPool A size of 4 and lease of 8 WorkerPool is instantiated Creates pool successfully Lease accepted with valid size
2 TestWorkerPool A discovery service and lease of 8 with no size WorkerPool is instantiated Creates pool successfully Durable mode with lease
3 TestWorkerPool A size of 4 and lease of 0 WorkerPool is instantiated Creates pool successfully Zero lease with size accepted
4 TestWorkerPool A discovery service and lease of 0 with no size WorkerPool is instantiated Raises ValueError Zero lease discovery-only rejected
5 TestWorkerPool A negative lease WorkerPool is instantiated Raises ValueError Negative lease rejected
6 TestWorkerPool Size=2, lease=4, and discovery (hybrid mode) Pool context is entered WorkerProxy receives lease=6 (size + lease) Hybrid mode forwarding
7 TestWorkerPool Size=2 and lease=4 without discovery (ephemeral) Pool context is entered WorkerProxy receives lease=6 (size + lease) Ephemeral mode forwarding
8 TestWorkerPool Discovery only and lease=6 (durable mode) Pool context is entered WorkerProxy receives lease=6 Durable mode forwarding
9 TestWorkerPool No explicit size or discovery, lease=4 (default) Pool context is entered WorkerProxy receives lease=cpu_count+4 Default mode forwarding
10 TestWorkerPool Plain int size with no lease Pool context is entered WorkerProxy receives lease=None No lease forwards None
11 TestWorkerPool Any positive size and any non-negative lease WorkerPool is instantiated Creates pool successfully Valid combinations accepted
12 TestWorkerPool Any negative lease value WorkerPool is instantiated Raises ValueError Negative lease rejected
13 TestWorkerProxy Discovery and lease=0 WorkerProxy is instantiated Raises ValueError Zero lease rejected by proxy
14 TestWorkerProxy Discovery and lease=-1 WorkerProxy is instantiated Raises ValueError Negative lease rejected by proxy
15 TestWorkerProxy Discovery and lease=5 WorkerProxy is instantiated Creates proxy successfully Positive lease accepted by proxy
16 TestWorkerProxy lease=2 and 3 worker-added events Proxy started, discovery drains Only 2 workers accepted Sentinel cap enforcement
17 TestWorkerProxy lease=None and 3 worker-added events Proxy started, discovery drains All 3 workers accepted No cap when None
18 TestWorkerProxy lease=2 at capacity, worker-updated event Proxy started, discovery drains Update processed without blocking Updates bypass cap
19 TestWorkerProxy lease=2 at capacity, drop then add Proxy started, discovery drains New worker accepted after drop Drop frees lease slot
20 TestWorkerProxy lease=1, rejected worker then updated Proxy started, discovery drains Update for rejected worker silently dropped Guard on unknown updates
21 TestWorkerProxy WorkerProxy with lease=2 Pickle round-trip then start restored proxy Only 2 workers accepted by restored proxy Cap survives pickling

@conradbzura conradbzura marked this pull request as ready for review March 27, 2026 02:47
@conradbzura conradbzura force-pushed the 132-workerpool-size-upper-limit branch from 8f44638 to ebe1191 Compare March 27, 2026 13:01
@conradbzura conradbzura self-assigned this Mar 27, 2026
@conradbzura conradbzura changed the title Add upper-limit support to WorkerPool size — Closes #132 Add upper-limit to WorkerPool size — Closes #132 Mar 27, 2026
@conradbzura conradbzura force-pushed the 132-workerpool-size-upper-limit branch from ebe1191 to 0041100 Compare March 27, 2026 14:01
Comment thread wool/src/wool/runtime/worker/pool.py Outdated
@conradbzura conradbzura force-pushed the 132-workerpool-size-upper-limit branch 3 times, most recently from 3257020 to 9ceeb93 Compare March 27, 2026 16:24
@conradbzura conradbzura changed the title Add upper-limit to WorkerPool size — Closes #132 Add upper-limit support to WorkerPool size — Closes #132 Mar 27, 2026
@conradbzura conradbzura force-pushed the 132-workerpool-size-upper-limit branch 2 times, most recently from b0485b9 to 6a069e0 Compare March 27, 2026 20:17
Lease specifies the maximum number of additional discovered workers
the pool will accept. The total pool capacity is size + lease when
both are set, or just lease for durable (discovery-only) pools.
The lease is a cap on admission, not a reservation.

Zero is allowed when size is set (caps at exactly the spawn count)
but rejected for discovery-only pools where it would be nonsensical.
WorkerProxy enforces lease > 0 since it always receives the computed
total (size + lease), never the raw zero. Size resolution is
extracted to a typed module-level _resolve_size helper. The sentinel
guards worker-updated events for never-added workers.
Cover the lease parameter across all pool modes including default
and durable. Zero lease accepted with size, rejected for
discovery-only. WorkerProxy lease validation tested independently.
Includes drop-then-add and update-for-rejected-worker tests.
Uses _drain_discovery helper polling proxy.workers instead of
accessing private sentinel state.
Both READMEs explain the lease parameter with examples for hybrid
and durable modes. Clarify that the lease count is a cap on
admission, not a reservation — discovered workers may serve
multiple pools and slots are not guaranteed to stay filled.
@conradbzura conradbzura force-pushed the 132-workerpool-size-upper-limit branch from 6a069e0 to ae2f009 Compare March 27, 2026 21:57
@conradbzura conradbzura merged commit e9dac8e into wool-labs:main Mar 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add upper-limit to WorkerPool size

1 participant