Files
trex-core/docs/releases/rel-009_20260625_event-reliability-fill-guard-alarm-runbook.md
T

14 KiB

REL-009: OPS-005 이벤트 발행 신뢰성 + 체결가 가드 + 알람 emitter + 무데이터 런북 (M2 통합 릴리즈)

  • Status: confirmed
  • Profile: app-service
  • Included Batch: BAT-047, BAT-048, BAT-049

Scope

  • Included:

    • BAT-047 (dcy-031 / OPS-005): 이벤트 발행 연결 신뢰성 — publish_event 1회 실패 시 강제 재연결+재시도(REQ-091), 발행 전용 연결 idle keepalive process_data_events 틱(REQ-092), DLQ 유입/emit 최종 실패 ERROR 경보(REQ-093), baseline 문서 정합(REQ-094). M1 프로덕션(9e35467) 미반영 결함 해소 — idle 60초 후 첫 전이 이벤트 유실 제거.
    • BAT-048 (dcy-032): 체결가 0/None 백필 가드 + WARN 로깅 — _on_filled/_on_partial_cancel에서 avg_price=0/None 시 지정가 백필(REQ-095), 백필/unresolvable WARN 로그(reason 필드 포함)(REQ-096), 알람 능력 스파이크 산출물·후보 A/B/C 분석(REQ-097 — 알람 실제 구현은 dcy-033 이월). 슬롯 avg_price·원장 cost basis의 무경고 0오염 제거.
    • BAT-049 (dcy-033): 알람 시스템 1단계 — 알람 envelope 표준 JSON 스키마·trex.alerts(topic, durable=True) exchange 신규 선언(REQ-098/099), application AlarmEmitter + CRITICAL code 8종 배선(REQ-100), runtime-flows.md 알람 발신 흐름 기술(REQ-101). 기존 wire 계약(exchange/큐/라우팅) 불변 — 가산·격리 추가.
    • dcy-017 후속 운영자 런북 (docs-only, 2026-06-22): 지속 무데이터/죽은 종목 위생 절차 docs/operations.md §7 신규 기재 — pause/resume 시맨틱 검증·Step 1~3b 절차·고아 방지 순서 명시. 코드 변경 없음.
  • Excluded:

    • 이벤트 발행 영속 outbox(옵션 C) — M3 후보
    • consumer(orb/tsl) idempotency 구현 — OQ-2(각 repo 추적)
    • 알람 수신·텔레그램 전달(trex-notifier) — 배포 의존성(아래 참조)
    • INFO·WARN 알람 code 배선 — M3 이후
    • 과거 0 기록 원장/슬롯 소급 정정
  • Scope Note:

    • BAT-047은 origin/main(b2165ea) 기준 이미 푸시됨 — 이번 배포는 현재 local main HEAD(5bdd720) 전체를 싣는 체크아웃 갱신이다.
    • dcy-017 런북은 별도 Discovery/Batch를 생성하지 않은 docs-only 패치(커밋 5bdd720)이며 코드 변경 없음.

배포 의존성 및 순서 (필독)

trex-notifier 선행 조건

trex.alerts exchange 선언은 데몬 기동 시 declare_topology()가 자동 수행한다. 알람 발행(mandatory=False)은 notifier 미연결 시 silent drop — core 기동 자체는 notifier 없이도 안전하다.

그러나 알람 수신·텔레그램 전달(trex-notifier)이 연결되지 않은 상태에서 CRITICAL 이벤트가 발생하면 알람이 유실(drop)된다. 따라서:

  1. trex-notifier 배포·바인딩 선행: trex.alerts에 바인딩된 notifier 큐가 없으면 알람이 RabbitMQ에서 곧바로 drop된다. trex-notifier를 먼저 띄우고 trex.alerts 바인딩을 확인한 뒤 trex-core를 재시작한다.
  2. trex-core는 orb/tsl 이벤트 발행 경로의 중심이다. trex-core 재시작 시간 동안 orb/tsl이 AMQP를 통해 trex-core로 전송하는 slot 의도(intent)가 일시 지연될 수 있다. 가능하면 거래 비활성 시간대(장 외)에 배포한다.

배포 순서 요약

