@@ -503,8 +503,9 @@ type terminator struct {
503503 mu sync.RWMutex
504504 stopped bool
505505
506- // largestIssued tracks the largest index allocated by this appender.
507- largestIssued atomic.Uint64
506+ // wantTreeSize tracks a tree size which is large enough to cover all
507+ // locally added entries.
508+ wantTreeSize atomic.Uint64
508509
509510 // shutdownTimeout is the maximum duration to wait for the shutdown process to complete.
510511 shutdownTimeout time.Duration
@@ -525,12 +526,13 @@ func (t *terminator) Add(ctx context.Context, entry *Entry) IndexFuture {
525526 return i , err
526527 }
527528
528- // https://github.com/golang/go/issues/63999 - atomically set largest issued index
529- old := t .largestIssued .Load ()
530- for old < i .Index && ! t .largestIssued .CompareAndSwap (old , i .Index ) {
531- old = t .largestIssued .Load ()
529+ // https://github.com/golang/go/issues/63999 - atomically set minimum tree size for shutdown.
530+ wantSize := i .Index + 1
531+ old := t .wantTreeSize .Load ()
532+ for old < wantSize && ! t .wantTreeSize .CompareAndSwap (old , wantSize ) {
533+ old = t .wantTreeSize .Load ()
532534 }
533- appenderHighestIndex .Record (ctx , otel .Clamp64 (t .largestIssued .Load ()))
535+ appenderHighestIndex .Record (ctx , otel .Clamp64 (t .wantTreeSize .Load ()- 1 ))
534536
535537 return i , err
536538 }
@@ -546,8 +548,9 @@ func (t *terminator) Shutdown(ctx context.Context) error {
546548 t .mu .Lock ()
547549 defer t .mu .Unlock ()
548550 t .stopped = true
549- maxIndex := t .largestIssued .Load ()
550- if maxIndex == 0 {
551+
552+ wantSize := t .wantTreeSize .Load ()
553+ if wantSize == 0 {
551554 // special case no work done
552555 return nil
553556 }
@@ -580,8 +583,8 @@ func (t *terminator) Shutdown(ctx context.Context) error {
580583 if err != nil {
581584 return err
582585 }
583- slog .DebugContext (gCtx , "Shutting down, waiting for checkpoint" , slog .Uint64 ("goal" , maxIndex ), slog .Uint64 ("current" , size ))
584- if size > maxIndex {
586+ slog .DebugContext (gCtx , "Shutting down, waiting for checkpoint" , slog .Uint64 ("goal" , wantSize ), slog .Uint64 ("current" , size ))
587+ if size >= wantSize {
585588 return nil
586589 }
587590 }
@@ -604,8 +607,8 @@ func (t *terminator) Shutdown(ctx context.Context) error {
604607 if err != nil {
605608 return err
606609 }
607- slog .DebugContext (gCtx , "Shutting down, waiting for follower" , slog .String ("follower" , f .Name ()), slog .Uint64 ("goal" , maxIndex ), slog .Uint64 ("processed" , processed ))
608- if processed > maxIndex {
610+ slog .DebugContext (gCtx , "Shutting down, waiting for follower" , slog .String ("follower" , f .Name ()), slog .Uint64 ("goal" , wantSize ), slog .Uint64 ("processed" , processed ))
611+ if processed >= wantSize {
609612 return nil
610613 }
611614 }
0 commit comments