Bound MarkAbandoned's compare-and-set retries, giving up after 10 tries (issue 711)

This commit is contained in:
jochen
2026-10-15 15:20:43 +02:00
parent 9aeb5f4493
commit e603b2cae1
2 changed files with 43 additions and 2 deletions
+9 -2
View File
@@ -87,6 +87,10 @@ func (b *BusCalls) Kept(ctx context.Context, id string) (Call, bool, error) {
return c, true, nil
}
// markAbandonedTries bounds the compare-and-set loop below (novox/hq issue 711 review round 1): a
// record that keeps changing on every read is not this sweep's to keep retrying forever over.
const markAbandonedTries = 10
// MarkAbandoned marks id abandoned unless its record already says it finished (novox/hq issue 711):
// a controller starting finds a call running under a holder that stopped, but that holder may have
// written the finish — with its kept answer — around the same moment. The record's own
@@ -94,9 +98,11 @@ func (b *BusCalls) Kept(ctx context.Context, id string) (Call, bool, error) {
// reads the record, and if it still says running, writes abandoned at that revision; a finish landing
// in between fails the write with a revision mismatch, and this rereads and finds the finish, which
// then stands. A record already resolved, or gone, is returned as found, so the caller never writes
// abandoned over it.
// abandoned over it. Past markAbandonedTries attempts, it gives up and returns an error naming the
// call instead of looping forever (novox/hq issue 711 review round 1); Durably reports that as it
// reports any other keeper error.
func (b *BusCalls) MarkAbandoned(ctx context.Context, id string) (Call, error) {
for {
for try := 0; try < markAbandonedTries; try++ {
entry, err := b.kv.Get(ctx, id)
if errors.Is(err, jetstream.ErrKeyNotFound) || errors.Is(err, jetstream.ErrInvalidKey) {
return Call{}, nil
@@ -125,6 +131,7 @@ func (b *BusCalls) MarkAbandoned(ctx context.Context, id string) (Call, error) {
}
return c, nil
}
return Call{}, fmt.Errorf("%s: its record kept changing; it is left as it stands", id)
}
// Recent is every call the bucket holds, newest first, without answers: read once through a watch