Files
trex-core/docs/batches/bat-047_20260619_event-publisher-connection-reliability/implementation.md
T
genichinandClaude Opus 4.8 d182464b7a feat(messaging): OPS-005 이벤트 발행 연결 신뢰성 (BAT-047)
발행 전용 연결의 idle heartbeat 사망 후 첫 발행 유실 결함 제거.
- REQ-091 발행 재시도 + 강제 재연결(_force_reconnect, is_open 불신)
- REQ-092 idle keepalive(execution-loop 단일스레드 틱, process_data_events time_limit=0)
- REQ-093 DLQ 가시성 + emit 실패 ERROR 경보(구조화 로그, dcy-029 재사용)
- REQ-094 baseline 문서 정합(runtime-flows/operations/project-structure)

독립 opus QC PASS-WITH-NOTES → 시정 2건(ruff F401, AC-3 프로덕션 경로) 완료.
554 passed/47 skipped/회귀 0/ruff clean. NFR-1 wire 무회귀(interface-contract diff 0).
BAT-047 release-candidate, REQ-091~094 Implemented. dcy-031. M2 트랙B.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-06-19 22:39:43 +09:00

3.7 KiB

BAT-047 Implementation

  • Status: completed
  • Batch: BAT-047

Plan Summary

REQ-091~094 구현. 변경은 발행 경로에 국소화하고 wire 계약·consume/RPC 경로 불변 유지.

  1. rabbitmq.py — _connect 타임아웃 파라미터화, _force_reconnect 신규, keepalive_tick 신규, publish_event 재시도 로직, _publish_dlq ERROR 격상.
  2. application/messaging.py — MessagingTransport 포트에 keepalive_tick() 추가 (no-op default).
  3. adapters/messaging/in_memory.py — keepalive_tick() no-op 구현.
  4. runtime/daemon.py — _make_event_emitter WARNING→ERROR 격상, _execution_loop keepalive 틱 삽입.
  5. tests/adapters/messaging/test_publish_reliability.py — 신규 테스트 17건.
  6. docs/ — baseline 문서 정합 (REQ-094).

Changed Files

코드

  • trex_core/adapters/messaging/rabbitmq.py
    • _connect(connect_timeout=None): 파라미터화, 기본값 self._timeout 유지
    • _force_reconnect(): 신규 — close() + _connect(connect_timeout=2.0) (NFR-2 5초 블록 예산)
    • keepalive_tick(): 신규 — process_data_events(time_limit=0), 비소유 스레드 호출 시 잠재적 오남용 방어(소유 스레드에서만 호출 규칙은 daemon.py에서 보장)
    • publish_event(): 1차 실패 시 _force_reconnect + 재시도, UnroutableError는 재시도 없이 DLQ
    • _do_basic_publish(): 신규 내부 헬퍼 — basic_publish 로직 추출(DRY)
    • _publish_dlq(): WARNING → ERROR 2건(DLQ 유입 + DLQ 재발행 실패)
  • trex_core/application/messaging.py
    • MessagingTransport 프로토콜에 keepalive_tick() -> None 추가
  • trex_core/adapters/messaging/in_memory.py
    • InMemoryTransport.keepalive_tick() no-op 구현
  • trex_core/runtime/daemon.py
    • _make_event_emitter: WARNING → ERROR, routing key + slot_id + strategy_id 포함
    • _execution_loop: self.event_publisher.keepalive_tick() 각 틱 시작 시 호출

테스트

  • tests/adapters/messaging/test_publish_reliability.py (신규, 17 테스트)

문서 (REQ-094)

  • docs/runtime-flows.md — 슬롯 이벤트 발행/구독, 데몬 lifecycle 갱신
  • docs/project-structure.md — messaging.py, rabbitmq.py 기술 갱신
  • docs/operations.md — DLQ 가시성/경보 섹션 신규

Execution Log

  1. rabbitmq.py — _connect, _force_reconnect, keepalive_tick, publish_event, _do_basic_publish, _publish_dlq 수정/추가.
  2. application/messaging.py — keepalive_tick 포트 메서드 추가.
  3. in_memory.py — no-op 추가.
  4. daemon.py — _make_event_emitter + _execution_loop 수정.
  5. 신규 테스트 17건 작성.
  6. python3 -m pytest tests/adapters/messaging/test_publish_reliability.py -v → 17 passed.
  7. python3 -m pytest tests/ --ignore=...rabbitmq_transport... --ignore=...rabbitmq_intent_e2e... -q → 554 passed, 40 skipped (기존 537 + 신규 17, 회귀 0).
  8. baseline 문서 정합 (runtime-flows, project-structure, operations).

Validation (중간)

  • 신규 17건 전부 통과.
  • 기존 537 passed → 554 passed (신규 17 추가). 회귀 0.
  • TREX_RABBITMQ_TEST_URL 필요 통합 테스트 2건(test_rabbitmq_transport.py, test_rabbitmq_intent_e2e.py): 환경 없어 skip — 기존과 동일.

Remaining Risks

  • R-3(Medium): at-least-once 재시도 — 중복 이벤트 발행 가능. OQ-2(orb/tsl 소비자 멱등성)는 delivery 검증으로 추적. trex-core 범위 밖.
  • R-live: 실제 pika 연결 환경(TREX_RABBITMQ_TEST_URL)에서의 keepalive/재연결 동작은 통합 테스트로만 검증 가능 — CI 환경 없어 미검증. unit mock 기반으로 logic을 검증했으나 실제 broker half-open 재현은 운영 환경 배포 후 확인 필요.