// Package worker provides a concurrent goroutine pool with lifecycle management. // // # Lifecycle // // The component follows the lifecycle.Component contract: // - OnInit: logs pool configuration; no goroutines are started. // - OnStart: launches PoolSize goroutines that consume from the task queue. // - OnStop: closes the task queue, cancels the pool context, then waits up to // ShutdownTimeout for all goroutines to finish. Returns nil regardless of // whether the drain completed before the deadline. // // Register with the launcher before starting: // // pool := worker.New(logger, cfg) // launcher.Register(pool) // // # Dispatching Tasks // // Dispatch is non-blocking. It returns false immediately when the buffer is full. // A false return means the task was dropped — the caller is responsible for // retry or overflow handling. // // ok := pool.Dispatch(func(ctx context.Context) error { // return sendEmail(ctx, msg) // }) // if !ok { // // queue was full; handle backpressure // } // // # Interface Segregation // // Inject Provider into callers that only dispatch work. // Pass Component to the launcher registration site. // // # Configuration // // EINHERJAR_WORKER_POOL_SIZE — number of concurrent goroutines; default 5 // EINHERJAR_WORKER_BUFFER_SIZE — task queue capacity; default 100 // EINHERJAR_WORKER_TASK_TIMEOUT — per-task deadline (0 = no deadline); default 0s // EINHERJAR_WORKER_SHUTDOWN_TIMEOUT — OnStop drain deadline; default 30s package worker