Files
trex-core/docs/srs/Exception/req-092_publish-idle-keepalive.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

6.5 KiB
Raw Blame History

req-092: 발행 전용 연결 idle keepalive (서버 측 heartbeat 사망 예방)

  • Status: Implemented
  • Type: Exception
  • Priority: High
  • Owner: project maintainers

Intent

  • 발행 전용 RabbitMQ 연결은 consumer 루프(process_data_events 0.2s 틱)와 달리 publish 사이에 I/O가 전혀 없어 heartbeat=30 설정에도 불구하고 ~60초 idle 후 서버가 연결을 종료한다. keepalive로 idle 구간에도 heartbeat I/O가 나가도록 해 서버 측 연결 종료를 사전 예방하고, REQ-091 재시도 경로를 보완하는 2차 방어선을 구성한다.

Requirement

  • 발행 전용 연결에 idle keepalive를 도입해, heartbeat 주기(heartbeat=30) 내에 process_data_events가 최소 1회 이상 호출되도록 보장한다.
  • keepalive는 pika BlockingConnection의 스레드 안전성 제약을 위반하지 않는다. 즉, 발행 전용 연결을 소유한 스레드에서만 keepalive I/O를 실행한다.
  • keepalive의 구체 구현 방식(별도 keepalive 스레드 vs. execution-loop 틱에 삽입)은 draft-batch-design에서 OQ-1 기준으로 확정한다. 본 REQ는 "발행 연결 소유 스레드 내 I/O 보장" 정책만 확정하며, 구현 위치는 설계 단계 결정으로 추적한다.
  • 이 변경은 adapters/messaging/rabbitmq.py 및 필요 최소 범위의 runtime/daemon.py에 국소화하며, consume/RPC 경로·슬롯 도메인·broker 집행 로직을 건드리지 않는다(NFR-3 흡수).
  • M1 운영 배포본(9e35467)의 wire 계약은 불변이다(NFR-1 흡수).

Acceptance Criteria

  1. Given idle 구간이 heartbeat × 2(60초) 이상 지속될 때, When keepalive가 활성화되어 있으면, Then 발행 전용 연결이 서버에 의해 종료되지 않고 살아 있는 상태를 유지한다(S-1 1차 방어선).
  2. Given keepalive 구현이 별도 스레드를 사용하거나 루프 틱에 삽입되는 경우, When 해당 I/O가 실행될 때, Then 발행 전용 연결을 소유한 스레드에서만 process_data_events가 호출되며, 다른 스레드가 동일 연결에 직접 I/O를 호출하지 않는다(pika 스레드 안전성 불변식).
  3. Given keepalive가 동작 중이고 동시에 발행이 발생할 때, When 두 작업이 겹치면, Then 연결 상태 손상 또는 예외 없이 정상 완료된다(pika 스레드 안전성 불변식 보강).
  4. Given keepalive 설정이 적용된 상태에서, When execution-loop의 매도 트리거 처리 타이밍을 확인하면, Then keepalive 틱이 execution-loop를 과도하게 블록하지 않는다(NFR-2 흡수 — 허용 블록 시간 상한은 design 단계 확정).
  5. Given consumer 스레드(intent/slots/control RPC)를 확인할 때, When keepalive 변경이 적용된 코드베이스를 검사하면, Then consumer 경로의 동작·큐 바인딩·토폴로지에 변화가 없다(consume/RPC 무회귀, NFR-1).
  6. Given keepalive 구현 방식이 설계 단계에서 확정된 후, When batch design 문서를 확인하면, Then OQ-1(keepalive 실행 위치·스레드 소유 모델)이 명시적으로 결정되어 있다(OQ-1 종료 조건 추적).

Impacted Area

  • Docs: docs/runtime-flows.md(데몬 lifecycle 흐름 — keepalive 틱 추가 기재, REQ-094에서 갱신). docs/project-structure.md(keepalive 컴포넌트 추가 시 반영, REQ-094에서 갱신).
  • Modules: trex_core/adapters/messaging/rabbitmq.py(keepalive 메커니즘 추가). trex_core/runtime/daemon.py(keepalive 연동, 최소 변경). 슬롯 도메인/broker 집행/consume 경로 불변.
  • Tests: tests/adapters/messaging/ — idle 60초 후 연결 생존 확인(AC-1), 스레드 소유 검증(AC-2), 동시 발행+keepalive 충돌 없음(AC-3), execution-loop 블록 상한(AC-4), consume 경로 회귀(AC-5).

Notes

  • 출처: dcy-031 FR-2(A), NFR-1, NFR-2, NFR-3, R-2(keepalive pika 스레드 충돌), S-1.
  • OQ-1(keepalive 구현 위치 — 별도 스레드 vs. execution-loop 삽입): 설계 단계 결정. AC-6에서 추적. 종료 조건: batch design 문서에 명시되면 Answered.
  • R-2(pika 스레드 비안전성): 이 위험은 AC-2/AC-3으로 검증하며, 설계 단계(OQ-1)에서 구현 방식을 확정해 완화한다.
  • keepalive는 REQ-091 재시도와 독립 계층이다. keepalive는 1차 예방(연결 사망 방지), REQ-091은 2차 복구(사망 후 재연결+재시도). 두 REQ는 함께 배치될 예정이지만 독립 구현·독립 검증 가능하다.

Change Log

CHG-20260619-01

  • Date: 2026-06-19
  • Author: trex-core-dev

Change Summary

  • dcy-031 FR-2(A) 로부터 최초 생성(Proposed). NFR-1·NFR-2·NFR-3 흡수. R-2(pika 스레드) OQ-1 인계. S-1 연결.

Intent

  • 발행 전용 연결 idle keepalive 정책을 backlog에 정규화하고, OQ-1 설계 결정 추적을 AC-6으로 고정한다.

Acceptance Criteria Delta

  • Added:
    • AC-1: idle 60초 후 연결 생존
    • AC-2: 발행 소유 스레드에서만 I/O (스레드 안전성)
    • AC-3: 동시 발행+keepalive 충돌 없음
    • AC-4: execution-loop 블록 상한
    • AC-5: consume/RPC 경로 무회귀
    • AC-6: OQ-1 종료 조건 추적
  • Updated: 없음
  • Removed: 없음

Impacted Area Delta

  • Docs:
    • docs/runtime-flows.md, docs/project-structure.md
  • Modules:
    • trex_core/adapters/messaging/rabbitmq.py, trex_core/runtime/daemon.py
  • Tests:
    • tests/adapters/messaging/ (idle/스레드/동시성/블록/회귀)

Delivery Trace Delta

  • Batches:
    • none (draft-req 단계, batch 미편성)
  • Releases:
    • none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req 후 REQ-091과 함께 단일 batch 편성 예정

Validation Plan

  • time-freeze 또는 sleep mock으로 idle 구간을 시뮬레이션한 후 연결 생존 + 스레드 안전성 검증. 기존 messaging 회귀 스위트 전체 통과 확인.

CHG-20260619-02

  • Date: 2026-06-19
  • Author: 팀장 (confirm-req)

Change Summary

  • Proposed → Approved. 필수 필드 충족, AC 구체, source dcy-031(confirmed, Open OQ 0) 정합. OQ-1(keepalive 실행 위치)은 AC-6에서 design 인계 추적 — 승인 비차단.

Intent

  • delivery input 승인. keepalive 구현 위치(별도 스레드 vs execution-loop 틱)는 draft-batch-design에서 확정.

Acceptance Criteria Delta

  • Added: 없음
  • Updated: 없음
  • Removed: 없음

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: REQ-091과 함께 단일 batch 편성 예정