Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
14 KiB
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_event1회 실패 시 강제 재연결+재시도(REQ-091), 발행 전용 연결 idle keepaliveprocess_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), applicationAlarmEmitter+ 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 절차·고아 방지 순서 명시. 코드 변경 없음.
- BAT-047 (dcy-031 / OPS-005): 이벤트 발행 연결 신뢰성 —
-
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)이며 코드 변경 없음.
- BAT-047은 origin/main(
배포 의존성 및 순서 (필독)
trex-notifier 선행 조건
trex.alerts exchange 선언은 데몬 기동 시 declare_topology()가 자동 수행한다. 알람 발행(mandatory=False)은 notifier 미연결 시 silent drop — core 기동 자체는 notifier 없이도 안전하다.
그러나 알람 수신·텔레그램 전달(trex-notifier)이 연결되지 않은 상태에서 CRITICAL 이벤트가 발생하면 알람이 유실(drop)된다. 따라서:
- trex-notifier 배포·바인딩 선행:
trex.alerts에 바인딩된 notifier 큐가 없으면 알람이 RabbitMQ에서 곧바로 drop된다. trex-notifier를 먼저 띄우고trex.alerts바인딩을 확인한 뒤 trex-core를 재시작한다. - 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
-
배포 전 준비
- 전체 테스트 green 확인:
python3 -m pytest -q→ 608 passed, 47 skipped (현재 HEAD5bdd720기준 검증 완료). - 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바인딩 완료 확인 (선행 조건).
- 전체 테스트 green 확인:
-
배포 실행 (운영 환경 — 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.alertsexchange 선언 성공(declare_topology완료) 확인.
-
배포 후 검증 (아래 Verification Checklist 참조)
Rollback Plan
- 트리거: 데몬 기동 실패 /
trex.alertsexchange 선언 오류 / 이벤트 발행 경로 이상(재시도 루프 과다·DLQ 급증) / 체결 처리 이상(백필 WARN 폭증·슬롯 PENDING 고착) / 기존 서비스 연동 장애. - 절차:
- 데몬 정지.
- 이전 커밋 체크아웃:
git checkout 9e35467(REL-008 배포본 = M1 프로덕션 라인). trex-core-daemon재기동.- DB 스키마 변경 없음 — 마이그레이션 없으므로 롤백 시 데이터 무손실.
trex.alertsexchange는 롤백 후에도 RabbitMQ에 남아있으나 발행자가 없어 무해. 필요 시 관리 UI에서 수동 삭제 가능(비필수).
- 부분 완화:
AlarmEmitter는 best-effort 삼킴 패턴으로 기동·발행 경로가 알람 실패에 비차단. 알람 발행 오류만 발생하면 롤백 대신 notifier 재바인딩을 먼저 시도한다.
Verification Checklist
배포 전
- 전체 테스트 green:
python3 -m pytest -q→ 608 passed, 47 skipped, 0 fail (HEAD5bdd720). - 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-049trex.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.alertsexchange 선언 포함, ERROR/CRITICAL/Traceback 0. - keepalive 동작 확인: 기동 후 60초 경과 시
keepalive_tick호출 로그(또는 무오류) 확인. - 알람 발행 경로 확인: CRITICAL 이벤트 발생 시
alarm.critical.trex-corerouting 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.reqexchange/큐/라우팅 형식 불변 확인. 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 현재 프로덕션) →34700f3on5bdd720(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.
- N/A (데몬은 HTTP 표면 없음). "ready" = 워커 스레드 + RabbitMQ 토폴로지 선언(
- Startup Log Fields:
- PASS.
declare_topology완료 로그,trex.alertsexchange 선언 확인(AMQP 5연결 정상), ERROR/CRITICAL/Traceback 0.
- PASS.
- Request Log Fields:
- PASS.
slot_filled이벤트 정상 발행 확인. OPS-005 ConnectionReset 무재발 확인. 12:02 sell_filled 집행 정상.
- PASS.
- Smoke or Manual Verification:
- PASS. idle keepalive 동작,
slot_filled이벤트 발행 경로 정상.trex.alertsexchange 선언 5연결 확인.
- PASS. idle keepalive 동작,
- Health Endpoint:
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 (
34700f3on5bdd720, 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 누적).
- 배포: 2026-06-25 PASS (
-
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 후보).
- ★ slot_filled NO_ROUTE / fill→strategy 라우팅 재설계 (trex-core/P1/M3): 자산중심 모델에서 fill 이벤트를 strategy 바인딩으로 전달하는 라우팅 매핑이 없음.
-
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 체크포인트로 재확인 |