c8c414e8fb
Pool.Shutdown() closed the job queue channel, but jobs can still be pushed while workers are draining: the feed scheduler ticker goroutine is never cancelled, and the UI and API refresh handlers push from detached goroutines that outlive the HTTP server shutdown. Any of them sending on the closed queue panicked the process mid-shutdown. Keep the queue channel open and instead close a dedicated shutdown channel, guarded by sync.Once. Push now selects between delivering a job and the shutdown signal, discarding jobs once shutdown begins, and workers select between the queue and the shutdown signal, so they still finish their current job before Shutdown returns.