Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

61 lines
1.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package processing
import (
"sync"
"time"
"github.com/google/uuid"
)
// StartLimiter lightly rate-limits processing job starts per company.
// In-process only — not shared across API replicas (effective RPM ≈ N × replicas).
// RATE_LIMIT_REPLICAS does not divide this limiter; multi-replica hard caps need edge/WAF.
// Counts StartJob/RetryJob API calls once each — not per auto-split sibling job,
// and not per product in a bulk StartJob payload (capped by MaxStartProducts).
type StartLimiter struct {
mu sync.Mutex
window time.Duration
max int
events map[uuid.UUID][]time.Time
}
// NewStartLimiter allows maxStarts per window (e.g. 20/min).
func NewStartLimiter(maxStarts int, window time.Duration) *StartLimiter {
if maxStarts <= 0 {
maxStarts = 20
}
if window <= 0 {
window = time.Minute
}
return &StartLimiter{
window: window,
max: maxStarts,
events: make(map[uuid.UUID][]time.Time),
}
}
// Allow reports whether a new job start is permitted for companyID.
func (l *StartLimiter) Allow(companyID uuid.UUID) bool {
if l == nil {
return true
}
now := time.Now()
l.mu.Lock()
defer l.mu.Unlock()
cut := now.Add(-l.window)
ev := l.events[companyID]
kept := ev[:0]
for _, t := range ev {
if t.After(cut) {
kept = append(kept, t)
}
}
if len(kept) >= l.max {
l.events[companyID] = kept
return false
}
kept = append(kept, now)
l.events[companyID] = kept
return true
}