2323from databricks .sql .telemetry .circuit_breaker_manager import CircuitBreakerManager
2424
2525
26- def wait_for_circuit_state (circuit_breaker , expected_state , timeout = 5 ):
26+ def wait_for_circuit_state (circuit_breaker , expected_states , timeout = 5 ):
2727 """
28- Wait for circuit breaker to reach expected state with polling.
29-
28+ Wait for circuit breaker to reach one of the expected states with polling.
29+
3030 Args:
3131 circuit_breaker: The circuit breaker instance to monitor
32- expected_state: The expected state (STATE_OPEN, STATE_CLOSED, STATE_HALF_OPEN)
32+ expected_states: List of acceptable states
33+ (STATE_OPEN, STATE_CLOSED, STATE_HALF_OPEN)
3334 timeout: Maximum time to wait in seconds
34-
35+
3536 Returns:
3637 True if state reached, False if timeout
37- """
38- start = time .time ()
39- while time .time () - start < timeout :
40- if circuit_breaker .current_state == expected_state :
41- return True
42- time .sleep (0.1 ) # Poll every 100ms
43- return False
4438
39+ Examples:
40+ # Single state - pass list with one element
41+ wait_for_circuit_state(cb, [STATE_OPEN])
4542
46- def wait_for_circuit_state_multiple (circuit_breaker , expected_states , timeout = 5 ):
47- """
48- Wait for circuit breaker to reach one of multiple expected states.
49-
50- Args:
51- circuit_breaker: The circuit breaker instance to monitor
52- expected_states: List of acceptable states
53- timeout: Maximum time to wait in seconds
54-
55- Returns:
56- True if any state reached, False if timeout
43+ # Multiple states
44+ wait_for_circuit_state(cb, [STATE_CLOSED, STATE_HALF_OPEN])
5745 """
5846 start = time .time ()
5947 while time .time () - start < timeout :
6048 if circuit_breaker .current_state in expected_states :
6149 return True
62- time .sleep (0.1 )
50+ time .sleep (0.1 ) # Poll every 100ms
6351 return False
6452
6553
@@ -105,12 +93,17 @@ def create_mock_response(self, status_code):
10593 }.get (status_code , b"Response" )
10694 return response
10795
108- @pytest .mark .parametrize ("status_code,should_trigger" , [
109- (429 , True ),
110- (503 , True ),
111- (500 , False ),
112- ])
113- def test_circuit_breaker_triggers_for_rate_limit_codes (self , status_code , should_trigger ):
96+ @pytest .mark .parametrize (
97+ "status_code,should_trigger" ,
98+ [
99+ (429 , True ),
100+ (503 , True ),
101+ (500 , False ),
102+ ],
103+ )
104+ def test_circuit_breaker_triggers_for_rate_limit_codes (
105+ self , status_code , should_trigger
106+ ):
114107 """
115108 Verify circuit breaker opens for rate-limit codes (429/503) but not others (500).
116109 """
@@ -148,9 +141,10 @@ def mock_request(*args, **kwargs):
148141
149142 if should_trigger :
150143 # Wait for circuit to open (async telemetry may take time)
151- assert wait_for_circuit_state (circuit_breaker , STATE_OPEN , timeout = 5 ), \
152- f"Circuit didn't open within 5s, state: { circuit_breaker .current_state } "
153-
144+ assert wait_for_circuit_state (
145+ circuit_breaker , [STATE_OPEN ], timeout = 5
146+ ), f"Circuit didn't open within 5s, state: { circuit_breaker .current_state } "
147+
154148 # Circuit should be OPEN after rate-limit failures
155149 assert circuit_breaker .current_state == STATE_OPEN
156150 assert circuit_breaker .fail_counter >= 2 # At least 2 failures
@@ -242,8 +236,9 @@ def mock_conditional_request(*args, **kwargs):
242236 time .sleep (2 )
243237
244238 # Wait for circuit to open
245- assert wait_for_circuit_state (circuit_breaker , STATE_OPEN , timeout = 5 ), \
246- f"Circuit didn't open, state: { circuit_breaker .current_state } "
239+ assert wait_for_circuit_state (
240+ circuit_breaker , [STATE_OPEN ], timeout = 5
241+ ), f"Circuit didn't open, state: { circuit_breaker .current_state } "
247242
248243 # Wait for reset timeout (5 seconds in test)
249244 time .sleep (6 )
@@ -256,7 +251,7 @@ def mock_conditional_request(*args, **kwargs):
256251 cursor .fetchone ()
257252
258253 # Wait for circuit to start recovering
259- assert wait_for_circuit_state_multiple (
254+ assert wait_for_circuit_state (
260255 circuit_breaker , [STATE_HALF_OPEN , STATE_CLOSED ], timeout = 5
261256 ), f"Circuit didn't recover, state: { circuit_breaker .current_state } "
262257
@@ -265,7 +260,7 @@ def mock_conditional_request(*args, **kwargs):
265260 cursor .fetchone ()
266261
267262 # Wait for full recovery
268- assert wait_for_circuit_state_multiple (
263+ assert wait_for_circuit_state (
269264 circuit_breaker , [STATE_CLOSED , STATE_HALF_OPEN ], timeout = 5
270265 ), f"Circuit didn't fully recover, state: { circuit_breaker .current_state } "
271266
0 commit comments