4646 CommitRetryEngine ,
4747 _extract_error_code ,
4848 _is_recognized_rejection ,
49+ _is_schema_valid_commit_success ,
4950)
5051
5152logger = logging .getLogger (__name__ )
@@ -763,11 +764,23 @@ def _handle_commit(
763764 commit_body : dict [str , Any ],
764765 event_fallback_body : dict [str , Any ],
765766 ) -> None :
767+ self ._retry_engine .persist_pending (
768+ reservation_id , commit_body , event_fallback_body
769+ )
766770 try :
767771 logger .debug ("Committing: id=%s" , reservation_id )
768772 response = self ._client .commit_reservation (reservation_id , commit_body )
769- if response .is_success :
773+ if _is_schema_valid_commit_success (response ):
774+ self ._retry_engine .discard_pending (reservation_id )
770775 logger .info ("Commit successful: id=%s" , reservation_id )
776+ elif response .is_success :
777+ logger .warning (
778+ "Commit returned ambiguous protocol-invalid 2xx; scheduling same-key retry: "
779+ "id=%s, status=%d" ,
780+ reservation_id ,
781+ response .status ,
782+ )
783+ self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
771784 elif response .is_transport_error or response .is_server_error :
772785 logger .warning ("Commit failed (retryable): id=%s, status=%d" , reservation_id , response .status )
773786 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
@@ -804,10 +817,13 @@ def _handle_commit(
804817 )
805818 self ._retry_engine .schedule_event (reservation_id , event_fallback_body )
806819 elif error_code == "RESERVATION_FINALIZED" :
820+ self ._retry_engine .discard_pending (reservation_id )
807821 logger .warning ("Reservation already finalized: id=%s" , reservation_id )
808822 elif error_code == "IDEMPOTENCY_MISMATCH" :
823+ self ._retry_engine .discard_pending (reservation_id )
809824 logger .warning ("Commit idempotency mismatch (not releasing): id=%s" , reservation_id )
810825 elif response .is_client_error and _is_recognized_rejection (error_code ):
826+ self ._retry_engine .discard_pending (reservation_id )
811827 self ._handle_release (reservation_id , f"commit_rejected_{ error_code } " )
812828 elif response .is_client_error :
813829 # Codeless or forward-compat-unknown 4xx: neither release
@@ -820,7 +836,12 @@ def _handle_commit(
820836 )
821837 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
822838 else :
823- logger .warning ("Unrecognized commit response: id=%s, response=%s" , reservation_id , response )
839+ logger .warning (
840+ "Unrecognized commit response; scheduling same-key retry: id=%s, response=%s" ,
841+ reservation_id ,
842+ response ,
843+ )
844+ self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
824845 except Exception :
825846 logger .exception ("Failed to commit: id=%s" , reservation_id )
826847 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
@@ -1047,16 +1068,24 @@ def heartbeat_loop() -> None:
10471068 return
10481069 delay_ms = nxt
10491070 except Exception :
1050- logger .warning ("Heartbeat extend error: id=%s" , reservation_id , exc_info = True )
10511071 if authoritative :
10521072 nxt = sched .on_transient_failure (_now_mono_ms ())
10531073 if nxt is None :
10541074 logger .warning (
1055- "Heartbeat stopping: no safe recovery window remains: id=%s" ,
1075+ "Heartbeat extend transport error; stopping because no safe recovery "
1076+ "window remains: id=%s" ,
10561077 reservation_id ,
1078+ exc_info = True ,
10571079 )
10581080 return
10591081 delay_ms = nxt
1082+ logger .warning (
1083+ "Heartbeat extend transport error; retrying with the same idempotency key "
1084+ "in %.0fms: id=%s" ,
1085+ delay_ms ,
1086+ reservation_id ,
1087+ exc_info = True ,
1088+ )
10601089
10611090 t = threading .Thread (target = heartbeat_loop , daemon = True , name = f"cycles-heartbeat-{ reservation_id [:12 ]} " )
10621091 t .start ()
@@ -1189,10 +1218,22 @@ async def _handle_commit(
11891218 commit_body : dict [str , Any ],
11901219 event_fallback_body : dict [str , Any ],
11911220 ) -> None :
1221+ self ._retry_engine .persist_pending (
1222+ reservation_id , commit_body , event_fallback_body
1223+ )
11921224 try :
11931225 response = await self ._client .commit_reservation (reservation_id , commit_body )
1194- if response .is_success :
1226+ if _is_schema_valid_commit_success (response ):
1227+ self ._retry_engine .discard_pending (reservation_id )
11951228 logger .info ("Commit successful: id=%s" , reservation_id )
1229+ elif response .is_success :
1230+ logger .warning (
1231+ "Commit returned ambiguous protocol-invalid 2xx; scheduling same-key retry: "
1232+ "id=%s, status=%d" ,
1233+ reservation_id ,
1234+ response .status ,
1235+ )
1236+ self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
11961237 elif response .is_transport_error or response .is_server_error :
11971238 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
11981239 else :
@@ -1228,10 +1269,13 @@ async def _handle_commit(
12281269 )
12291270 self ._retry_engine .schedule_event (reservation_id , event_fallback_body )
12301271 elif error_code == "RESERVATION_FINALIZED" :
1272+ self ._retry_engine .discard_pending (reservation_id )
12311273 logger .warning ("Reservation already finalized: id=%s" , reservation_id )
12321274 elif error_code == "IDEMPOTENCY_MISMATCH" :
1275+ self ._retry_engine .discard_pending (reservation_id )
12331276 logger .warning ("Commit idempotency mismatch (not releasing): id=%s" , reservation_id )
12341277 elif response .is_client_error and _is_recognized_rejection (error_code ):
1278+ self ._retry_engine .discard_pending (reservation_id )
12351279 await self ._handle_release (reservation_id , f"commit_rejected_{ error_code } " )
12361280 elif response .is_client_error :
12371281 # Codeless or forward-compat-unknown 4xx: neither release
@@ -1244,7 +1288,12 @@ async def _handle_commit(
12441288 )
12451289 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
12461290 else :
1247- logger .warning ("Unrecognized commit response: id=%s, response=%s" , reservation_id , response )
1291+ logger .warning (
1292+ "Unrecognized commit response; scheduling same-key retry: id=%s, response=%s" ,
1293+ reservation_id ,
1294+ response ,
1295+ )
1296+ self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
12481297 except Exception :
12491298 logger .exception ("Failed to commit: id=%s" , reservation_id )
12501299 self ._retry_engine .schedule (reservation_id , commit_body , event_fallback_body )
@@ -1457,16 +1506,24 @@ async def heartbeat_loop() -> None:
14571506 return
14581507 delay_ms = nxt
14591508 except Exception :
1460- logger .warning ("Heartbeat extend error: id=%s" , reservation_id , exc_info = True )
14611509 if authoritative :
14621510 nxt = sched .on_transient_failure (_now_mono_ms ())
14631511 if nxt is None :
14641512 logger .warning (
1465- "Heartbeat stopping: no safe recovery window remains: id=%s" ,
1513+ "Heartbeat extend transport error; stopping because no safe "
1514+ "recovery window remains: id=%s" ,
14661515 reservation_id ,
1516+ exc_info = True ,
14671517 )
14681518 return
14691519 delay_ms = nxt
1520+ logger .warning (
1521+ "Heartbeat extend transport error; retrying with the same idempotency "
1522+ "key in %.0fms: id=%s" ,
1523+ delay_ms ,
1524+ reservation_id ,
1525+ exc_info = True ,
1526+ )
14701527 except asyncio .CancelledError :
14711528 return
14721529
0 commit comments