Skip to content

Commit 417bc36

Browse files
authored
Separate retirement fence deadline from the held lease query (#314)
1 parent 9ef8258 commit 417bc36

1 file changed

Lines changed: 18 additions & 6 deletions

File tree

‎services/core/internal/execution/runtime_retirement_failure_test.go‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import (
1111
"github.com/MiniMax-AI/OpenAgentCore/services/core/internal/sandbox"
1212
)
1313

14+
// retirementFenceLease bounds only the cancellation attempt. The concurrent
15+
// owner query retains the production lease deadline and must remain usable.
16+
type retirementFenceLease struct{ Ownership }
17+
18+
func (l retirementFenceLease) CancelOperations(ctx context.Context, cancel context.CancelFunc) error {
19+
ctx, stop := context.WithTimeout(ctx, 100*time.Millisecond)
20+
defer stop()
21+
return l.Ownership.CancelOperations(ctx, cancel)
22+
}
23+
1424
func TestFailedInventoryRetirementClosesAdmissionAndRetainsGate(t *testing.T) {
1525
for _, mode := range []string{"gate_timeout", "lease_loss"} {
1626
t.Run(mode, func(t *testing.T) {
@@ -43,13 +53,12 @@ func TestFailedInventoryRetirementClosesAdmissionAndRetainsGate(t *testing.T) {
4353
go func() { defer m.active.Done(); defer finish(); <-operation.Done(); <-releaseProvider }()
4454
var queryDone chan error
4555
if mode == "gate_timeout" {
46-
// This independent owner caller has its own bounded query context. Unlike
47-
// a lifecycle scan, it is not canceled by the manager's shutdown context.
48-
queryCtx, cancel := context.WithTimeout(t.Context(), 10*time.Second)
49-
defer cancel()
56+
// Both lease operations have the same production deadline. Give only
57+
// the later fence a shorter caller deadline so it expires first.
58+
m.lease = retirementFenceLease{Ownership: owner.Lease}
5059
queryDone = make(chan error, 1)
5160
armed.Store(true)
52-
go func() { queryDone <- owner.Lease.CheckOwnership(queryCtx) }()
61+
go func() { queryDone <- owner.Lease.CheckOwnership(t.Context()) }()
5362
select {
5463
case <-reading:
5564
case <-time.After(2 * time.Second):
@@ -114,13 +123,16 @@ func TestFailedInventoryRetirementClosesAdmissionAndRetainsGate(t *testing.T) {
114123
unblockRead()
115124
select {
116125
case err := <-queryDone:
126+
queryDone = nil
117127
if err != nil {
118128
t.Fatal("fence timeout damaged unrelated owner read", err)
119129
}
120130
case <-time.After(2 * time.Second):
121131
t.Fatal("owner read did not settle")
122132
}
123-
queryDone = nil
133+
if err := owner.Lease.CheckOwnership(t.Context()); err != nil {
134+
t.Fatal("fence timeout lost the execution lease", err)
135+
}
124136
}
125137
// Shutdown can now cancel the original work, but cannot call it settled
126138
// merely because cancellation was requested or a serial gate became free.

0 commit comments

Comments
 (0)