test: make context-failure regressions deterministic and simplify alarm log handling
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
1ca9e60c98
commit
75406af970
@@ -101,22 +101,29 @@ class DuplicateInFlightIntentStore:
|
||||
raise AssertionError("finalize must not be called for duplicate_in_flight")
|
||||
|
||||
|
||||
class ContextFailingSlotRepository(InMemorySlotRepository):
|
||||
"""Raise only on the N+1th fetch_slot to simulate post-finalize lookup failure."""
|
||||
class PostFinalizeContextFailingSlotRepository(InMemorySlotRepository):
|
||||
"""Raise fetch_slot only after explicitly armed by finalize."""
|
||||
|
||||
def __init__(self, *, fail_on_fetch_call_no=None):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._fetch_calls = 0
|
||||
self._fail_on_fetch_call_no = fail_on_fetch_call_no
|
||||
self._raise_on_fetch = False
|
||||
|
||||
def fetch_slot(self, slot_id):
|
||||
self._fetch_calls += 1
|
||||
if self._fail_on_fetch_call_no == self._fetch_calls:
|
||||
if self._raise_on_fetch:
|
||||
raise RuntimeError("context lookup failed")
|
||||
return super().fetch_slot(slot_id)
|
||||
|
||||
def fail_on_next_fetch(self):
|
||||
self._fail_on_fetch_call_no = self._fetch_calls + 1
|
||||
|
||||
class FinalizeArmingIntentStore(InMemoryIntentStore):
|
||||
"""Arm repo fetch failure immediately after finalize persistence."""
|
||||
|
||||
def __init__(self, repo):
|
||||
super().__init__()
|
||||
self._repo = repo
|
||||
|
||||
def finalize(self, intent_id, status, slot_id, reason):
|
||||
super().finalize(intent_id, status, slot_id, reason)
|
||||
self._repo._raise_on_fetch = True
|
||||
|
||||
|
||||
def _make_holding_slot(repo, svc, instance_key="default", portfolio_id="pf-A", symbol="005930", qty=10):
|
||||
@@ -531,10 +538,10 @@ def test_reconcile_warned_alarm_finalize_failure_and_publish_failure_are_isolate
|
||||
|
||||
|
||||
def test_reconcile_warned_buy_context_lookup_failure_does_not_change_response():
|
||||
repo = ContextFailingSlotRepository(fail_on_fetch_call_no=2)
|
||||
repo = PostFinalizeContextFailingSlotRepository()
|
||||
svc = SlotService(repo)
|
||||
warn_store = InMemoryReconcileWarningStore()
|
||||
intent_store = InMemoryIntentStore()
|
||||
intent_store = FinalizeArmingIntentStore(repo)
|
||||
alarms = RecordingAlarmEmitter()
|
||||
repo.reconcile_universe("default", {"pf-A": "005930"})
|
||||
slot = repo.find_slot_by_portfolio("default", "pf-A")
|
||||
@@ -558,13 +565,12 @@ def test_reconcile_warned_buy_context_lookup_failure_does_not_change_response():
|
||||
|
||||
|
||||
def test_reconcile_warned_sell_context_lookup_failure_does_not_change_response():
|
||||
repo = ContextFailingSlotRepository()
|
||||
repo = PostFinalizeContextFailingSlotRepository()
|
||||
svc = SlotService(repo)
|
||||
warn_store = InMemoryReconcileWarningStore()
|
||||
intent_store = InMemoryIntentStore()
|
||||
intent_store = FinalizeArmingIntentStore(repo)
|
||||
alarms = RecordingAlarmEmitter()
|
||||
slot = _make_holding_slot(repo, svc, qty=10, portfolio_id="pf-A", symbol="005930")
|
||||
repo._fail_on_fetch_call_no = repo._fetch_calls + 2
|
||||
warn_store.set_warned(str(slot.slot_id), portfolio_id="pf-A", case_code="C")
|
||||
intent_svc = IntentService(
|
||||
svc, repo, intent_store, instance_key="default", warn_store=warn_store, alarm_emitter=alarms
|
||||
|
||||
@@ -17,7 +17,6 @@ where no broker connection exists. In that case publish_alarm() logs and skips.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from trex_core.adapters.messaging.topology import alarm_routing_key
|
||||
@@ -91,11 +90,9 @@ class AlarmEmitter:
|
||||
code, title,
|
||||
)
|
||||
return False
|
||||
except Exception: # noqa: BLE001 — alarm must never crash the caller
|
||||
exc = sys.exc_info()[1]
|
||||
exc_name = type(exc).__name__ if exc is not None else "Exception"
|
||||
except Exception as exc: # noqa: BLE001 — alarm must never crash the caller
|
||||
_log.error(
|
||||
"alarm publish failed: code=%s title=%s error_type=%s",
|
||||
code, title, exc_name,
|
||||
code, title, type(exc).__name__,
|
||||
)
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user