1. (장 외 시간) trex-notifier 배포 및 trex.alerts 바인딩 확인
2. trex-core main 갱신 → pip install -e . (의존성 변경 없음 — 확인 후 생략 가능) → 데몬 재시작
3. (선택) trex-orb-v1 / trex-tsl-v1 재시작 — 코드 변경 없어 강제 아님, keepalive/재연결은 core 측 개선임

Rollout Plan

  1. 배포 전 준비

    • 전체 테스트 green 확인: python3 -m pytest -q → 608 passed, 47 skipped (현재 HEAD 5bdd720 기준 검증 완료).
    • ruff clean 확인: ruff check trex_core/ tests/ → All checks passed!.
    • BAT-047/048/049 verification.md 상태: BAT-047 approved, BAT-048 verified(팀장 confirm 완료), BAT-049 release-candidate(팀장 실인프라 e2e 포함 confirmed).
    • DB 스키마 변경 없음 — 신규 마이그레이션 없음. apply_migrations 기존 001~015 idempotent 재실행.
    • trex-notifier 배포·trex.alerts 바인딩 완료 확인 (선행 조건).
  2. 배포 실행 (운영 환경 — bare .venv, instance_key=trex-admin-daily-trading)

    • git pull (또는 git fetch && git checkout 5bdd720) — local main을 프로덕션 체크아웃 경로에 반영.
    • 의존성 변경 여부 확인: git diff 9e35467 HEAD -- pyproject.toml → 변경 없으면 pip install -e . 생략 가능.
    • trex-core-daemon 재시작 (기존 PID 종료 후 신규 기동).
    • 기동 로그에서 trex.alerts exchange 선언 성공(declare_topology 완료) 확인.
  3. 배포 후 검증 (아래 Verification Checklist 참조)

Rollback Plan

  • 트리거: 데몬 기동 실패 / trex.alerts exchange 선언 오류 / 이벤트 발행 경로 이상(재시도 루프 과다·DLQ 급증) / 체결 처리 이상(백필 WARN 폭증·슬롯 PENDING 고착) / 기존 서비스 연동 장애.
  • 절차:
    1. 데몬 정지.
    2. 이전 커밋 체크아웃: git checkout 9e35467 (REL-008 배포본 = M1 프로덕션 라인).
    3. trex-core-daemon 재기동.
    4. DB 스키마 변경 없음 — 마이그레이션 없으므로 롤백 시 데이터 무손실.
    5. trex.alerts exchange는 롤백 후에도 RabbitMQ에 남아있으나 발행자가 없어 무해. 필요 시 관리 UI에서 수동 삭제 가능(비필수).
  • 부분 완화: AlarmEmitter는 best-effort 삼킴 패턴으로 기동·발행 경로가 알람 실패에 비차단. 알람 발행 오류만 발생하면 롤백 대신 notifier 재바인딩을 먼저 시도한다.

Verification Checklist

배포 전

  • 전체 테스트 green: python3 -m pytest -q → 608 passed, 47 skipped, 0 fail (HEAD 5bdd720).
  • ruff clean: ruff check trex_core/ tests/ → All checks passed!.
  • BAT-047 verification: Status=approved (confirmed 2026-06-19).
  • BAT-048 verification: Status=verified (confirmed 2026-06-21).
  • BAT-049 verification: Status=release-candidate (팀장 실인프라 e2e confirmed 2026-06-21).
  • trex-notifier 배포·trex.alerts 바인딩 완료 (선행).
  • DB 스키마 변경 없음 재확인 (마이그레이션 없음).
  • docs/interface-contract.md 변경 범위 확인: BAT-049 trex.alerts 섹션 추가(기존 섹션 diff=0).
  • OPS-005 배포갭 인지: 현재 프로덕션 M1(9e35467)은 idle keepalive·재시도 미포함 — 이번 배포가 해소.

