单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。 Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.1 KiB
Go
67 lines
2.1 KiB
Go
// 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
|