When workers hit max_jobs_per_worker or max_worker_lifetime, all reader
Fibers exit but the delayed-job and metrics timers kept the EventLoop
alive indefinitely. The worker process never exited, so the master
never respawned replacements — stalling the queue.
Added hasReachedLimits() check to both timer callbacks so they cancel
themselves when job/lifetime limits are reached, allowing the EventLoop
to drain and the process to exit cleanly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>