feat: add automatic Worker runtime with lease recovery and bounded shutdown
This commit is contained in:
76
sdk/go/worker_lease_guard.go
Normal file
76
sdk/go/worker_lease_guard.go
Normal file
@@ -0,0 +1,76 @@
|
||||
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 }
|
||||
Reference in New Issue
Block a user