onesvm-browser-server/server/internal/store/result_query.go
chii eb972dfa93 feat: 落地 browser-server 控制面并打通 mgr1 海外订阅
单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 15:05:12 +08:00

67 lines
2.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// result_query.go:jobs 表按 request_id 查询(W3 新增文件;禁改 W1 既有文件)。
package store
import (
"database/sql"
"fmt"
"time"
"onesvm.com/onesvm/browser-server/internal/config"
)
// JobByRequestID 按 request_id 查最新一条任务(/result/{request_id} 支撑;
// request_id 在 jobs 表唯一(gateway 生成 ULID),取 id 最大者兜底重试重入)。
func (d *DB) JobByRequestID(reqID string) (*Job, error) {
job, err := scanJob(d.raw.QueryRow(
`SELECT id, request_id, intent, payload, priority, status, available_at,
lease_until, attempts, worker, error, created_at, updated_at FROM jobs
WHERE request_id = ? ORDER BY id DESC LIMIT 1`, reqID))
if err != sql.ErrNoRows && err != nil {
return nil, fmt.Errorf("store: JobByRequestID: %w", err)
}
if err == sql.ErrNoRows {
return nil, ErrNotFound
}
return job, nil
}
// CountDead 死信数(/metrics)。
func (d *DB) CountDead() (int, error) {
var n int
if err := d.raw.QueryRow(`SELECT COUNT(id) FROM dead_letters`).Scan(&n); err != nil {
return 0, fmt.Errorf("store: CountDead: %w", err)
}
return n, nil
}
// QueueWaitAvgMs 平均排队等待(created_at → 首次 running 的 updated_at 差,
// 简化口径:全部 jobs 的 (updated_at-created_at) 均值,毫秒;估算指标)。
func (d *DB) QueueWaitAvgMs() (float64, error) {
rows, err := d.raw.Query(`SELECT created_at, updated_at FROM jobs WHERE status IN ('done','failed','dead') LIMIT 500`)
if err != nil {
return 0, fmt.Errorf("store: QueueWaitAvgMs: %w", err)
}
defer rows.Close()
var sumMS, n int64
for rows.Next() {
var c, u string
if err := rows.Scan(&c, &u); err != nil {
return 0, fmt.Errorf("store: QueueWaitAvgMs scan: %w", err)
}
ct, err1 := time.Parse(time.RFC3339, c)
ut, err2 := time.Parse(time.RFC3339, u)
if err1 == nil && err2 == nil && ut.After(ct) {
sumMS += ut.Sub(ct).Milliseconds()
n++
}
}
if err := rows.Err(); err != nil {
return 0, fmt.Errorf("store: QueueWaitAvgMs rows: %w", err)
}
if n == 0 {
return 0, nil
}
return float64(sumMS) / float64(n), nil
}
var _ = config.Now