package jobs import ( "context" "sync" "time" ) const slotWaitInterval = 500 * time.Millisecond type slotLimiter struct { mutex sync.Mutex active int } func (limiter *slotLimiter) acquire(ctx context.Context, limit func() int) bool { ticker := time.NewTicker(slotWaitInterval) defer ticker.Stop() for { if limiter.tryAcquire(limit()) { return true } select { case <-ctx.Done(): return false case <-ticker.C: } } } func (limiter *slotLimiter) tryAcquire(limit int) bool { limiter.mutex.Lock() defer limiter.mutex.Unlock() if limiter.active >= limit { return false } limiter.active++ return true } func (limiter *slotLimiter) release() { limiter.mutex.Lock() defer limiter.mutex.Unlock() limiter.active-- }