배포 후

  • OPS-005 해소 확인 (BAT-047 핵심): 장 시작 후 orb/tsl → core idle 60초 이상 경과 후 첫 slot 전이 이벤트가 정상 수신되는지 확인. ConnectionReset / StreamLostError 로그 무재발 확인. slot_filled / slot_entered 이벤트가 orb/tsl에 도달하는지 확인.
  • 데몬 기동 로그: declare_topology 정상 완료, trex.alerts exchange 선언 포함, ERROR/CRITICAL/Traceback 0.
  • keepalive 동작 확인: 기동 후 60초 경과 시 keepalive_tick 호출 로그(또는 무오류) 확인.
  • 알람 발행 경로 확인: CRITICAL 이벤트 발생 시 alarm.critical.trex-core routing key로 trex.alerts에 발행되고 trex-notifier가 텔레그램 전달하는지 확인 (e2e 경로).
  • 체결 처리: 정상 체결 시 avg_price 백필 WARN 미발생 확인. KIS avg_price 이상 케이스 발생 시 WARN 로그 필드(slot_id/symbol/backfill_price/reason) 확인.
  • AMQP wire 무회귀: trex.events, trex.intent.req, trex.slots.req, trex.control.req exchange/큐/라우팅 형식 불변 확인. orb/tsl 연동 장애 없음 확인.
  • trex-core report 정상 동작 (REL-008 기능 회귀 없음).

AMQP Wire 계약 무회귀 체크포인트

이번 릴리즈의 AMQP 변경 범위는 아래로 한정된다. orb/tsl 연동에 영향 없음을 명시한다.

항목 변경 여부 근거
trex.events exchange/토폴로지 불변 BAT-047 Out of Scope 명시, verification NFR-1 PASS
trex.intent.req 큐/라우팅 불변 BAT-047/048/049 모두 불변 확인
trex.slots.req 큐/스키마 불변 BAT-047/048/049 모두 불변 확인
trex.control.req 큐 불변 변경 없음
슬롯 이벤트 페이로드 스키마 불변 BAT-047 wire 무회귀 PASS
trex.alerts exchange 신규 추가 (가산·격리) BAT-049 REQ-099. 기존 exchange/큐에 무영향. mandatory=False — unroutable silent drop
docs/interface-contract.md trex.alerts 섹션 신규 (기존 섹션 diff=0) BAT-049 REQ-098 AC-3 PASS

Release Execution Evidence

  • Release Status Transition Target: released

Deployment Facts

  • Executed At:
    • 2026-06-25
  • Completed At:
  • Environment:
    • 운영 (/root/release 또는 해당 경로, instance_key=trex-admin-daily-trading, 실거래 KIS 계좌 91254), bare .venv
  • Operator:
    • 사장님
  • Revision or Artifact:
    • 9e35467(REL-008 M1 현재 프로덕션) → 34700f3 on 5bdd720(REL-009 배포본).
    • BAT-047: d182464, BAT-048: f1b649c, BAT-049: d4c5fcb, dcy-017 런북: 5bdd720.
  • Commands or Procedure:
    • git pull (또는 체크아웃 5bdd720) → pip install -e . (의존성 변경 시) → trex-core-daemon 재시작.
    • 마이그레이션: 기동 시 apply_migrations 자동 실행 (001~015 idempotent, 신규 없음).

Profile-Specific Checks

  • app-service:
    • Health Endpoint:
      • N/A (데몬은 HTTP 표면 없음). "ready" = 워커 스레드 + RabbitMQ 토폴로지 선언(trex.alerts 포함) 완료, 로그 ERROR/Traceback 0.
    • Startup Log Fields:
      • PASS. declare_topology 완료 로그, trex.alerts exchange 선언 확인(AMQP 5연결 정상), ERROR/CRITICAL/Traceback 0.
    • Request Log Fields:
      • PASS. slot_filled 이벤트 정상 발행 확인. OPS-005 ConnectionReset 무재발 확인. 12:02 sell_filled 집행 정상.
    • Smoke or Manual Verification:
      • PASS. idle keepalive 동작, slot_filled 이벤트 발행 경로 정상. trex.alerts exchange 선언 5연결 확인.

Rollback Outcome

  • Rollback Required:
    • No
  • Rollback Trigger:
    • none
  • Rollback Action:
    • none

