1354679e33
Phase 2 Tasks T2.1-T2.4 of the startup_speedup_20260606 track.
NEW: src/io_pool.py
make_io_pool() factory: 4-worker ThreadPoolExecutor with
thread_name_prefix='controller-io'. The sanctioned way for any
background work. Replaces ad-hoc threading.Thread() calls per
the 'no new threads' rule.
NEW: src/warmup.py
WarmupManager: manages a list of modules to import on the shared
pool. Public API:
.submit(modules) - start warmup (call once)
.status() - {pending, completed, failed}
.is_done() - bool
.wait(timeout) - block until done
.on_complete(callback) - register completion callback
.reset() - clear state
Thread-safe (lock-guarded). 10 tests cover all paths.
NEW: tests/test_io_pool.py (4 tests):
- ThreadPoolExecutor returned
- 4 workers
- Threads named 'controller-io-*'
- Jobs run in parallel (barrier test)
NEW: tests/test_warmup.py (10 tests):
- One job per module submitted
- Initial pending list correct
- Failed imports tracked
- Done event set after all complete
- wait() blocks until done
- on_complete callback fires (and immediately if already done)
- Modules actually end up in sys.modules
- reset() clears state
- Jobs run concurrently (not serially)
All 14 tests pass. AppController integration is the next commit.
21 lines
612 B
Python
21 lines
612 B
Python
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
|
|
IO_POOL_MAX_WORKERS: int = 4
|
|
IO_POOL_THREAD_NAME_PREFIX: str = "controller-io"
|
|
|
|
|
|
def make_io_pool(max_workers: int = IO_POOL_MAX_WORKERS) -> ThreadPoolExecutor:
|
|
"""Create the shared AppController I/O pool.
|
|
|
|
4 worker threads, named "controller-io-N". Used for warmup, log pruning,
|
|
disk-bound subsystem init, and any other background work that should
|
|
not spin up its own thread.
|
|
|
|
Caller is responsible for shutdown (e.g. controller.shutdown()).
|
|
"""
|
|
return ThreadPoolExecutor(
|
|
max_workers=max_workers,
|
|
thread_name_prefix=IO_POOL_THREAD_NAME_PREFIX,
|
|
)
|