1717logger = logging .getLogger (__name__ )
1818
1919# Circuit Breaker Configuration Constants
20- DEFAULT_FAILURE_THRESHOLD = 0.5
21- DEFAULT_MINIMUM_CALLS = 20
22- DEFAULT_TIMEOUT = 30
23- DEFAULT_RESET_TIMEOUT = 30
24- DEFAULT_EXPECTED_EXCEPTION = (Exception ,)
25- DEFAULT_NAME = "telemetry-circuit-breaker"
20+ MINIMUM_CALLS = 20
21+ RESET_TIMEOUT = 30
22+ CIRCUIT_BREAKER_NAME = "telemetry-circuit-breaker"
2623
2724# Circuit Breaker State Constants
2825CIRCUIT_BREAKER_STATE_OPEN = "open"
2926CIRCUIT_BREAKER_STATE_CLOSED = "closed"
3027CIRCUIT_BREAKER_STATE_HALF_OPEN = "half-open"
3128CIRCUIT_BREAKER_STATE_DISABLED = "disabled"
32- CIRCUIT_BREAKER_STATE_NOT_INITIALIZED = "not_initialized"
3329
3430# Logging Message Constants
3531LOG_CIRCUIT_BREAKER_STATE_CHANGED = "Circuit breaker state changed from %s to %s for %s"
@@ -76,56 +72,18 @@ def state_change(self, cb: CircuitBreaker, old_state, new_state) -> None:
7672logger .info (LOG_CIRCUIT_BREAKER_HALF_OPEN ,cb .name )
7773
7874
79- @dataclass (frozen = True )
80- class CircuitBreakerConfig :
81- """Configuration for circuit breaker behavior.
82-
83- This class is immutable to prevent modification of circuit breaker settings.
84- All configuration values are set to constants defined at the module level.
85- """
86-
87- # Failure threshold percentage (0.0 to 1.0)
88- failure_threshold :float = DEFAULT_FAILURE_THRESHOLD
89-
90- # Minimum number of calls before circuit can open
91- minimum_calls :int = DEFAULT_MINIMUM_CALLS
92-
93- # Time window for counting failures (in seconds)
94- timeout :int = DEFAULT_TIMEOUT
95-
96- # Time to wait before trying to close circuit (in seconds)
97- reset_timeout :int = DEFAULT_RESET_TIMEOUT
98-
99- # Expected exception types that should trigger circuit breaker
100- expected_exception :tuple = DEFAULT_EXPECTED_EXCEPTION
101-
102- # Name for the circuit breaker (for logging)
103- name :str = DEFAULT_NAME
104-
105-
10675class CircuitBreakerManager :
10776"""
10877 Manages circuit breaker instances for telemetry requests.
10978
11079 This class provides a singleton pattern to manage circuit breaker instances
11180 per host, ensuring that telemetry failures don't impact main SQL operations.
81+
82+ Circuit breaker configuration is fixed and cannot be overridden.
11283 """
11384
11485_instances :Dict [str ,CircuitBreaker ]= {}
11586_lock = threading .RLock ()
116- _config :Optional [CircuitBreakerConfig ]= None
117-
118- @classmethod
119- def initialize (cls ,config :CircuitBreakerConfig )-> None :
120- """
121- Initialize the circuit breaker manager with configuration.
122-
123- Args:
124- config: Circuit breaker configuration
125- """
126- with cls ._lock :
127- cls ._config = config
128- logger .debug ("CircuitBreakerManager initialized with config: %s" ,config )
12987
13088@classmethod
13189def get_circuit_breaker (cls ,host :str )-> CircuitBreaker :
@@ -138,10 +96,6 @@ def get_circuit_breaker(cls, host: str) -> CircuitBreaker:
13896 Returns:
13997 CircuitBreaker instance for the host
14098 """
141- if not cls ._config :
142- # Return a no-op circuit breaker if not initialized
143- return cls ._create_noop_circuit_breaker ()
144-
14599with cls ._lock :
146100if host not in cls ._instances :
147101cls ._instances [host ]= cls ._create_circuit_breaker (host )
@@ -160,93 +114,16 @@ def _create_circuit_breaker(cls, host: str) -> CircuitBreaker:
160114 Returns:
161115 New CircuitBreaker instance
162116 """
163- config = cls ._config
164- if config is None :
165- raise RuntimeError ("CircuitBreakerManager not initialized" )
166-
167- # Create circuit breaker with configuration
117+ # Create circuit breaker with fixed configuration
168118breaker = CircuitBreaker (
169- fail_max = config . minimum_calls , # Number of failures before circuit opens
170- reset_timeout = config . reset_timeout ,
171- name = f"{ config . name } -{ host } " ,
119+ fail_max = MINIMUM_CALLS ,
120+ reset_timeout = RESET_TIMEOUT ,
121+ name = f"{ CIRCUIT_BREAKER_NAME } -{ host } " ,
172122 )
173-
174- # Add state change listeners for logging
175123breaker .add_listener (CircuitBreakerStateListener ())
176124
177125return breaker
178126
179- @classmethod
180- def _create_noop_circuit_breaker (cls )-> CircuitBreaker :
181- """
182- Create a no-op circuit breaker that always allows calls.
183-
184- Returns:
185- CircuitBreaker that never opens
186- """
187- # Create a circuit breaker with very high thresholds so it never opens
188- breaker = CircuitBreaker (
189- fail_max = 1000000 ,# Very high threshold
190- reset_timeout = 1 ,# Short reset time
191- name = "noop-circuit-breaker" ,
192- )
193- return breaker
194-
195- @classmethod
196- def get_circuit_breaker_state (cls ,host :str )-> str :
197- """
198- Get the current state of the circuit breaker for a host.
199-
200- Args:
201- host: The hostname
202-
203- Returns:
204- Current state of the circuit breaker
205- """
206- if not cls ._config :
207- return CIRCUIT_BREAKER_STATE_DISABLED
208-
209- with cls ._lock :
210- if host not in cls ._instances :
211- return CIRCUIT_BREAKER_STATE_NOT_INITIALIZED
212-
213- breaker = cls ._instances [host ]
214- return breaker .current_state
215-
216- @classmethod
217- def reset_circuit_breaker (cls ,host :str )-> None :
218- """
219- Reset the circuit breaker for a host to closed state.
220-
221- Args:
222- host: The hostname
223- """
224- with cls ._lock :
225- if host in cls ._instances :
226- # pybreaker doesn't have a reset method, we need to recreate the breaker
227- del cls ._instances [host ]
228- logger .info ("Reset circuit breaker for host: %s" ,host )
229-
230- @classmethod
231- def clear_circuit_breaker (cls ,host :str )-> None :
232- """
233- Remove the circuit breaker instance for a host.
234-
235- Args:
236- host: The hostname
237- """
238- with cls ._lock :
239- if host in cls ._instances :
240- del cls ._instances [host ]
241- logger .debug ("Cleared circuit breaker for host: %s" ,host )
242-
243- @classmethod
244- def clear_all_circuit_breakers (cls )-> None :
245- """Clear all circuit breaker instances."""
246- with cls ._lock :
247- cls ._instances .clear ()
248- logger .debug ("Cleared all circuit breakers" )
249-
250127
251128def is_circuit_breaker_error (exception :Exception )-> bool :
252129"""