Release Decision Evidence

  • Released Decision:
    • released
  • Rationale:
    • 2026-06-25 배포 PASS. 2026-06-26 첫 거래일 OPS-005(RabbitMQ ConnectionReset) 무재발(0건) 확인. slot_filled 이벤트 정상 발행. 12:02 sell_filled 집행 정상. AMQP 5연결 정상. 롤백 없음.
  • Recorded By:
    • 팀장
  • Recorded At:
    • 2026-06-26

Feedback Handoff

M2 배포 + 첫 거래일 환류 (2026-06-26)

  • Observation Summary:

    • 배포: 2026-06-25 PASS (34700f3 on 5bdd720, PID 849009). trex.alerts 선언, AMQP 5연결 정상.
    • 첫 거래일 검증: OPS-005(RabbitMQ ConnectionReset) 무재발(0건) — 해소 확인. slot_filled 이벤트 정상 발행. 12:02 sell_filled 집행 정상.
    • 신규 발견: slot_filled 이벤트 NO_ROUTE → DLQ 유입 확인. 라우팅키 slot_filled_*._.{symbol}(strategy_id 자리 _). 원인: _emit_event(execution.py:345/398)가 자산중심 슬롯(dcy-020, portfolio_id 단위, strategy_id 미보유) 기반 발행 → orb/tsl의 trex.events.strategy.{strategy_id} 바인딩과 불일치. 체결이벤트 채널(REQ-003) 미전달(전략은 slots RPC 폴링 주력이라 비치명적이나 채널 깨짐+DLQ 누적).
  • Discovery Input:

    • ★ slot_filled NO_ROUTE / fill→strategy 라우팅 재설계 (trex-core/P1/M3): 자산중심 모델에서 fill 이벤트를 strategy 바인딩으로 전달하는 라우팅 매핑이 없음. _emit_event의 라우팅키 생성 로직이 strategy_id를 참조하지 않아 orb/tsl의 trex.events.strategy.{strategy_id} 바인딩과 불일치 → NO_ROUTE → DLQ 누적. 자산중심 슬롯(portfolio_id 단위)에서 fill→strategy 라우팅 재설계 필요. 보드 등록됨. 교차 영향 사안: wire 계약(exchange/라우팅키/바인딩) 변경 — 팀장 검토 후 Discovery 개시 필요.
    • 이벤트 발행 영속 outbox: BAT-047 Out of Scope으로 이월됨(M3 후보). at-least-once 중복 이벤트 소비자 멱등성도 함께 추적.
    • 실 broker 통합 CI: half-open/idle 60초/broker 재시작 시나리오는 현재 mock unit으로만 검증. TREX_RABBITMQ_TEST_URL 포함 통합 환경 구성(M3 후보).
    • INFO·WARN 알람 code 배선: CRITICAL 8종 이후 후속 범위(dcy-033 범위 경계 밖, M3 후보).
  • REQ Input:

    • none
  • Change Request Input:

    • none

미해결 / 잔여 위험

항목 수준 설명 해소 방안
trex-notifier 미선행 시 알람 유실 Medium notifier 없이 core 배포 시 CRITICAL 알람 silent drop 배포 순서 준수: notifier → core
지정가 백필 추정치 오차 Medium BAT-048 R-1: 실제 체결가 ≠ 지정가 가능. reason=avg_price_backfill WARN으로 추적 가능 운영자 WARN 발생 시 operations.md §5 절차 참조
fill_price_unresolvable 슬롯 고착 Low BAT-048 R-2: limit_price=None 시 PENDING 고착 → watchdog 탐지 필요 기존 stale_pending watchdog 동작, 운영자 개입
half-open/idle 실인프라 검증 Low BAT-047 mock unit 검증 — 실 broker 통합 skip (환경 미구성) 배포 후 OPS-005 재발 모니터링으로 실증, M3 통합 CI
NFR-2 publish 블록 최악 케이스 Low BAT-047: 1차 실패 시 원 socket_timeout(5.0s) 초과 가능 배포 후 모니터링, 필요 시 후속 REQ(publish timeout 강화)
BAT-049 통합(실 RabbitMQ) 3건 Low declare_topology/mandatory=False/기존 topology 불변은 팀장 실인프라 e2e에서 확인됨(2026-06-21) 배포 후 Smoke 체크포인트로 재확인