mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 18:03:43 +00:00
feat(multiplayer): add regional allocation budget
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package allocator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrAllocationBudgetExceeded is deliberately generic: callers should not
|
||||
// learn quota internals, and the allocator can safely retry the leased match
|
||||
// after the current window expires.
|
||||
var ErrAllocationBudgetExceeded = fmt.Errorf("allocation budget exceeded")
|
||||
|
||||
// FixedWindowBudget is a process-local denial-of-wallet guard. It limits the
|
||||
// number of provider allocation attempts per region in a time window. The
|
||||
// production deployment must use the same policy behind a shared durable
|
||||
// counter for a global quota; this type prevents one allocator replica from
|
||||
// spending without bound and is useful in tests and single-replica setups.
|
||||
type FixedWindowBudget struct {
|
||||
mu sync.Mutex
|
||||
limit int
|
||||
window time.Duration
|
||||
windowStart time.Time
|
||||
counts map[string]int
|
||||
}
|
||||
|
||||
func NewFixedWindowBudget(limit int, window time.Duration) (*FixedWindowBudget, error) {
|
||||
if limit < 1 || window <= 0 {
|
||||
return nil, fmt.Errorf("invalid allocation budget")
|
||||
}
|
||||
return &FixedWindowBudget{limit: limit, window: window, counts: make(map[string]int)}, nil
|
||||
}
|
||||
|
||||
func (b *FixedWindowBudget) Allow(region string, now time.Time) error {
|
||||
if b == nil || (region != "EU" && region != "NA") || now.IsZero() {
|
||||
return fmt.Errorf("invalid allocation budget request")
|
||||
}
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.windowStart.IsZero() || !now.Before(b.windowStart.Add(b.window)) {
|
||||
b.windowStart = now
|
||||
b.counts = make(map[string]int)
|
||||
}
|
||||
if b.counts[region] >= b.limit {
|
||||
return ErrAllocationBudgetExceeded
|
||||
}
|
||||
b.counts[region]++
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user