From 80bad0d184e6332c100b0fc5fe4a791d40316eb2 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Sat, 15 Nov 2025 03:35:07 +0700 Subject: [PATCH] fix(sync): `AdaptiveWaitGroup` counter racy causing flaky tests. Reorder counter updates relative to semaphore ops to prevent race condition where `Current()` could temporarily exceed 2485582size+12485582. * `Add()`: inc counter before acquiring semaphore * `Done()`: dec counter before releasing semaphore This eliminates the race window where both `Add()` and `Done()` had pending counter updates, causing `TestThrottling` to fail in CI with `Current()` reaching 6-7 instead of expected max. of 5 (size=4). Signed-off-by: Dwi Siswanto --- sync/adaptivewaitgroup.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sync/adaptivewaitgroup.go b/sync/adaptivewaitgroup.go index f9ab354d..2b07c3ce 100644 --- a/sync/adaptivewaitgroup.go +++ b/sync/adaptivewaitgroup.go @@ -67,22 +67,23 @@ func (s *AdaptiveWaitGroup) AddWithContext(ctx context.Context) error { case <-ctx.Done(): return ctx.Err() default: + s.current.Add(1) + // Attempt to acquire a semaphore slot, handle error if acquisition fails if err := s.sem.Acquire(ctx, 1); err != nil { + s.current.Add(-1) return err } } - // Safely add to the waitgroup only after acquiring the semaphore s.wg.Add(1) - s.current.Add(1) return nil } func (s *AdaptiveWaitGroup) Done() { + s.current.Add(-1) s.sem.Release(1) s.wg.Done() - s.current.Add(-1) } func (s *AdaptiveWaitGroup) Wait() {