mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
Adds a monotonic per-slot generation counter to createWorkerPool's
state. Each successful worker replacement (replaceWorker) bumps the
slot's counter exactly once — atomically with the workers[slotIndex]
swap, so observers (getStats) see the new (worker, generation) pair
consistently. Handler closures in the dispatch loop capture the
slot's generation at attach time and short-circuit when they fire
on a stale generation.
In the current implementation, cleanup() synchronously removes
listeners on a Worker instance the moment a death is observed, so
no listener naturally fires on a stale generation — the guard is a
defensive layer protecting against any future refactor that loosens
cleanup() ordering or re-attaches handlers across the swap. The
load-bearing observable is the slotGenerations[] array exposed via
WorkerPoolStats so operators (and tests) can confirm a slot was
actually replaced and not just the same worker recycled.
Implementation:
- const slotGenerations: number[] = new Array(size).fill(0) in
createWorkerPool's per-pool state, alongside respawnCount and
consecutiveFailuresPerSlot.
- replaceWorker: slotGenerations[workerIndex]++ AFTER the
workers[workerIndex] = replacement swap (only on the success
branch — drop-slot paths leave the counter unchanged).
- runWorker dispatch loop: const slotGen = slotGenerations[workerIndex]
captured before handler attachment; every handler (handler /
errorHandler / exitHandler / messageErrorHandler) starts with
`if (slotGenerations[workerIndex] !== slotGen) return`.
- WorkerPoolStats gains `readonly slotGenerations: readonly number[]`.
- getStats() returns slotGenerations.slice() so callers can't mutate
pool state by writing to the returned array.
Two existing toEqual snapshots in worker-pool-resilience.test.ts
extended with the new slotGenerations field (both expect all-zeros —
neither test scenario triggers a respawn).
New test file (worker-pool-slot-generation.test.ts, 4 tests):
1. Fresh pool: every slot at generation 0.
2. Successful crash + respawn: generation bumps to 1 exactly once.
3. Crash that drops the slot (maxRespawnsPerSlot:0): generation
stays at 0 because no successful respawn happened. The dispatch
rejection on breaker trip is the expected outcome here; the
load-bearing assertion is the post-rejection stats.
4. Multi-slot independence: one slot crashing bumps only that
slot's generation, not the other. Order-independent via sort()
because the round-robin assignment isn't pinned by contract.
All assertions exact .toEqual / .toBe per DoD §2.7.
|
||
|---|---|---|
| .. | ||
| fixtures | ||
| helpers | ||
| integration | ||
| unit | ||
| utils | ||