func (wp *workerPool) spawnWorker(initialWork *contextualItem) bool {
	if !incrementIfSmallerThan(&wp.workers, int32(wp.MaxWorkers)) {
		return false
	}
	registerWorkerStarted(wp.Name)
	wp.wg.Add(1)
	wp.StartTask(&component.TaskConfig{
		Context: wp.Context,
		ID:      wp.Name,
		Func:    wp.workerBody(initialWork),
		Restart: component.TaskRestartNever,
		Backoff: component.DefaultTaskBackoffConfig,
	})
	return true
}
spawnWorker spawns a worker task, if a worker slot is available.
package workerpool
import (
	"context"
	"sync"
	"sync/atomic"
	"time"
	"go.thethings.network/lorawan-stack/v3/pkg/component"
	"go.thethings.network/lorawan-stack/v3/pkg/errors"
)
const (
	defaultWorkerIdleTimeout = 1 * time.Second
	defaultQueueSize = 32
	defaultMinWorkers = 4
	defaultMaxWorkers = 1024
)
type Component interface {
	StartTask(*component.TaskConfig)
	FromRequestContext(context.Context) context.Context
}
type Handler func(ctx context.Context, item interface{})
type Config struct {
	Component
	context.Context                  
	Name              string         
	Handler           Handler        
	MinWorkers        int            
	MaxWorkers        int            
	QueueSize         int            
	WorkerIdleTimeout time.Duration  
}
type WorkerPool interface {
	Publish(ctx context.Context, item interface{}) error
	Wait()
}
type contextualItem struct {
	ctx  context.Context
	item interface{}
}
type workerPool struct {
	Config
	mainQueue chan *contextualItem  
	fastQueue chan *contextualItem  
	workers int32
	wg      sync.WaitGroup
}
func (wp *workerPool) handle(it *contextualItem) {
	registerWorkerBusy(wp.Name)
	defer registerWorkerIdle(wp.Name)
	defer registerWorkProcessed(it.ctx, wp.Name)
	defer registerWorkLatency(wp.Name, time.Now())
	wp.Handler(it.ctx, it.item)
}
func (wp *workerPool) workerBody(initialWork *contextualItem) func(context.Context) error {
	worker := func(ctx context.Context) error {
		var timeout bool
		defer func() {
			if timeout {
				return
			}
			atomic.AddInt32(&wp.workers, -1)
			select {
			case <-ctx.Done():
			case <-wp.Done():
			default:
				wp.spawnWorker(nil)
			}
		}()
		defer wp.wg.Done()
		defer registerWorkerStopped(wp.Name)
		registerWorkerIdle(wp.Name)
		defer registerWorkerBusy(wp.Name)
		if initialWork != nil {
			wp.handle(initialWork)
		}
		for {
			select {
			case <-wp.Done():
				return wp.Err()
			case <-ctx.Done():
				return ctx.Err()
			case <-time.After(wp.WorkerIdleTimeout):
				if decrementIfGreaterThan(&wp.workers, int32(wp.MinWorkers)) {
					timeout = true
					return nil
				}
			case item := <-wp.fastQueue:
				wp.handle(item)
			case item := <-wp.mainQueue:
				registerWorkDequeued(wp.Name)
				wp.handle(item)
			}
		}
	}
	return worker
}