# 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 편성 예정