@@ -49,6 +49,25 @@ type Backend struct {
4949 // cached from conn.Context()
5050 id string
5151 idents header.Identifiers
52+
53+ // draining indicates if this backend is draining and should not accept new connections
54+ draining bool
55+ // mu protects draining field
56+ mu sync.RWMutex
57+ }
58+
59+ // IsDraining returns true if the backend is draining
60+ func (b * Backend ) IsDraining () bool {
61+ b .mu .RLock ()
62+ defer b .mu .RUnlock ()
63+ return b .draining
64+ }
65+
66+ // SetDraining marks the backend as draining
67+ func (b * Backend ) SetDraining () {
68+ b .mu .Lock ()
69+ defer b .mu .Unlock ()
70+ b .draining = true
5271}
5372
5473func (b * Backend ) Send (p * client.Packet ) error {
@@ -346,9 +365,24 @@ func (s *DefaultBackendStorage) GetRandomBackend() (*Backend, error) {
346365 if len (s .backends ) == 0 {
347366 return nil , & ErrNotFound {}
348367 }
349- agentID := s .agentIDs [s .random .Intn (len (s .agentIDs ))]
350- klog .V (3 ).InfoS ("Pick agent as backend" , "agentID" , agentID )
351- // always return the first connection to an agent, because the agent
352- // will close later connections if there are multiple.
353- return s .backends [agentID ][0 ], nil
368+
369+ // Start at a random agent and check each agent in sequence
370+ startIdx := s .random .Intn (len (s .agentIDs ))
371+ for i := 0 ; i < len (s .agentIDs ); i ++ {
372+ // Wrap around using modulo
373+ currentIdx := (startIdx + i ) % len (s .agentIDs )
374+ agentID := s .agentIDs [currentIdx ]
375+ // always return the first connection to an agent, because the agent
376+ // will close later connections if there are multiple.
377+ backend := s .backends [agentID ][0 ]
378+
379+ if ! backend .IsDraining () {
380+ klog .V (3 ).InfoS ("Pick agent as backend" , "agentID" , agentID )
381+ return backend , nil
382+ }
383+ }
384+
385+ // All agents are draining
386+ klog .V (2 ).InfoS ("No non-draining backends available" )
387+ return nil , & ErrNotFound {}
354388}
0 commit comments