22Routing strategies for load balancing across providers.
33"""
44import random
5+ import logging
56from typing import List , Optional
67from abc import ABC , abstractmethod
78
9+ # Configure logging for this module
10+ logger = logging .getLogger (__name__ )
11+ # Ensure we show debug messages
12+ logging .basicConfig ()
13+ logger .setLevel (logging .DEBUG )
14+
815class Router (ABC ):
916 """Abstract base class for routing strategies"""
1017
@@ -17,21 +24,44 @@ class RoundRobinRouter(Router):
1724 """Round-robin routing strategy"""
1825
1926 def __init__ (self , providers : List ):
20- self .providers = providers
27+ self .all_providers = providers
2128 self .index = 0
2229
2330 def select (self , providers : List ) -> Optional :
2431 if not providers :
32+ logger .debug ("Round-robin: No providers available" )
2533 return None
2634
27- # Find next available provider
28- for _ in range (len (providers )):
29- provider = self .providers [self .index % len (self .providers )]
30- self .index += 1
31- if provider in providers :
32- return provider
35+ # If only one provider available, return it
36+ if len (providers ) == 1 :
37+ logger .debug (f"Round-robin: Only one provider: { providers [0 ].name } " )
38+ return providers [0 ]
3339
34- return providers [0 ] if providers else None
40+ logger .debug (f"Round-robin: Starting selection, index={ self .index } , providers={ [p .name for p in providers ]} " )
41+
42+ # Find next available provider in round-robin fashion
43+ start_index = self .index
44+ attempts = 0
45+ while attempts < len (self .all_providers ):
46+ # Get provider at current index from all providers
47+ current_provider = self .all_providers [self .index % len (self .all_providers )]
48+ next_index = (self .index + 1 ) % len (self .all_providers )
49+
50+ logger .debug (f"Round-robin: Checking provider { current_provider .name } at index { self .index } " )
51+
52+ # Update index for next call
53+ self .index = next_index
54+
55+ # If this provider is in the available list, use it
56+ if current_provider in providers :
57+ logger .debug (f"Round-robin: Selected provider { current_provider .name } " )
58+ return current_provider
59+
60+ attempts += 1
61+
62+ # If we've cycled through all providers, just return first available
63+ logger .debug (f"Round-robin: Fallback to first available: { providers [0 ].name } " )
64+ return providers [0 ]
3565
3666class WeightedRouter (Router ):
3767 """Weighted random routing strategy"""
0 commit comments