@@ -45,9 +45,8 @@ type spectatorImpl struct {
4545 stateMu sync.RWMutex
4646 shardToOwner map [string ]* ShardOwner
4747
48- // Channel to signal when first state is received
49- firstStateCh chan struct {}
50- firstStateOnce sync.Once
48+ // Signal to notify when first state is received
49+ firstStateSignal csync.ResettableSignal
5150}
5251
5352func (s * spectatorImpl ) Start (ctx context.Context ) error {
@@ -68,10 +67,8 @@ func (s *spectatorImpl) Stop() {
6867 if s .cancel != nil {
6968 s .cancel ()
7069 }
71- // Close the firstStateCh to unblock any goroutines waiting for first state
72- s .firstStateOnce .Do (func () {
73- close (s .firstStateCh )
74- })
70+ // Close the firstStateSignal to unblock any goroutines waiting for first state
71+ s .firstStateSignal .Done ()
7572 s .stopWG .Wait ()
7673}
7774
@@ -166,9 +163,7 @@ func (s *spectatorImpl) handleResponse(response *types.WatchNamespaceStateRespon
166163
167164 // Signal that first state has been received (only once)
168165 if isFirstState {
169- s .firstStateOnce .Do (func () {
170- close (s .firstStateCh )
171- })
166+ s .firstStateSignal .Done ()
172167 }
173168
174169 s .logger .Debug ("Received namespace state update" ,
@@ -181,13 +176,7 @@ func (s *spectatorImpl) handleResponse(response *types.WatchNamespaceStateRespon
181176// If not found in cache, it falls back to querying the shard distributor directly.
182177func (s * spectatorImpl ) GetShardOwner (ctx context.Context , shardKey string ) (* ShardOwner , error ) {
183178 // Wait for first state to be received to avoid flooding shard distributor on startup
184- select {
185- case <- s .firstStateCh :
186- // First state received, continue
187- case <- ctx .Done ():
188- // Context cancelled or timed out before first state received
189- return nil , fmt .Errorf ("context cancelled while waiting for first state: %w" , ctx .Err ())
190- }
179+ s .firstStateSignal .Wait (ctx )
191180
192181 // Check cache first
193182 s .stateMu .RLock ()
0 commit comments