onesvm-browser-server/server/internal/scheduler/results.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

79 lines
2.2 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.

// results.go:任务结果缓存 + /result 查询支撑。
//
// 契约(A3.1):GET /result/{request_id}:done → Envelope;queued/running →
// 202 + {status};无 → 404。done 信封写进程内 bounded LRU(50 条,与 gateway
// 缓存同量级);schema 禁改(W1 纪律)→ 信封不另立列,进程内缓存为权威读面,
// 缓存淘汰后由 gateway 按 202 轮询引导重查。
package scheduler
import (
"encoding/json"
"sync"
"time"
"onesvm.com/onesvm/browser-server/internal/contract"
)
// resultEntry 结果条目。
type resultEntry struct {
env *contract.Envelope
setAt time.Time
}
// resultCache 进程内 done 信封缓存(bounded LRU)。
type resultCache struct {
mu sync.Mutex
cap int
items map[string]*resultEntry
order []string // LRU 序(头部最旧)
}
func newResultCache() *resultCache {
return &resultCache{cap: 50, items: map[string]*resultEntry{}}
}
// put 写入(超 cap 淘汰最旧)。
func (c *resultCache) put(reqID string, env *contract.Envelope) {
if reqID == "" || env == nil {
return
}
c.mu.Lock()
defer c.mu.Unlock()
if _, exists := c.items[reqID]; !exists {
c.order = append(c.order, reqID)
}
c.items[reqID] = &resultEntry{env: env, setAt: time.Now()}
for len(c.order) > c.cap {
oldest := c.order[0]
c.order = c.order[1:]
delete(c.items, oldest)
}
}
// get 读(命中提升 LRU 位)。
func (c *resultCache) get(reqID string) (*contract.Envelope, bool) {
c.mu.Lock()
defer c.mu.Unlock()
e, ok := c.items[reqID]
if !ok {
return nil, false
}
return e.env, true
}
// buildResultEnvelope 适配器执行结果 → Envelope(模版层 Build 的调用包装)。
func buildResultEnvelope(t *Template, in TemplateInput) *contract.Envelope {
return t.Build(TemplateInput{
Job: in.Job, Adapter: in.Adapter, ProxyExit: in.ProxyExit,
Cached: in.Cached, Raw: in.Raw, Warnings: in.Warnings, TookMs: in.TookMs,
})
}
// jsonRaw 信封序列化(/result 内嵌用)。
func jsonRaw(e *contract.Envelope) json.RawMessage {
b, err := json.Marshal(e)
if err != nil {
return json.RawMessage(`{"ok":false,"error":{"code":"upstream","message":"信封序列化失败"}}`)
}
return b
}