mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 00:32:40 +00:00
Coop: split lock checks (per-minute) from resolution (daily)
Locks were gated behind the same once-per-day 08:00 UTC tick as floor resolution. A run created after morningHour would wait until next day's tick to be eligible — meaning actual lock latency could be 24-48h, not the 24h advertised. Worse, a run created late on Day N missed the Day N+1 tick (too early) AND the Day N+2 tick happens 48h after creation. Fix: lock checks fire on every ticker minute (cheap timestamp scan over typically 0-5 open runs). Resolution stays daily, gated by JobCompleted. Real symptom that prompted this: Run #1 created 17:17 UTC, locked never fired because the morning tick at 08:00 UTC the next day saw the run as not-yet-eligible (only 15h elapsed), then marked the daily job complete before the actual 24h elapsed at 17:17 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,20 +14,24 @@ import (
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// coopTicker fires once per UTC day to:
|
||||
// 1. Lock open invites whose 24h window has elapsed.
|
||||
// 2. For each active run, resolve the day's floor and advance/complete.
|
||||
// coopTicker has two cadences:
|
||||
//
|
||||
// Reuses the daily_prefetch job-completion guard so a bot restart on the same
|
||||
// UTC day does not double-process.
|
||||
// 1. Lock checks fire every minute. They're cheap (one timestamp comparison
|
||||
// per open run) and a 24h invite window is poorly served by a 24h tick —
|
||||
// a run started after 08:00 UTC would otherwise wait 30-48h to lock.
|
||||
// 2. Floor resolution fires once per UTC day at morningHour, gated by the
|
||||
// daily_prefetch JobCompleted guard. Resolution is the heavy step that
|
||||
// advances days, distributes rewards, and posts to the room.
|
||||
func (p *AdventurePlugin) coopTicker() {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
// Locks: every minute.
|
||||
p.coopProcessLocks()
|
||||
|
||||
// Resolutions: once per day at morningHour:00 UTC.
|
||||
now := time.Now().UTC()
|
||||
// Run at the same minute as the morning DM (08:00 UTC) — same cadence as
|
||||
// the rest of the adventure system.
|
||||
if now.Hour() != p.morningHour || now.Minute() != 0 {
|
||||
continue
|
||||
}
|
||||
@@ -36,8 +40,7 @@ func (p *AdventurePlugin) coopTicker() {
|
||||
if db.JobCompleted(jobName, dateKey) {
|
||||
continue
|
||||
}
|
||||
slog.Info("coop: daily tick")
|
||||
p.coopProcessLocks()
|
||||
slog.Info("coop: daily tick — resolving active runs")
|
||||
p.coopProcessActiveRuns()
|
||||
db.MarkJobCompleted(jobName, dateKey)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user