# req-099: trex.alerts AMQP exchange 토폴로지 + 가산·격리 불변식 - Status: Approved - Type: Integration - Priority: High - Owner: trex-core-dev ## Intent - 알람 전달 채널로 전용 `trex.alerts` topic exchange를 선언하고, 토폴로지(exchange 타입·이름·라우팅 규약)와 소비자/발행자 역할을 `docs/interface-contract.md`에 명시한다. - 이 채널은 **가산·격리** 원칙을 따른다: 기존 exchange/큐(trex.events/trex.intent.req/trex.slots.req/trex.control.req 등) 스키마와 동작은 일절 변경하지 않으며, `trex.alerts`는 독립 추가 채널로만 존재한다. - trex-core 데몬이 기동 시 `trex.alerts` exchange를 멱등 선언(declare)하도록 `MessagingTransport.declare_topology()`를 확장한다. ## Requirement - trex-core `MessagingTransport.declare_topology()`는 아래 AMQP 엔티티를 멱등으로 선언해야 한다. - exchange: `trex.alerts`, type=`topic`, durable=`True` - 모듈(trex-core/orb/tsl/kdh)은 기존 RabbitMQ 연결에서 `trex.alerts` exchange로 알람 envelope를 발행한다. routing key는 `alarm.{severity}.{source}` (예: `alarm.critical.trex-core`). - trex-notifier는 `trex.alerts` exchange의 단일 소비자로서, 바인딩 패턴 `alarm.#`(또는 severity별 `alarm.critical.#`)으로 자신의 큐를 바인딩해 수신한다(notifier 큐 선언·바인딩은 trex-notifier 소유). - trex-core가 알람을 발행(publish)할 때: `mandatory=False`(소비자 없어도 unroutable 에러 없이 조용히 drop) — notifier 다운이 core 발행을 막지 않도록 한다. - 기존 AMQP 토폴로지(trex.events topic exchange, trex.events.dlq, trex.intent.req/trex.slots.req/trex.control.req 큐, trex.direct/trex.broadcast exchange)는 수정하지 않는다. - `docs/interface-contract.md`의 알람 채널 섹션(REQ-098)에 exchange 타입·이름·라우팅 규약·발행자/소비자 역할을 명시한다. ## Acceptance Criteria 1. Given trex-core 데몬이 기동될 때, When `declare_topology()`가 호출되면, Then `trex.alerts`(topic, durable=True) exchange가 멱등 선언되어야 한다(이미 존재하면 no-op). 2. Given `trex.alerts` exchange가 선언됐을 때, When 기존 exchange/큐 목록(trex.events, trex.events.dlq, trex.intent.req, trex.slots.req, trex.control.req, trex.direct, trex.broadcast)을 확인하면, Then 이들 엔티티의 type·durable·인수(arguments)가 변경되지 않아야 한다. 3. Given trex-core가 알람을 발행할 때, When notifier 큐가 바인딩되지 않아 unroutable인 경우, Then `mandatory=False`이므로 발행이 조용히 성공하고(silent drop) TransportUnavailableError 또는 UnroutableError가 발생하지 않아야 한다. 4. Given `docs/interface-contract.md` 알람 채널 섹션(REQ-098)이 추가됐을 때, When 토폴로지 명세를 확인하면, Then exchange 이름(`trex.alerts`), 타입(`topic`), durable 여부, routing key 형식(`alarm.{severity}.{source}`), 발행자(모든 모듈), 단일 소비자(trex-notifier)가 명시되어야 한다. 5. Given `declare_topology()`가 `trex.alerts` exchange를 포함하도록 수정됐을 때, When 기존 topology 선언 관련 단위 테스트를 실행하면, Then 기존 테스트가 모두 통과하고 신규 exchange 선언에 대한 단위 테스트가 추가되어야 한다. 6. Given trex-core가 알람을 발행할 때, When publishing 시 transport가 `disconnected` 또는 `reconnecting` 상태이면, Then 알람 발행은 silently skip되어야 하며 core 본업(슬롯 전이·매매 집행)을 블로킹하지 않아야 한다(best-effort 비차단 — REQ-100 연계). ## Impacted Area - Docs: `docs/interface-contract.md` — 알람 채널 섹션 토폴로지 내용 추가(REQ-098 섹션 확장) - Modules: - `trex_core/adapters/broker/rabbitmq.py` 또는 topology 선언 담당 모듈 — `trex.alerts` exchange 선언 추가 - `trex_core/application/` messaging 관련 모듈 — 알람 발행 헬퍼(REQ-100 연계) - Tests: - `tests/adapters/` 또는 `tests/application/` — `declare_topology` 단위 테스트에 `trex.alerts` exchange 선언 assertion 추가 - 기존 topology 선언 테스트 회귀 확인 ## Notes - `trex.alerts` exchange는 `trex.events`와 별개로 선언된다. 둘은 다른 exchange 이름을 가지므로 바인딩·라우팅이 교차하지 않는다. - notifier가 없는 환경(개발/테스트)에서도 core는 정상 동작해야 한다. `mandatory=False` + best-effort 발행이 이를 보장한다. - RabbitMQ topology attribute 충돌(기존 큐·exchange와 durable/type 불일치) 시 PRECONDITION_FAILED — 이는 기존 엔티티 수정 금지 불변식을 위반한 경우로, 이 REQ의 AC-2로 사전 방지된다. - orb/tsl/kdh는 자신의 RabbitMQ 연결에서 `trex.alerts` exchange로 직접 발행한다. core는 이들의 연결을 관여하지 않는다(각 모듈 REQ 범위). - trex-notifier의 큐 이름·바인딩 패턴·prefetch 등은 trex-notifier repo REQ에서 정의한다. - dcy-033 NFR-1(가산·격리) 대응 — AC-2가 직접 검증 기준. - dcy-033 성공기준 S-3(기존 wire 계약 무회귀) 연계. ## Change Log ### CHG-20260621-01 - Date: 2026-06-21 - Author: trex-core-dev #### Change Summary - REQ-099 신규 생성(Proposed). dcy-033 FR-2 대응: `trex.alerts` AMQP exchange 토폴로지 + 가산·격리 불변식. #### Intent - `trex.alerts` 전용 exchange를 선언하고, 기존 AMQP 계약을 건드리지 않으면서 알람 채널을 가산적으로 추가한다. #### Acceptance Criteria Delta - Added: AC-1~6 (신규 생성) - Updated: (없음) - Removed: (없음) #### Impacted Area Delta - Docs: - `docs/interface-contract.md` 알람 채널 섹션(REQ-098)에 토폴로지 내용 추가 - Modules: - topology 선언 담당 모듈에 `trex.alerts` exchange 추가 - Tests: - topology 선언 단위 테스트 신규 assertion 추가 #### Delivery Trace Delta - Batches: (미정, M2 이후 큐잉) - Releases: (미정) #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: REQ-098/100/101과 단일 batch 편성 예정 #### Validation Plan - RabbitMQ mock/stub에서 `declare_topology()` 호출 후 `trex.alerts` exchange 선언 assertion - 기존 exchange/큐 선언 테스트 회귀 통과 확인 - `mandatory=False` 발행 시 unroutable 상황에서 예외 없음 확인(단위 테스트)