feat(alarm): trex-core 알람 emitter + trex.alerts exchange (dcy-033 BAT-049, Implemented)

AlarmEmitter(application, best-effort 비차단)+trex.alerts topic exchange 가산·격리+8 CRITICAL code 배선. 608 passed, opus QC PASS, 팀장 e2e(텔레그램 HTTP200) 통과. REQ-098~101 Implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
2026-06-21 19:25:55 +09:00
co-authored by Claude Opus 4.8
parent b2165eac25
commit d4c5fcbba1
29 changed files with 1195 additions and 47 deletions
@@ -1,4 +1,4 @@
"""InMemoryTransport stub tests (REQ-022 AC-1 + REQ-024 degrade)."""
"""InMemoryTransport stub tests (REQ-022 AC-1 + REQ-024 degrade + REQ-099 alarm)."""
from __future__ import annotations
import threading
@@ -86,3 +86,23 @@ def test_publish_event_with_no_subscriber_routes_to_dlq():
dlq = t.dlq_messages()
assert len(dlq) == 1
assert dlq[0][0] == "slot_filled_buy.A.005930"
# dcy-033 / REQ-099: alarm channel tests
def test_publish_alarm_event_records_event():
"""Alarm event is recorded in _alarm_events when transport is available."""
t = InMemoryTransport()
t.publish_alarm_event("alarm.critical.trex-core", {"code": "kill_switch_fired"})
alarms = t.alarm_events()
assert len(alarms) == 1
rk, payload = alarms[0]
assert rk == "alarm.critical.trex-core"
assert payload["code"] == "kill_switch_fired"
def test_publish_alarm_event_raises_when_unavailable():
"""Alarm publish raises TransportUnavailableError when transport is down."""
t = InMemoryTransport()
t.set_available(False)
with pytest.raises(TransportUnavailableError):
t.publish_alarm_event("alarm.critical.trex-core", {"code": "test"})
+12 -1
View File
@@ -1,4 +1,4 @@
"""Topology constants + routing key builders (REQ-021)."""
"""Topology constants + routing key builders (REQ-021, REQ-099)."""
from __future__ import annotations
from trex_core.adapters.messaging import topology
@@ -12,6 +12,17 @@ def test_topology_constants():
assert not hasattr(topology, "SNAPSHOT_REQ_QUEUE")
# dcy-033 / REQ-099: trex.alerts exchange constant + routing key builder
def test_alerts_exchange_constant():
assert topology.ALERTS_EXCHANGE == "trex.alerts"
def test_alarm_routing_key_format():
assert topology.alarm_routing_key("critical", "trex-core") == "alarm.critical.trex-core"
assert topology.alarm_routing_key("warn", "trex-orb-v1") == "alarm.warn.trex-orb-v1"
assert topology.alarm_routing_key("info", "kis-data-hub") == "alarm.info.kis-data-hub"
def test_event_routing_key_format():
assert topology.event_routing_key("slot_filled_buy", "A", "005930") == \
"slot_filled_buy.A.005930"