Files
orbit/sdk/go/worker_lease_guard.go

77 lines
1.8 KiB
Go
Raw Permalink 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.
package orbit
import (
"context"
"sync"
"time"
)
// executionGuard 独立于网络控制取消处理器,已到期/取消的上下文永不恢复。
type executionGuard struct {
ctx context.Context
cancel context.CancelCauseFunc
mu sync.Mutex
deadline time.Time
wake chan struct{}
done chan struct{}
}
func newExecutionGuard(parent context.Context, lease WorkerLease) (*executionGuard, bool) {
deadline, ok := lease.ExecutionDeadline()
if !ok {
return nil, false
}
ctx, cancel := context.WithCancelCause(parent)
g := &executionGuard{ctx: ctx, cancel: cancel, deadline: deadline, wake: make(chan struct{}, 1), done: make(chan struct{})}
go g.watch()
return g, true
}
func (g *executionGuard) watch() {
defer close(g.done)
timer := time.NewTimer(time.Until(g.until()))
defer timer.Stop()
for {
select {
case <-g.ctx.Done():
return
case <-g.wake:
case <-timer.C:
}
g.mu.Lock()
remaining := time.Until(g.deadline)
if remaining <= 0 {
g.cancel(ErrExecutionLeaseLost)
g.mu.Unlock()
return
}
timer.Reset(remaining)
g.mu.Unlock()
}
}
func (g *executionGuard) update(lease WorkerLease) bool {
g.mu.Lock()
defer g.mu.Unlock()
if g.ctx.Err() != nil || !time.Now().Before(g.deadline) {
g.cancel(ErrExecutionLeaseLost)
return false
}
deadline, ok := lease.ExecutionDeadline()
if !lease.Active || lease.State != "RUNNING" {
g.cancel(ErrExecutionLeaseLost)
return false
}
// Lease 是新鲜核验,不是历史 Receipt。新会话可能缩短有效窗口,必须遵守。
if !ok {
g.cancel(ErrExecutionLeaseLost)
return false
}
g.deadline = deadline
select {
case g.wake <- struct{}{}:
default:
}
return true
}
func (g *executionGuard) until() time.Time { g.mu.Lock(); defer g.mu.Unlock(); return g.deadline }
func (g *executionGuard) stop(cause error) { g.cancel(cause); <-g.done }