quota: z.ai credit-bucket back-pressure + resource gate + usage accounting (Redmine 490+491)
The loop now consults quota and host state before every dispatch and
DEFERS gated work with a logged reason instead of letting turns die at
the provider (the 2026-08-28 19:00 quota-wall failure mode, replayed as
a test). Adds internal/quota: 5h/weekly credit buckets (provider poll
when z.ai ships an endpoint - fake-server tested - else locally
estimated from the documented credit formula), TZ-aware peak window
(default 01:00-05:00 America/Chicago weekdays, matching the documented
z.ai peak Mon-Fri 14:00-18:00 Singapore), block/defer thresholds, a
read-only load/mem/disk/IO-PSI monitor, an optional redis shared-state
hop (stdlib RESP2 mini-client) so all instances of an account
coordinate, per-class token+credit accounting in loop.jsonl, and
`harness quota status|probe|gate`. Config: [quota] + [resources]
sections; README runbook covers the redis container and deploy-time
cgroup enforcement.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package quota
|
||||
|
||||
import (
|
||||
_ "time/tzdata" // embedded zone database: TZ-aware windows work in scratch containers
|
||||
|
||||
"time"
|
||||
|
||||
"ukrrs.com/mopac/harness/internal/config"
|
||||
)
|
||||
|
||||
// Schedule is the TZ-aware peak window. z.ai peak hours are documented as
|
||||
// Monday-Friday 14:00-18:00 Singapore (UTC+8), which is 01:00-05:00
|
||||
// America/Chicago in winter (CST) / 00:00-04:00 during US DST — the default
|
||||
// matches Charles's "0100 to 0500 CST" and is configurable to the minute.
|
||||
// The window may wrap midnight (start > end): then it covers evenings of
|
||||
// the start day plus early mornings of the following day.
|
||||
type Schedule struct {
|
||||
Start, End time.Duration // minutes-since-midnight in Loc
|
||||
Loc *time.Location
|
||||
WeekdaysOnly bool
|
||||
}
|
||||
|
||||
// NewSchedule parses the window out of the [quota] config fields.
|
||||
func NewSchedule(peakStart, peakEnd, tzName string, weekdaysOnly bool) (Schedule, error) {
|
||||
start, err := config.ParseHHMM(peakStart)
|
||||
if err != nil {
|
||||
return Schedule{}, err
|
||||
}
|
||||
end, err := config.ParseHHMM(peakEnd)
|
||||
if err != nil {
|
||||
return Schedule{}, err
|
||||
}
|
||||
loc, err := time.LoadLocation(tzName)
|
||||
if err != nil {
|
||||
return Schedule{}, err
|
||||
}
|
||||
return Schedule{Start: start, End: end, Loc: loc, WeekdaysOnly: weekdaysOnly}, nil
|
||||
}
|
||||
|
||||
// SameDay reports whether t is inside the window without crossing midnight
|
||||
// (start <= t < end, single-day window).
|
||||
func (s Schedule) inWindow(mins time.Duration) bool {
|
||||
if s.Start <= s.End {
|
||||
return mins >= s.Start && mins < s.End
|
||||
}
|
||||
// Wrapped window: [start, 24h) of the start day, [0, end) of the next.
|
||||
return mins >= s.Start || mins < s.End
|
||||
}
|
||||
|
||||
// InPeak reports whether t falls inside the peak window, evaluated in the
|
||||
// schedule's timezone. For wrapped windows the weekday check applies to the
|
||||
// day the window STARTED on (a Sunday 22:00-02:00 window is off all week
|
||||
// when weekdays-only, because it starts on Sunday).
|
||||
func (s Schedule) InPeak(t time.Time) bool {
|
||||
local := t.In(s.Loc)
|
||||
mins := time.Duration(local.Hour())*time.Hour + time.Duration(local.Minute())*time.Minute
|
||||
if s.Start <= s.End {
|
||||
if !s.inWindow(mins) {
|
||||
return false
|
||||
}
|
||||
return !s.WeekdaysOnly || isWeekday(local)
|
||||
}
|
||||
// Evening half: today carries the window.
|
||||
if mins >= s.Start {
|
||||
return !s.WeekdaysOnly || isWeekday(local)
|
||||
}
|
||||
// Morning half: the window started yesterday.
|
||||
if mins < s.End {
|
||||
return !s.WeekdaysOnly || isWeekday(local.AddDate(0, 0, -1))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isWeekday(t time.Time) bool {
|
||||
wd := t.Weekday()
|
||||
return wd >= time.Monday && wd <= time.Friday
|
||||
}
|
||||
Reference in New Issue
Block a user