fix: converge broker failures without retry

This commit is contained in:
Hermes Agent
2026-08-19 11:29:26 +09:00
parent be98965f2c
commit 15aeae6930
15 changed files with 181 additions and 211 deletions
+2 -34
View File
@@ -30,32 +30,6 @@ from trex_core.domain.slot import (
_log = logging.getLogger(__name__)
# ---- sell-reject retryability (issue #27 / REQ-007 CHG-20260615-01) ---------
# core-owned reason -> retryable mapping for the rejected SellIntent response.
# Maintained with the reject vocabulary (intents.py _admit_sell/_dedup) so a new
# reason gets a correct flag without the daemon touching a table. Unrecognized
# reasons default to retryable=True: a stranded stop-loss (held losing position)
# is worse than bounded, observable hammering on a terminal decision.
_SELL_REJECT_RETRYABLE: dict[str, bool] = {
"slot_state_changed": True,
"slot_not_holding:pending_buy": True,
"duplicate_in_flight": True,
"slot_not_found": False,
"slot_not_holding:inactive": False,
"slot_not_holding:pending_sell": False,
"slot_not_holding:error": False,
}
def _sell_reject_retryable(reason: Optional[str]) -> bool:
"""Map a rejected-sell reason to retryable (issue #27). Default True (safety)."""
if reason is None:
return True
# malformed payload: client defect — retrying the same bytes is pointless.
if reason.startswith("bad_request"):
return False
return _SELL_REJECT_RETRYABLE.get(reason, True)
# ---- intent RPC handler -----------------------------------------------------
@@ -117,7 +91,7 @@ def make_intent_rpc_handler(
# dcy-022 / REQ-068: execution policy (optional, backward-compat).
timeout_sec=_opt_int(body.get("timeout_sec")),
slippage_pct=_opt_float(body.get("slippage_pct")),
venue=_opt_str(body.get("venue")) or "AUTO",
venue=_opt_str(body.get("venue")) or "SOR",
)
d = intent_service.submit_buy(buy)
elif intent_type == "sell":
@@ -133,7 +107,7 @@ def make_intent_rpc_handler(
# dcy-022 / REQ-068: execution policy (optional, backward-compat).
timeout_sec=_opt_int(body.get("timeout_sec")),
slippage_pct=_opt_float(body.get("slippage_pct")),
venue=_opt_str(body.get("venue")) or "AUTO",
venue=_opt_str(body.get("venue")) or "SOR",
)
d = intent_service.submit_sell(sell)
else:
@@ -146,9 +120,6 @@ def make_intent_rpc_handler(
"intent_id": intent_id, "status": "rejected",
"slot_id": None, "reason": f"bad_request:{exc}",
}
# issue #27: sell-side malformed payload carries retryable=False.
if intent_type == "sell":
payload["retryable"] = _sell_reject_retryable(payload["reason"])
return RpcResponse(payload=payload)
payload = {
"intent_id": d.intent_id,
@@ -156,9 +127,6 @@ def make_intent_rpc_handler(
"slot_id": (str(d.slot_id) if d.slot_id else None),
"reason": d.reason,
}
# issue #27 / REQ-007 AC-7: additive retryable on rejected sell only.
if intent_type == "sell" and d.status == "rejected":
payload["retryable"] = _sell_reject_retryable(d.reason)
return RpcResponse(payload=payload)
return handler