61 lines
1.5 KiB
Go
61 lines
1.5 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
|
core "git.yuntuo.hk/k2safe/orbit/model"
|
|
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
|
"git.yuntuo.hk/k2safe/orbit/pulse/worker"
|
|
)
|
|
|
|
type claimResult struct {
|
|
assignment *worker.Assignment
|
|
err error
|
|
}
|
|
|
|
func workerPollKey(ns core.ID, in worker.ConnectInput) [32]byte {
|
|
// 正式注册已校验;再次规范化仅取得稳定能力集合,不包含任何秘密。
|
|
in, _ = worker.NormalizeConnect(in)
|
|
raw, _ := json.Marshal(struct {
|
|
Namespace, Queue core.ID
|
|
Capabilities []worker.Capability
|
|
Keys bool
|
|
}{ns, in.QueueID, in.Capabilities, in.ConcurrencyKeys})
|
|
return sha256.Sum256(raw)
|
|
}
|
|
func (h *WorkerHub) claimFair(ctx context.Context, t auth.Token, b worker.Binding, key [32]byte) (out claimResult) {
|
|
// HTTP handler 原本具有 panic 隔离;异步领取同样不能因一次异常杀死其他连接。
|
|
defer func() {
|
|
if recover() != nil {
|
|
out = claimResult{err: fault.Unavailable}
|
|
}
|
|
}()
|
|
h.mu.Lock()
|
|
until := h.emptyPolls[key]
|
|
h.mu.Unlock()
|
|
if until.After(time.Now()) {
|
|
return out
|
|
}
|
|
call, stop := context.WithTimeout(ctx, 8*time.Second)
|
|
defer stop()
|
|
out.assignment, out.err = h.service.Claim(call, t, b)
|
|
if out.assignment == nil && out.err == nil {
|
|
h.mu.Lock()
|
|
now := time.Now()
|
|
for k, v := range h.emptyPolls {
|
|
if !v.After(now) {
|
|
delete(h.emptyPolls, k)
|
|
}
|
|
}
|
|
if len(h.emptyPolls) < 128 {
|
|
h.emptyPolls[key] = now.Add(h.poll)
|
|
}
|
|
h.mu.Unlock()
|
|
}
|
|
return out
|
|
}
|