@@ -83,13 +83,17 @@ export class StorageNodeSelector implements StorageNodeSelectorService {
8383 }
8484
8585 // Select the next node in rendezvous order from the list of all nodes
86- this . selectedNode = ( await this . selectUntilEndOfList ( ) ) ?? null
87- this . logger . info ( 'Selected content node' , this . selectedNode )
88-
89- if ( ! this . selectedNode ) {
90- // We've selected all healthy nodes. Return null and start over next time select() is called
91- this . logger . info (
92- 'Selected all healthy nodes. Returning null and starting over next time select() is called'
86+ const selectedNode = await this . selectUntilEndOfList ( )
87+
88+ if ( selectedNode ) {
89+ this . selectedNode = selectedNode
90+ this . logger . info ( 'Selected content node' , this . selectedNode )
91+ } else {
92+ // No healthy nodes found. Fall back to a random node
93+ this . selectedNode = this . getRandomNode ( )
94+ this . logger . warn (
95+ 'No healthy nodes found. Falling back to random node:' ,
96+ this . selectedNode
9397 )
9498 this . selectionState = 'failed_all'
9599 }
@@ -126,6 +130,17 @@ export class StorageNodeSelector implements StorageNodeSelectorService {
126130 return selectedNode
127131 }
128132
133+ private getRandomNode ( ) : string | null {
134+ if ( ! this . orderedNodes ?. length ) {
135+ this . orderedNodes = this . orderNodes ( new Date ( ) . toString ( ) )
136+ }
137+ if ( this . orderedNodes . length === 0 ) {
138+ return null
139+ }
140+ const randomIndex = Math . floor ( Math . random ( ) * this . orderedNodes . length )
141+ return this . orderedNodes [ randomIndex ] ?? null
142+ }
143+
129144 private orderNodes ( key : string ) {
130145 const endpoints = this . nodes . map ( ( node ) => node . endpoint . toLowerCase ( ) )
131146 const hash = new RendezvousHash ( ...endpoints )
0 commit comments