feat: support durable task cancellation without foreign keys
This commit is contained in:
@@ -248,6 +248,7 @@ func (h *WorkerHub) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
draining := welcome.Draining
|
||||
eligible := false
|
||||
leases := map[core.ID]time.Time{}
|
||||
cancelSent := map[core.ID]bool{}
|
||||
ticker := time.NewTicker(h.poll)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
@@ -332,6 +333,36 @@ func (h *WorkerHub) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
case <-ticker.C:
|
||||
// 取消与领取容量、排空无关;通知丢失后仍可由 Resume/Renew 核对持久化意图。
|
||||
if input.CancellationNotifications && len(leases) > 0 {
|
||||
call, stop := context.WithTimeout(ctx, 8*time.Second)
|
||||
items, err := h.service.Cancellations(call, token, binding)
|
||||
stop()
|
||||
if err != nil {
|
||||
if fault.Code(err) == "STALE_SESSION" || fault.Code(err) == "UNAUTHENTICATED" || fault.Code(err) == "PERMISSION_DENIED" {
|
||||
send(workerFrame{Type: "error", Error: publicWorkerError(err)}, true)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
active := make(map[core.ID]bool, len(items))
|
||||
for _, item := range items {
|
||||
active[item.AttemptID] = true
|
||||
if cancelSent[item.AttemptID] || len(outgoing) >= 4 {
|
||||
continue
|
||||
}
|
||||
raw, err := jsonwire.Marshal(item)
|
||||
if err != nil || !send(workerFrame{Type: "task.cancel", Body: raw}, false) {
|
||||
return
|
||||
}
|
||||
cancelSent[item.AttemptID] = true
|
||||
}
|
||||
for id := range cancelSent {
|
||||
if !active[id] {
|
||||
delete(cancelSent, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 本地记录仅减少空轮询;SQL 仍原子验证总容量、队列额度和有效会话。
|
||||
now := time.Now()
|
||||
for attempt, until := range leases {
|
||||
|
||||
Reference in New Issue
Block a user