From 832c85b233ab1613b94d37d42521952319cc18bc Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 13 Jul 2026 08:54:01 +0200 Subject: [PATCH] =?UTF-8?q?dita=5Fv2(bingx=5Fvenue):=20make=20=5Fpublish?= =?UTF-8?q?=5Ftelemetry=20TOTAL=20=E2=80=94=20telemetry=20cannot=20raise?= =?UTF-8?q?=20into=20the=20order=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pre-existing guard covered only publish(). The attribute/coercion block above it (int()/str()/.metadata.get() on intent+order) was UNGUARDED, and kwarg binding happens before the body runs at all — so a signature skew sailed straight past a defence that existed precisely to prevent this, and orphaned 6 live positions. Everything that can raise now lives inside one try. Failures log loud and are swallowed; the order path is never affected. Proven against: exploding plane, poisoned intent coercion (the formerly-unguarded region), and absent plane. ARCHITECTURAL DEBT (raised by HJ, not fixed here): telemetry has no business being called inline on the exec path at all. Correct shape = fire-and-forget enqueue drained by the M6 journal lane. This commit makes it harmless, not absent. Co-Authored-By: Claude Opus 4.8 --- prod/clean_arch/dita_v2/bingx_venue.py | 64 ++++++++++++++++---------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/prod/clean_arch/dita_v2/bingx_venue.py b/prod/clean_arch/dita_v2/bingx_venue.py index 04e5dfc..37f21f2 100644 --- a/prod/clean_arch/dita_v2/bingx_venue.py +++ b/prod/clean_arch/dita_v2/bingx_venue.py @@ -302,29 +302,39 @@ class BingxVenueAdapter(VenueAdapter): client_order_id: str = "", details: dict[str, Any] | None = None, ) -> None: - plane = self._telemetry_plane - publish = getattr(plane, "publish_venue", None) if plane is not None else None - if publish is None: - return - slot_id = 0 - trade_id = "" - asset = "" - side = TradeSide.FLAT - action = "" - intent_id = "" - if intent is not None: - slot_id = int(getattr(intent, "slot_id", 0) or 0) - trade_id = str(getattr(intent, "trade_id", "") or "") - asset = str(getattr(intent, "asset", "") or "") - side = getattr(intent, "side", TradeSide.FLAT) - action = str(getattr(intent, "action", "") or "") - intent_id = str(getattr(intent, "intent_id", "") or "") - if order is not None: - slot_id = int(order.metadata.get("slot_id", slot_id) or slot_id) - trade_id = str(order.internal_trade_id or trade_id) - asset = str(order.metadata.get("asset") or asset) - side = order.side or side + # TOTAL: this method cannot raise. It runs INLINE on the order path — + # submit()/submit_async() call it immediately after the venue has already + # accepted the order. An exception escaping here reaches the caller's + # submit guard, which synthesises a REJECTED event and rolls the FSM back + # while the venue keeps the position (orphan; 6 of them on 2026-07-13). + # + # The guard used to cover only publish(), leaving the attribute/coercion + # block below it unprotected — which is how a signature skew orphaned live + # positions past a defence that existed precisely to prevent it. Everything + # that can raise now lives inside the try. Observability never vetoes a fill. try: + plane = self._telemetry_plane + publish = getattr(plane, "publish_venue", None) if plane is not None else None + if publish is None: + return + slot_id = 0 + trade_id = "" + asset = "" + side = TradeSide.FLAT + action = "" + intent_id = "" + if intent is not None: + slot_id = int(getattr(intent, "slot_id", 0) or 0) + trade_id = str(getattr(intent, "trade_id", "") or "") + asset = str(getattr(intent, "asset", "") or "") + side = getattr(intent, "side", TradeSide.FLAT) + action = str(getattr(intent, "action", "") or "") + intent_id = str(getattr(intent, "intent_id", "") or "") + if order is not None: + slot_id = int(order.metadata.get("slot_id", slot_id) or slot_id) + trade_id = str(order.internal_trade_id or trade_id) + asset = str(order.metadata.get("asset") or asset) + side = order.side or side publish( VenueTelemetrySnapshot( phase=phase, @@ -350,8 +360,14 @@ class BingxVenueAdapter(VenueAdapter): details=dict(details or {}), ) ) - except Exception: - pass + except Exception as exc: + import logging as _log + + _log.getLogger(__name__).warning( + "FIX(bingx_venue): telemetry publish failed (phase=%s) — swallowed, " + "order path unaffected: %s", + phase, exc, + ) def _call_backend(self, method_name: str, *args: Any, **kwargs: Any) -> Any: method = getattr(self.backend, method_name, None)