feat: add automatic Worker runtime with lease recovery and bounded shutdown

This commit is contained in:
2026-09-17 14:29:28 +08:00
parent 1753fcbccb
commit da123bba69
22 changed files with 1784 additions and 17 deletions

View 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 }