Compare commits
2 commits
ax/review-
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
781e0ee3d6 | ||
|
|
2ad4870bd0 |
2 changed files with 29 additions and 11 deletions
33
ratelimit.go
33
ratelimit.go
|
|
@ -249,7 +249,12 @@ func (rl *RateLimiter) Load() error {
|
|||
return err
|
||||
}
|
||||
|
||||
return yaml.Unmarshal([]byte(content), rl)
|
||||
if err := yaml.Unmarshal([]byte(content), rl); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ensureMaps(rl)
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadSQLite reads quotas and state from the SQLite backend.
|
||||
|
|
@ -590,21 +595,20 @@ func (rl *RateLimiter) AllStats() map[string]ModelStats {
|
|||
// Decide returns structured allow/deny information for an estimated request.
|
||||
// It never records usage; call RecordUsage after a successful decision.
|
||||
func (rl *RateLimiter) Decide(model string, estimatedTokens int) Decision {
|
||||
if estimatedTokens < 0 {
|
||||
return Decision{
|
||||
Allowed: false,
|
||||
Code: DecisionInvalidTokens,
|
||||
Reason: "estimated tokens must be non-negative",
|
||||
Stats: rl.Stats(model),
|
||||
}
|
||||
}
|
||||
|
||||
rl.mu.Lock()
|
||||
defer rl.mu.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
decision := Decision{}
|
||||
|
||||
if estimatedTokens < 0 {
|
||||
decision.Allowed = false
|
||||
decision.Code = DecisionInvalidTokens
|
||||
decision.Reason = "estimated tokens must be non-negative"
|
||||
decision.Stats = rl.snapshotLocked(model)
|
||||
return decision
|
||||
}
|
||||
|
||||
quota, ok := rl.Quotas[model]
|
||||
if !ok {
|
||||
decision.Allowed = true
|
||||
|
|
@ -830,6 +834,15 @@ func newConfiguredRateLimiter(cfg Config) *RateLimiter {
|
|||
return rl
|
||||
}
|
||||
|
||||
func ensureMaps(rl *RateLimiter) {
|
||||
if rl.Quotas == nil {
|
||||
rl.Quotas = make(map[string]ModelQuota)
|
||||
}
|
||||
if rl.State == nil {
|
||||
rl.State = make(map[string]*UsageStats)
|
||||
}
|
||||
}
|
||||
|
||||
func applyConfig(rl *RateLimiter, cfg Config) {
|
||||
profiles := DefaultProfiles()
|
||||
providers := cfg.Providers
|
||||
|
|
|
|||
|
|
@ -363,12 +363,17 @@ func TestRatelimit_Decide_Good(t *testing.T) {
|
|||
|
||||
t.Run("negative estimate returns invalid decision", func(t *testing.T) {
|
||||
rl := newTestLimiter(t)
|
||||
model := "neg"
|
||||
rl.Quotas[model] = ModelQuota{MaxRPM: 5, MaxTPM: 50, MaxRPD: 5}
|
||||
|
||||
decision := rl.Decide("neg", -5)
|
||||
decision := rl.Decide(model, -5)
|
||||
|
||||
assert.False(t, decision.Allowed)
|
||||
assert.Equal(t, DecisionInvalidTokens, decision.Code)
|
||||
assert.Zero(t, decision.RetryAfter)
|
||||
require.Contains(t, rl.State, model)
|
||||
require.NotNil(t, rl.State[model])
|
||||
assert.Equal(t, 0, rl.State[model].DayCount)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue