@@ -193,7 +193,7 @@ func (c *MultiNode[CHAIN_ID, RPC]) SelectRPC(ctx context.Context) (rpc RPC, err
193193// selectNode returns the active Node, if it is still nodeStateAlive, otherwise it selects a new one from the NodeSelector.
194194func (c * MultiNode [CHAIN_ID , RPC ]) selectNode (ctx context.Context ) (node Node [CHAIN_ID , RPC ], err error ) {
195195 if c .selectionMode == NodeSelectionModeRandomRPC {
196- return c .selectRandomRPCNode (ctx )
196+ return c .awaitNodeSelection (ctx )
197197 }
198198
199199 c .activeMu .RLock ()
@@ -217,34 +217,18 @@ func (c *MultiNode[CHAIN_ID, RPC]) selectNode(ctx context.Context) (node Node[CH
217217 c .activeNode .UnsubscribeAllExceptAliveLoop ()
218218 }
219219
220- for {
221- c .activeNode = c .nodeSelector .Select ()
222- if c .activeNode != nil {
223- break
224- }
225- if slices .ContainsFunc (c .primaryNodes , func (n Node [CHAIN_ID , RPC ]) bool {
226- return n .State ().isInitializing ()
227- }) {
228- // initial dial still in-progress - retry until done
229- select {
230- case <- ctx .Done ():
231- return nil , ctx .Err ()
232- case <- time .After (100 * time .Millisecond ):
233- continue
234- }
235- }
236- c .lggr .Criticalw ("No live RPC nodes available" , "NodeSelectionMode" , c .nodeSelector .Name ())
237- c .eng .EmitHealthErr (fmt .Errorf ("no live nodes available for chain %s" , c .chainID .String ()))
238- return nil , ErrNodeError
220+ c .activeNode , err = c .awaitNodeSelection (ctx )
221+ if err != nil {
222+ return nil , err
239223 }
240224
241225 c .lggr .Debugw ("Switched to a new active node due to prev node heath issues" , "prevNode" , prevNodeName , "newNode" , c .activeNode .String ())
242226 return c .activeNode , err
243227}
244228
245- // selectRandomRPCNode picks a random healthy node on every call without caching
246- // or terminating existing subscriptions on other nodes.
247- func (c * MultiNode [CHAIN_ID , RPC ]) selectRandomRPCNode (ctx context.Context ) (Node [CHAIN_ID , RPC ], error ) {
229+ // awaitNodeSelection blocks until nodeSelector returns a live node or all nodes
230+ // finish initializing. Returns ErrNodeError when no live nodes are available .
231+ func (c * MultiNode [CHAIN_ID , RPC ]) awaitNodeSelection (ctx context.Context ) (Node [CHAIN_ID , RPC ], error ) {
248232 for {
249233 node := c .nodeSelector .Select ()
250234 if node != nil {
0 commit comments