@@ -1396,6 +1396,7 @@ def check_connection(username: str, password: str, wait_for_connection: bool = F
13961396 max_retries = CONNECTION_MAX_RETRIES
13971397 sleep_interval = CONNECTION_RETRY_SLEEP
13981398 restart_attempts = 0
1399+ proactive_restart_attempts = 0
13991400 client = None
14001401
14011402 def probe_status () -> Optional [str ]:
@@ -1464,6 +1465,23 @@ def probe_status() -> Optional[str]:
14641465 counter += 1
14651466 if counter % 10 == 0 :
14661467 logger .info ("Waiting for ThetaTerminal connection (attempt %s/%s)." , counter , max_retries )
1468+ if counter and counter % 15 == 0 :
1469+ if proactive_restart_attempts >= MAX_RESTART_ATTEMPTS :
1470+ logger .error (
1471+ "ThetaTerminal still disconnected after %s attempts; restart limit reached." ,
1472+ counter ,
1473+ )
1474+ break
1475+ proactive_restart_attempts += 1
1476+ logger .warning (
1477+ "ThetaTerminal disconnected for %s consecutive probes; restarting (proactive #%s)." ,
1478+ counter ,
1479+ proactive_restart_attempts ,
1480+ )
1481+ client = start_theta_data_client (username = username , password = password )
1482+ time .sleep (max (BOOT_GRACE_PERIOD , sleep_interval ))
1483+ counter = 0
1484+ continue
14671485 time .sleep (sleep_interval )
14681486
14691487 if not connected and counter >= max_retries :
@@ -1476,6 +1494,8 @@ def get_request(url: str, headers: dict, querystring: dict, username: str, passw
14761494 all_responses = []
14771495 next_page_url = None
14781496 page_count = 0
1497+ consecutive_disconnects = 0
1498+ restart_budget = 3
14791499
14801500 # Lightweight liveness probe before issuing the request
14811501 check_connection (username = username , password = password , wait_for_connection = False )
@@ -1498,25 +1518,51 @@ def get_request(url: str, headers: dict, querystring: dict, username: str, passw
14981518 )
14991519
15001520 response = requests .get (request_url , headers = headers , params = request_params )
1521+ status_code = response .status_code
15011522 # Status code 472 means "No data" - this is valid, return None
1502- if response . status_code == 472 :
1523+ if status_code == 472 :
15031524 logger .warning (f"No data available for request: { response .text [:200 ]} " )
15041525 # DEBUG-LOG: API response - no data
15051526 logger .debug (
15061527 "[THETA][DEBUG][API][RESPONSE] status=472 result=NO_DATA"
15071528 )
1529+ consecutive_disconnects = 0
15081530 return None
1531+ elif status_code == 474 :
1532+ consecutive_disconnects += 1
1533+ logger .warning ("Received 474 from Theta Data (attempt %s): %s" , counter + 1 , response .text [:200 ])
1534+ if consecutive_disconnects >= 2 :
1535+ if restart_budget <= 0 :
1536+ logger .error ("Restart budget exhausted after repeated 474 responses." )
1537+ raise ValueError ("Cannot connect to Theta Data!" )
1538+ logger .warning (
1539+ "Restarting ThetaTerminal after %s consecutive 474 responses (restart budget remaining %s)." ,
1540+ consecutive_disconnects ,
1541+ restart_budget - 1 ,
1542+ )
1543+ restart_budget -= 1
1544+ start_theta_data_client (username = username , password = password )
1545+ check_connection (username = username , password = password , wait_for_connection = True )
1546+ time .sleep (max (BOOT_GRACE_PERIOD , CONNECTION_RETRY_SLEEP ))
1547+ consecutive_disconnects = 0
1548+ counter = 0
1549+ else :
1550+ check_connection (username = username , password = password , wait_for_connection = True )
1551+ time .sleep (CONNECTION_RETRY_SLEEP )
1552+ continue
15091553 # If status code is not 200, then we are not connected
1510- elif response . status_code != 200 :
1511- logger .warning (f"Non-200 status code { response . status_code } : { response .text [:200 ]} " )
1554+ elif status_code != 200 :
1555+ logger .warning (f"Non-200 status code { status_code } : { response .text [:200 ]} " )
15121556 # DEBUG-LOG: API response - error
15131557 logger .debug (
15141558 "[THETA][DEBUG][API][RESPONSE] status=%d result=ERROR" ,
1515- response . status_code
1559+ status_code
15161560 )
15171561 check_connection (username = username , password = password , wait_for_connection = True )
1562+ consecutive_disconnects = 0
15181563 else :
15191564 json_resp = response .json ()
1565+ consecutive_disconnects = 0
15201566
15211567 # DEBUG-LOG: API response - success
15221568 response_rows = len (json_resp .get ("response" , [])) if isinstance (json_resp .get ("response" ), list ) else 0
0 commit comments