queue stats: cast the claim-wait average to whole seconds !351

merged merged by cmc on 2026-09-08 06:23 UTC · krz/gitbay:queue-avg-cast into main

2 files changed, +36 −2

Layout: unified · split

internal/store/builds.go +2 −2
@@ -213,8 +213,8 @@ func (s *Store) QueueStats() (QueueStats, error) {
213213 err := s.DB.QueryRow(`SELECT
214214 (SELECT COUNT(*) FROM builds WHERE status = 'pending'),
215215 COUNT(*),
216 COALESCE(AVG(strftime('%s', started_at) - strftime('%s', created_at)), 0),
217 COALESCE(MAX(strftime('%s', started_at) - strftime('%s', created_at)), 0),
216 CAST(COALESCE(AVG(strftime('%s', started_at) - strftime('%s', created_at)), 0) AS INTEGER),
217 CAST(COALESCE(MAX(strftime('%s', started_at) - strftime('%s', created_at)), 0) AS INTEGER),
218218 (SELECT COUNT(*) FROM builds WHERE reaped_at >= ?)
219219 FROM builds WHERE started_at >= ?`, since, since).
220220 Scan(&q.Pending, &q.Claimed24h, &q.ClaimWaitAvgS, &q.ClaimWaitMaxS, &q.Reaped24h)
internal/store/builds_test.go +34
@@ -297,3 +297,37 @@ func TestReapStaleBuildsAfterLogClosed(t *testing.T) {
297297 t.Fatal(err)
298298 }
299299}
300
301// AVG is a float in SQLite; the stats scan it as whole seconds.
302func TestQueueStatsFractionalAverage(t *testing.T) {
303 s := open(t)
304 if err := s.MigrateUp(); err != nil {
305 t.Fatal(err)
306 }
307 uid, err := s.CreateUser("cmc", true)
308 if err != nil {
309 t.Fatal(err)
310 }
311 if _, err := s.CreateRepo("user", uid, "orgo", "public"); err != nil {
312 t.Fatal(err)
313 }
314 for range 2 {
315 if _, err := s.CreateBuild(1, "test", "abc123", "main", `["true"]`, "", "", true); err != nil {
316 t.Fatal(err)
317 }
318 if _, ok, err := s.ClaimBuild(nil); err != nil || !ok {
319 t.Fatalf("claim: %v ok=%v", err, ok)
320 }
321 }
322 // Waits of 1 s and 2 s: an average of 1.5.
323 if _, err := s.DB.Exec(`UPDATE builds SET created_at = strftime('%Y-%m-%dT%H:%M:%SZ', started_at, '-' || number || ' seconds')`); err != nil {
324 t.Fatal(err)
325 }
326 q, err := s.QueueStats()
327 if err != nil {
328 t.Fatal(err)
329 }
330 if q.Claimed24h != 2 || q.ClaimWaitAvgS != 1 || q.ClaimWaitMaxS != 2 || q.Pending != 0 || q.Reaped24h != 0 {
331 t.Fatalf("stats: %+v", q)
332 }
333}