feat: add messaging transport rollout
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# BAT-007 Design
|
||||
|
||||
- Status: draft
|
||||
- Batch: BAT-007
|
||||
|
||||
## Architecture Summary
|
||||
- 기존 FastAPI/uvicorn HTTP `/v1` 어댑터를 제거하고, trex-core ↔ 전략 모듈 통신을 **RabbitMQ(AMQP) 기반 메시지 transport** 로 전환한다. **application** 에 `MessagingTransport` Protocol 을 두고, **adapters/messaging** 에 `RabbitMQTransport`(`pika` 동기) 와 `InMemoryTransport`(stub) 구현체를, **runtime** 에 sync+thread daemon(consumer/execution/ledger 스레드 + 이벤트 publisher) 구성을 둔다. 토폴로지는 3 패턴(스냅샷 RPC + intent admission RPC + 이벤트 topic) 이며, intent 는 슬롯 Postgres durable commit 후 ack + correlation_id dedup 으로 effectively-once 효과를 낸다. broker 장애 시 어댑터의 connection 상태가 application 레이어로 노출되어 신규 매매를 보수적으로 중단한다(버퍼링 0). HTTP 표면은 `healthz` 포함 0 으로 떨어지고 liveness 는 프로세스 감독이 담당한다.
|
||||
|
||||
## Changed Areas
|
||||
- Docs: interface-contract(메시지 계약 + 어댑터 신선도 노출, HTTP `/v1` 제거), runtime-flows(스냅샷 RPC / intent RPC / 이벤트 발행·구독 / degrade 분기 / 스레드 구성 / HTTP 흐름 제거), project-structure(adapters/messaging 신설, adapters/api 제거, runtime/daemon 의 스레드 구성과 의존성 변경).
|
||||
- Modules:
|
||||
- application: 신규 `messaging.py`(`MessagingTransport` Protocol + RPC 요청/응답 DTO + 이벤트 DTO). 기존 `intents.py`/(dcy-005 스냅샷 서비스 자리) 는 transport-무관 호출 인자만 받는다.
|
||||
- adapters/messaging: 신규 패키지. `topology.py`(exchange/queue/binding/routing-key 상수 + 매핑 헬퍼), `in_memory.py`(결정론 stub), `rabbitmq.py`(pika BlockingConnection 기반 publish/subscribe/RPC, 스레드별 channel, 재연결 백오프).
|
||||
- adapters/api: **제거** (`app.py`, `schemas.py`, `__init__.py`).
|
||||
- runtime: `config.py` 에 `RabbitMQConfig(url, timeout)` 추가, `TREX_RABBITMQ_URL` 로딩, `TREX_API_HOST`/`TREX_API_PORT` 폐기. `daemon.py` 에서 uvicorn import/실행 제거, FastAPI base 제거, intent RPC consumer 스레드 + snapshot RPC consumer 스레드 추가, 기존 execution/ledger 스레드 유지, graceful shutdown 에 connection close 포함.
|
||||
- persistence: 변경 없음 (intent_log 를 dedup 게이트로 재사용; 단, RabbitMQ consumer 전용 dedup 컬럼이 필요하면 design 결정 1 참조).
|
||||
- pyproject: `pika>=1.3` 추가, `fastapi`/`uvicorn` 제거 (httpx 는 ledger 어댑터가 유지).
|
||||
- Interfaces: `MessagingTransport.publish_event(routing_key, payload, mandatory=True)`, `MessagingTransport.consume_rpc(queue, handler)`, `MessagingTransport.call_rpc(queue, payload, timeout)`, 그리고 토폴로지 상수 + routing-key 빌더.
|
||||
|
||||
## Key Decisions
|
||||
1. **dedup 게이트 = intent_log 재사용(dcy-003/REQ-007 멱등 게이트 직접 활용)**. RabbitMQ intent consumer 는 `correlation_id`(= intent 멱등키, dcy-003 패턴)를 `IntentStore.try_insert`(application port) 의 `intent_id` 로 그대로 사용해 단일 dedup 진실원을 유지한다. consumer 전용 dedup table 은 두지 않는다 — at-least-once 재전달 시 두 번째 호출은 `try_insert==False` 로 끝나 슬롯 전이 0, 첫 결과를 그대로 response 로 회신한다. (장점: 새 스키마 0, 기존 멱등 가드 직접 활용. 단점: intent admission RPC 외 다른 RPC 가 늘면 별도 dedup 전략 필요 — 본 batch 범위에서는 intent + read-only snapshot 만 있어 충분.)
|
||||
2. **ack-after-commit 시퀀스**: intent consumer 는 (a) `IntentService.submit_buy/sell` 호출 → (b) Postgres durable commit 안에서 `intent_log` row 와 슬롯 전이가 함께 atomically commit → (c) reply-to 큐로 admission 응답 publish → (d) 메시지 manual ack. (b)와 (c) 사이 크래시는 재전달 시 (1) 의 dedup 으로 재실행되지 않고, (c)와 (d) 사이 크래시는 재전달 시 같은 응답을 다시 보내고 ack — 동일 `correlation_id` 응답은 호출자가 dedup. publisher confirms 로 reply publish 의 broker 수락을 확인.
|
||||
3. **단일 consumer + prefetch=1**: intent RPC consumer 는 단일 스레드 + `basic_qos(prefetch_count=1)` 로 FIFO 보장(불변식 A 단일 writer 와 정합). snapshot RPC consumer 는 read-only 이므로 prefetch>1 허용 가능하지만 본 batch 는 단일 + prefetch=1 로 일관성 우선.
|
||||
4. **이벤트 페이로드 = 현재 상태 + 단조 시퀀스(슬롯 `updated_at` 또는 별도 version 컬럼)**. delta 가 아니라 last-wins 가능한 스냅샷을 운반해 순서 보증 불요. 미수신/중복은 스냅샷 RPC reconcile 로 보정. `daily_slot.updated_at` 을 시퀀스로 사용(이미 존재, 새 컬럼 0).
|
||||
5. **publisher confirms + DLQ**: 이벤트 publisher 는 `confirm_delivery()` 모드 + `basic_publish(mandatory=True)`. 발행 거부(NACK) 또는 unroutable 은 별도 `trex.events.dlq` 큐로 라우팅, last_error 로그. intent RPC reply publish 도 동일.
|
||||
6. **per-strategy durable queue + TTL/max-length**: 전략별 이벤트 queue 는 durable, queue 인자 `x-message-ttl=3600000`(1h) + `x-max-length=10000` + `x-overflow=drop-head`(drop-oldest). 초과/만료는 스냅샷 RPC reconcile 로 회복.
|
||||
7. **재연결 백오프 상태 머신**: `connected → disconnected(트리거: socket error/heartbeat timeout) → reconnecting(백오프 1s,2s,4s,8s,...,30s cap) → connected`. 재연결 성공 후 토폴로지 재선언 + consumer rebind 책임은 어댑터 내부. application 레이어는 `transport.health()` 로 enum 조회.
|
||||
8. **스레드별 channel + add_callback_threadsafe**: pika `BlockingConnection` 은 thread-safe 가 아니므로 (a) 각 consumer 스레드는 자기 connection+channel 을 소유하고 (b) execution/ledger 스레드의 이벤트 발행은 publisher 스레드 channel 의 `add_callback_threadsafe` 로 enqueue 한다. 또는 별도 publisher worker 스레드 도입 — design 검토 후 단순화를 위해 publisher worker 스레드 1개 + queue 기반 cross-thread enqueue 채택.
|
||||
9. **HTTP 표면 0 회귀 가드**: 데몬 lifecycle 테스트가 기동 후 `import trex_core.runtime.daemon` 결과에 `fastapi`/`uvicorn`/`starlette` import 가 없음을 정적 가드로 검사. 추가로 포트 스캔(socket bind 0 검증) 통합 테스트(미가용 시 skip).
|
||||
10. **broker outage = transport.health() != connected 일 때 application 분기**. `IntentService` 진입점은 변경하지 않고, 새 `intent RPC consumer` 가 message 를 수신해도 transport.health() == disconnected 면 reply publish 가 어차피 실패 → 그 경우 메시지 reject(requeue=False) + DLQ 로 격리(전략은 timeout 으로 감지 후 보류). 스냅샷 RPC 도 동일. **버퍼링 금지**: 어댑터에 로컬 outbox 를 두지 않는다(ledger outbox 는 별도 — broker→ledger 가 아니라 core→portfolio-hub 방향이라 영향 없음).
|
||||
|
||||
## Edge Cases
|
||||
- 동일 `correlation_id` 의 intent 메시지가 재전달 → `intent_log.try_insert==False` → 기존 결과 fetch 후 reply, 슬롯 전이 0.
|
||||
- intent commit 직후 reply publish 전 크래시 → 재기동 후 메시지 재전달 → dedup 으로 같은 reply 재전송 → 호출자 dedup. 응답은 같은 `correlation_id`.
|
||||
- pika connection drop 도중 publish/consume → 자동 재연결 백오프 + 채널 재선언 + consumer rebind. 미전송 message 는 broker 가 redeliver 시 dedup.
|
||||
- 전략 queue down 중 trex-core 이벤트 발행 → durable queue 가 catch-up 보관 → 전략 복구 시 수신. TTL/max-length 초과분은 drop-oldest + reconcile.
|
||||
- portfolio-hub 가 아닌 RabbitMQ 가 down → 신규 intent 거부(requeue=False + DLQ) + 스냅샷 RPC timeout → 전략 보류. core 자율 안전 매도(미구현, A-5)는 transport 와 독립 동작 전제.
|
||||
- 전략 모듈 미전환 상태에서 cut-over 시 통신 단절 → release 단계 cut-over 순서(전략 모듈 → trex-core release) 합의 + stub 사전 검증으로 회피(R-2).
|
||||
- HTTP 클라이언트(이전 전략 모듈/외부 tool)가 옛 `POST /v1/intents/buy` 호출 시도 → connection refused (HTTP 표면 0). release notes 에 cut-over 경고 명시.
|
||||
|
||||
## Architecture Impact
|
||||
- both (project-structure + runtime-flows). interface-contract 도 갱신한다(메시지 계약 + HTTP `/v1` 제거).
|
||||
|
||||
## Reference Doc Update Plan
|
||||
- project-structure.md:
|
||||
- 트리에서 `trex_core/adapters/api/` 제거, `trex_core/adapters/messaging/` (`topology.py`, `rabbitmq.py`, `in_memory.py`) 추가.
|
||||
- `trex_core/application/messaging.py` (Protocol + DTO) 추가.
|
||||
- runtime/daemon 의 스레드 구성(intent RPC + snapshot RPC + execution + ledger + publisher worker) 반영.
|
||||
- 의존성 변경(`pika` 추가, `fastapi`/`uvicorn` 제거) 반영.
|
||||
- runtime-flows.md:
|
||||
- 기존 매수/매도 intent HTTP 흐름 제거.
|
||||
- 신규: 스냅샷 RPC 흐름, intent admission RPC 흐름(2단계 시맨틱: admission 동기 + fill 비동기 이벤트), 체결/슬롯 이벤트 발행·구독 흐름(routing key `{event_type}.{strategy_id}.{symbol}` + per-strategy queue), broker degrade 분기 흐름, 재연결 백오프, 스레드 구성.
|
||||
- interface-contract.md:
|
||||
- HTTP `/v1` 섹션 제거.
|
||||
- 신규: 메시지 계약(스냅샷 RPC `trex.snapshot.req` / intent RPC `trex.intent.req` / 이벤트 topic `trex.events`), routing key 형식, RPC payload/response 셰이프, `correlation_id`/reply-to 규약, durable/persistent/ack 정책, publisher confirms + DLQ, TTL/max-length, 어댑터 신선도 상태(`connected/disconnected/reconnecting`) 노출.
|
||||
- data-model.md: 변경 없음 — 이벤트 페이로드는 entity 가 아니라 interface contract 가 담는 편이 자연스러움(REQ-026 Notes 참조).
|
||||
@@ -0,0 +1,66 @@
|
||||
# BAT-007 Implementation
|
||||
|
||||
- Status: complete
|
||||
- Batch: BAT-007
|
||||
|
||||
## Plan Summary
|
||||
- `MessagingTransport` Protocol(application) + `InMemoryTransport` stub + `RabbitMQTransport`(pika 동기) 어댑터를 신설하고, 데몬을 sync+thread 4 스레드(intent RPC consumer + snapshot RPC consumer + execution + ledger) 구조로 재구성했다. intent RPC consumer 는 `IntentService.submit_*` 를 호출해 Postgres durable commit 후 manual ack 하며, `intent_log` 멱등 게이트가 중복 메시지를 흡수한다. ExecutionService 에 event emitter hook 을 더해 fill 전이 직후 `trex.events` 토픽으로 routing key `{event_type}.{strategy_id}.{symbol}` 이벤트를 발행한다(publisher confirms + DLQ). 어댑터의 connection 상태가 application 으로 노출되어 broker outage 시 신규 매매가 보수적으로 중단된다. `adapters/api/` 트리와 `fastapi`/`uvicorn` 의존을 제거하고 baseline 3문서를 정합시켰다.
|
||||
|
||||
## Changed Files
|
||||
- 신규
|
||||
- `trex_core/application/messaging.py` — `MessagingTransport` Protocol, `RpcRequest`/`RpcResponse`, `TransportHealth`/`TransportUnavailableError`/`RpcTimeoutError`.
|
||||
- `trex_core/application/messaging_handlers.py` — `make_intent_rpc_handler` / `make_snapshot_rpc_handler` / `slot_transition_event_payload`.
|
||||
- `trex_core/adapters/messaging/__init__.py`, `topology.py`(상수 + routing key 빌더 + STRATEGY_QUEUE_ARGS), `in_memory.py`(결정론 stub + 가용성 토글 + DLQ 수집), `rabbitmq.py`(pika BlockingConnection + 재연결 백오프 + publisher confirms + manual ack-after-handler).
|
||||
- `tests/adapters/messaging/{__init__,test_topology,test_in_memory_transport,test_rabbitmq_transport,test_rabbitmq_intent_e2e}.py` — REQ-021/022/023 검증 (RabbitMQ 통합 5종 + intent dedup E2E 2종 + stub/토폴로지 11종).
|
||||
- `tests/application/{test_messaging_intent_consumer,test_messaging_snapshot_consumer,test_messaging_event_publisher}.py` — REQ-021/022/023/024 handler·이벤트 흐름·degrade 분기.
|
||||
- `tests/runtime/test_daemon_no_http_surface.py` — REQ-025 HTTP 표면 0 회귀 가드 5종.
|
||||
- 수정
|
||||
- `trex_core/application/execution.py` — `SlotEventEmitter` callback, `ExecutionService.__init__` 에 `event_emitter` 인자 추가, `_on_filled` 에서 transition + ledger enqueue 후 `_emit_event` 호출(publish 실패가 슬롯 전이를 롤백하지 않음).
|
||||
- `trex_core/runtime/config.py` — `RabbitMQConfig` 추가, `TREX_RABBITMQ_URL`/`TREX_RABBITMQ_TIMEOUT` 로딩, `DaemonConfig.host/port` 와 `TREX_API_HOST`/`TREX_API_PORT` 폐기.
|
||||
- `trex_core/runtime/daemon.py` — uvicorn/FastAPI import 제거, `Daemon` 클래스로 4 스레드(execution/ledger/intent-rpc/snapshot-rpc) + 이벤트 publisher transport + `signal` 기반 graceful shutdown + connection close 보장.
|
||||
- `tests/domain/test_domain_import_sweep.py` — 금지 prefix 에 `pika`, `starlette` 추가.
|
||||
- `tests/conftest.py` — 게이트 env 설명을 RabbitMQ/KIS 포함하도록 갱신.
|
||||
- `pyproject.toml` — `pika>=1.3` 추가, `fastapi`/`uvicorn` 제거, `httpx` 를 dev → runtime 의존성으로 이동(ledger 어댑터가 사용).
|
||||
- `.env.example` — `TREX_RABBITMQ_URL`/`TREX_RABBITMQ_TIMEOUT` 추가, `TREX_API_HOST`/`TREX_API_PORT` 제거.
|
||||
- `docs/runtime-flows.md` / `docs/interface-contract.md` / `docs/project-structure.md` — messaging 레이어 반영, HTTP `/v1` 섹션 제거, sync+thread 데몬 + 4 스레드 구성 반영 (REQ-026).
|
||||
- `docs/discovery/dcy-002_…md` — transport supersede 메모 (REQ-025 AC-5 cross-reference).
|
||||
- 제거
|
||||
- `trex_core/adapters/api/` 전체 (`app.py`, `schemas.py`, `__init__.py`).
|
||||
- `tests/adapters/api/` 전체.
|
||||
|
||||
## Execution Log
|
||||
1. baseline 테스트 109 passed / 12 skipped 확인.
|
||||
2. RabbitMQ 가용성 확인: `127.0.0.1:5672` (admin/admin) 으로 `pika.BlockingConnection` 성공.
|
||||
3. `pika>=1.3` 설치, `pyproject.toml` 의 `fastapi`/`uvicorn` 제거.
|
||||
4. REQ-021: `topology.py` 에 토폴로지 상수 + routing key 빌더 + STRATEGY_QUEUE_ARGS(TTL/max-length/drop-head/DLX) 추가.
|
||||
5. REQ-022: `application/messaging.py` (Protocol + DTO + TransportHealth), `adapters/messaging/in_memory.py` (process-local pub/sub + sync RPC + 가용성 토글), `adapters/messaging/rabbitmq.py` (pika BlockingConnection + 재연결 백오프 + publisher confirms + manual ack-after-handler).
|
||||
6. REQ-021/022/023: `application/messaging_handlers.py` 에 intent/snapshot RPC handler + 이벤트 payload builder. intent handler 는 `correlation_id` 를 intent_id 로 재사용해 `intent_log` 멱등 게이트(REQ-007)를 dedup source 로 활용.
|
||||
7. REQ-023: ExecutionService 에 event emitter hook 추가. publisher confirms + DLQ 라우팅은 RabbitMQTransport 가 담당. per-strategy durable queue 는 stub 과 실 broker 둘 다 검증.
|
||||
8. REQ-024: `TransportHealth` enum, `TransportUnavailableError` 즉시-실패, 재연결 백오프(1s..30s cap), stub `set_available(False)` 회귀 가드.
|
||||
9. REQ-025: `adapters/api/` 전체 제거, `runtime/daemon.py` 를 `Daemon` 클래스 + 4 스레드 + signal handler 로 재작성, `runtime/config.py` 의 `host`/`port` 필드 + `TREX_API_HOST/PORT` 로딩 제거. `.env.example` 정리.
|
||||
10. REQ-026: baseline 3문서(runtime-flows / interface-contract / project-structure) messaging 섹션 신설 + HTTP `/v1` 섹션 제거 + sync+thread 4 스레드 구성 반영. dcy-002 헤더에 transport supersede 메모 추가(dcy-005 는 이미 cross-reference 완료).
|
||||
11. 회귀 가드 추가: `tests/runtime/test_daemon_no_http_surface.py` (import 가드 + `adapters/api` 트리 0 + grep fastapi/uvicorn 0 + pyproject 0 + config env 0), `tests/domain/test_domain_import_sweep.py` 에 pika/starlette 금지 prefix.
|
||||
12. 최종 검증: `TREX_RABBITMQ_TEST_URL="amqp://admin:admin@127.0.0.1:5672/"` 로 `pytest -q` → **135 passed / 12 skipped** (PG/KIS 게이트만 skip; 실 RabbitMQ 통합 7건 모두 실행/통과). `ruff check trex_core tests` → All checks passed.
|
||||
|
||||
## Validation
|
||||
- 명령: `TREX_RABBITMQ_TEST_URL="amqp://admin:admin@127.0.0.1:5672/" .venv/bin/python -m pytest -q`
|
||||
- 결과: `135 passed, 12 skipped`.
|
||||
- 명령: `.venv/bin/ruff check trex_core tests`
|
||||
- 결과: `All checks passed!`.
|
||||
- 추가 테스트 ~26개:
|
||||
- 토폴로지: 4종.
|
||||
- InMemoryTransport stub: 5종(routing pattern, RPC dispatch, degrade, DLQ).
|
||||
- RabbitMQTransport 통합: 5종(topology declare 멱등, RPC roundtrip, per-strategy event filter, RPC timeout, close).
|
||||
- RabbitMQ intent E2E: 2종(correlation_id dedup, queue topology PRECONDITION assertion).
|
||||
- intent handler: 7종(admit, dedup, no_idle, sell from holding, bad payload, unknown type, correlation_id fallback).
|
||||
- snapshot handler: 3종(all/open view, strategy filter).
|
||||
- event publisher: 3종(routing + state + sequence, per-strategy filter, publish failure non-blocking).
|
||||
- HTTP-표면-0 가드: 5종(import 가드 + 트리 부재 + grep + pyproject + config env).
|
||||
- RabbitMQ 통합 evidence: 실 broker(127.0.0.1:5672, admin/admin) 로 topology declare, RPC roundtrip, per-strategy queue 필터, RPC timeout, intent E2E dedup 통과.
|
||||
|
||||
## Remaining Risks
|
||||
- core 자율 안전 매도(A-5, REQ-024 Notes) 는 본 batch 미구현. broker 장기 outage 시 열린 포지션 자동 보호 없음 — 운영자 수동 대응 의존. 별도 Discovery 로 트래킹 필요.
|
||||
- 전략 모듈 측 RabbitMQ 클라이언트 전환은 본 batch 범위 외. release 단계에서 cut-over 순서(전략 모듈 → trex-core) 합의 필요 (R-2 / R-5 dcy-006 risk).
|
||||
- pika thread-safety 우회는 스레드별 transport 인스턴스 + 짧은 채널 lifecycle 로 단순화했으나, 장기 부하/연결 누수 가능성은 운영 환경 모니터링으로 보강 필요(본 batch 단위 테스트로는 충분).
|
||||
- snapshot RPC 응답 셰이프는 dcy-005 logical 계약이 아직 REQ 정규화되지 않아 stub-shape 수준(슬롯 목록 + capacity). dcy-005 REQ 확정 시 후속 batch 에서 정합 보강(R-7).
|
||||
- `httpx` 의존을 dev → runtime 으로 이동했다. `portfolio-hub` ledger 어댑터(BAT-006) 가 실제로 사용하므로 적정 위치이며 BAT-006 verification 에 영향 없음.
|
||||
@@ -0,0 +1,32 @@
|
||||
# BAT-007: 전략 모듈 RabbitMQ transport 전환
|
||||
|
||||
- Status: release-candidate
|
||||
- Profile: standard
|
||||
- Source Discovery: dcy-006
|
||||
- Included REQ: REQ-021, REQ-022, REQ-023, REQ-024, REQ-025, REQ-026
|
||||
- Excluded REQ: 없음
|
||||
|
||||
## Summary
|
||||
- dcy-006 transport 슬라이스(trex-core ↔ 전략 모듈 통신을 HTTP `/v1` API 에서 RabbitMQ(AMQP) 로 완전 전환)를 하나의 delivery 단위로 묶는다. 토폴로지/계약(REQ-021) → transport 포트 + RabbitMQ 어댑터(`pika` 동기) + stub + sync+thread daemon 재구성(REQ-022) → delivery 신뢰성(effectively-once, durable, DLQ, publisher confirms, REQ-023) → 가용성 degrade 정책(NFR-3, REQ-024) → HTTP `/v1` API + healthz + adapters/api + fastapi/uvicorn 의존 완전 제거(REQ-025) → baseline 3문서 정합(REQ-026) 까지 한 batch 로 deliver 한다.
|
||||
|
||||
## Scope
|
||||
- In Scope:
|
||||
- REQ-021: 통신 토폴로지(스냅샷 RPC `trex.snapshot.req`, intent admission RPC `trex.intent.req` + RabbitMQ direct reply-to + `correlation_id`, 이벤트 topic exchange `trex.events` + routing key `{event_type}.{strategy_id}.{symbol}`) 와 요청/이벤트 매핑 원칙(view·strategy_id payload, event routing key) 선언.
|
||||
- REQ-022: `trex_core/application/messaging.py` 신규 `MessagingTransport` Protocol, `trex_core/adapters/messaging/{rabbitmq,in_memory}.py`, 데몬을 sync+thread (intent RPC consumer + snapshot RPC consumer + execution/ledger 스레드)로 재구성, pika 자동 재연결 직접 구현. NFR-1 (도메인 순수성) import 스윕 가드 확장.
|
||||
- REQ-023: intent durable+persistent + manual ack-after-commit + dedup(dcy-003 correlation_id), 단일 consumer + prefetch=1 FIFO, 이벤트 durable per-strategy queue + 상태/단조 시퀀스 운반 + last-wins, publisher confirms + DLQ, TTL/max-length drop-oldest + 스냅샷 reconcile.
|
||||
- REQ-024: broker outage 시 버퍼링 금지 + 신규 매매 보수적 중단, 어댑터 connection 신선도(`connected/disconnected/reconnecting`) 노출, core 자율 안전 매도 독립 정책 contract 명시(구현은 별도 Discovery, A-5).
|
||||
- REQ-025: `trex_core/adapters/api/` 전체 제거, `trex_core/runtime/daemon.py` 에서 uvicorn import/실행 제거, `runtime/config.py` 의 `TREX_API_HOST`/`TREX_API_PORT` 폐기, `pyproject.toml` 의 `fastapi`/`uvicorn` 의존 정리, dcy-002·dcy-005 의 HTTP 가정 cross-reference 갱신.
|
||||
- REQ-026: `docs/interface-contract.md`/`docs/runtime-flows.md`/`docs/project-structure.md` 정합 (메시지 계약·MQ 흐름·messaging 어댑터·sync+thread 런타임 반영, HTTP `/v1` 섹션 제거).
|
||||
- Out of Scope (후속 Discovery / 다른 Discovery 소관):
|
||||
- 스냅샷/intent 의 logical 계약 자체 변경(dcy-005/002/003 소관), 전략 의사결정 로직(전략 모듈 책임), RabbitMQ 클러스터/HA 운영 세부, portfolio-hub 등 다른 외부 연동의 transport, core 자율 안전 매도(stop-loss·forced_close 자동 트리거) 실제 구현(A-5, 별도 Discovery).
|
||||
|
||||
## Documents
|
||||
- Planning: [planning.md](./planning.md)
|
||||
- Design: [design.md](./design.md)
|
||||
- Implementation: [implementation.md](./implementation.md)
|
||||
- Verification: [verification.md](./verification.md)
|
||||
|
||||
## Notes
|
||||
- Source Discovery dcy-006 단일. 핵심 확정 결정: RabbitMQ 가 HTTP 를 **대체**(병행 없음, OQ-1) + HTTP 표면 0(`healthz` 포함, OQ-7) + 3패턴 토폴로지(스냅샷 RPC + intent RPC + 이벤트 topic, OQ-2) + effectively-once(at-least-once + idempotency, OQ-3) + 보수적 degrade(버퍼링 금지·신규 매매 중단·core 안전 매도 독립, OQ-4) + pika 동기 + sync+thread 런타임(OQ-5) + `TREX_RABBITMQ_URL` env(OQ-6).
|
||||
- 핵심 리스크: 가용성 결합 — RabbitMQ 가 SPOF 성격(R-3 High, HTTP fallback 없음). REQ-024 degrade 정책 + core 안전 매도 독립(A-5 미구현, 별도 트래킹)으로 신규 매매 중단으로 영향 한정. big-bang 마이그레이션(R-5) 은 본 batch 가 REQ-022/025 동시 deliver 로 회피.
|
||||
- DATA(비차단): 실 RabbitMQ broker 인스턴스/자격증명 provision 은 delivery/운영 작업 — verification 은 stub `InMemoryTransport` 로 충분 검증 가능하며 실 broker 미가용은 PG/KIS 와 동일하게 게이트 skip 으로 분리한다.
|
||||
@@ -0,0 +1,59 @@
|
||||
# BAT-007 Planning
|
||||
|
||||
- Status: draft
|
||||
- Batch: BAT-007
|
||||
- Profile: standard
|
||||
|
||||
## Included REQ
|
||||
- REQ-021 (Integration): messaging 토폴로지 + 메시지 계약 매핑
|
||||
- REQ-022 (Integration): messaging transport 포트 + RabbitMQ 어댑터 + stub + sync+thread daemon
|
||||
- REQ-023 (Exception): messaging delivery 신뢰성 (effectively-once + durable + DLQ + publisher confirms)
|
||||
- REQ-024 (Non-Functional): RabbitMQ 가용성 degrade 정책
|
||||
- REQ-025 (Interface): HTTP `/v1` API 완전 제거 (healthz 포함, HTTP 표면 0)
|
||||
- REQ-026 (Documentation): messaging 레이어 baseline 문서 정합
|
||||
|
||||
## Delivery Plan
|
||||
- 의존 순서대로 구현한다.
|
||||
1. REQ-021: `trex_core/adapters/messaging/topology.py`(또는 등가) 에 exchange/queue/binding/routing-key 정의. 매핑 원칙(view·strategy_id payload, event routing key)을 헬퍼로 고정.
|
||||
2. REQ-022: `trex_core/application/messaging.py` Protocol(publish/subscribe/RPC), `adapters/messaging/in_memory.py`(결정론 stub), `adapters/messaging/rabbitmq.py`(pika BlockingConnection, 스레드별 channel + `add_callback_threadsafe`, 자체 재연결 백오프). `runtime/config.py` 에 `PortfolioHubConfig` 옆에 `RabbitMQConfig(url, timeout)` 추가, `TREX_RABBITMQ_URL` env 로딩.
|
||||
3. REQ-025: `runtime/daemon.py` 에서 uvicorn import/실행과 FastAPI base 제거, `_execution_loop`/`_ledger_loop` 옆에 `_intent_rpc_consumer`/`_snapshot_rpc_consumer` 스레드 추가. `runtime/config.py` 의 `TREX_API_HOST`/`TREX_API_PORT` 폐기. `trex_core/adapters/api/` 전체 트리 + 해당 테스트 제거. `pyproject.toml` 의 `fastapi`/`uvicorn` 의존 제거.
|
||||
4. REQ-023: consumer 에 manual ack-after-postgres-commit + correlation_id dedup (intent_log 또는 dedicated dedup store), 단일 consumer + prefetch=1, 이벤트 publisher 에 publisher confirms + DLQ exchange 라우팅, per-strategy durable queue + TTL/max-length.
|
||||
5. REQ-024: 어댑터의 connection 상태 enum(`connected/disconnected/reconnecting`) 노출 + application 레이어 broker-down 분기(스냅샷 RPC timeout → 매매 보류, intent publish 실패 → 거부), 버퍼링 금지 회귀 가드 테스트.
|
||||
6. REQ-026: REQ-021~025 구현이 안정화된 뒤 `docs/interface-contract.md`/`docs/runtime-flows.md`/`docs/project-structure.md` 3문서를 messaging 레이어로 정합 (HTTP `/v1` 섹션 제거, messaging 섹션 신설, sync+thread 런타임 반영).
|
||||
- 데몬 reconcile 시점은 변경하지 않는다(REQ-014 broker reconcile, REQ-019 ledger outbox 처리 그대로 유지).
|
||||
|
||||
## Dependencies
|
||||
- Internal:
|
||||
- REQ-022 는 REQ-021 의 토폴로지 정의 선행.
|
||||
- REQ-023 은 REQ-022 의 어댑터 ack/publish 경로에 통합.
|
||||
- REQ-024 는 REQ-022 의 connection 상태 노출에 의존.
|
||||
- REQ-025 는 REQ-022 의 sync+thread 런타임이 동시에 들어가야 통신 단절(R-5) 회피.
|
||||
- REQ-026 은 REQ-021~025 구현 결과에 의존.
|
||||
- 기존 자산: BAT-002 의 `IntentService`/`SlotService` 호출 경계, BAT-004 의 broker execution + ledger outbox 스레드, BAT-006 의 ledger writer 스레드는 그대로 재사용한다.
|
||||
- dcy-003 의 멱등키(`correlation_id` 패턴)와 `intent_log` durable dedup 게이트(REQ-007/intent_log) 를 RabbitMQ intent consumer 의 dedup 으로 재사용한다.
|
||||
- External:
|
||||
- RabbitMQ broker 인스턴스 + 자격증명(`amqp://user:pass@host:5672/vhost`) — `TREX_RABBITMQ_URL` env 로 주입. 실 broker 미가용 시 stub 검증 + RabbitMQ 통합 테스트는 게이트 skip.
|
||||
- `pika>=1.3` 신규 의존성 추가, `fastapi`/`uvicorn` 의존 제거.
|
||||
- 전략 모듈 측 RabbitMQ 클라이언트 전환(외부 작업) — 본 batch 는 trex-core 측 transport 만 제공한다. 전략 모듈 전환 일정과 cut-over 는 운영 release 단계 의제.
|
||||
|
||||
## Design Gate
|
||||
- Design Required Before Implementation: yes
|
||||
- Reason: 신규 transport 포트 + 외부 어댑터 + 데몬 런타임 재구성(uvicorn 제거 + sync+thread, intent/snapshot RPC consumer 스레드 신설) + delivery 신뢰성 규약(ack 시점, dedup 게이트, DLQ, publisher confirms, TTL/max-length) + degrade 정책의 connection 상태 머신 + HTTP 어댑터 전체 제거가 구조/인터페이스/런타임을 동시에 흔든다. 구현 전 토폴로지(exchange/queue/routing key/reply-to), ack-after-commit 시퀀스, 재연결 백오프 + degrade 상태 머신, 스레드별 채널 관리 규약을 design.md 에 고정해야 한다.
|
||||
|
||||
## Milestones
|
||||
1. M1 — REQ-021: 토폴로지 선언(exchanges/queues/bindings/routing keys) + 매핑 헬퍼 + stub 어댑터 RPC/event 골격.
|
||||
2. M2 — REQ-022: `MessagingTransport` 포트 + `InMemoryTransport`(stub) + `RabbitMQTransport`(pika 동기) + `RabbitMQConfig` + `TREX_RABBITMQ_URL` 로딩.
|
||||
3. M3 — REQ-025: `adapters/api/` 제거 + `runtime/daemon.py` 의 uvicorn/FastAPI 제거 + intent/snapshot RPC consumer 스레드 신설 + `pyproject.toml`/`.env.example` 정리.
|
||||
4. M4 — REQ-023: ack-after-commit + correlation_id dedup + 단일 consumer prefetch=1 + 이벤트 publisher confirms + DLQ + per-strategy durable queue + TTL/max-length.
|
||||
5. M5 — REQ-024: connection 상태 노출 + application broker-down 분기 + 회귀 가드(버퍼링 0, 복구 후 자동 재생 0).
|
||||
6. M6 — REQ-026: baseline 3문서 정합 + 변경 이력 추가.
|
||||
7. M7 — 통합 verification: stub 어댑터 RPC/이벤트 lifecycle, dedup, durable+catch-up, conflict/DLQ, degrade 분기, HTTP 표면 0(포트/grep), 도메인 import 스윕, baseline 문서-코드 정합 리뷰.
|
||||
|
||||
## Risks
|
||||
- R-1 (High, dcy-006 R-3): 가용성 결합 — RabbitMQ 가 SPOF 성격, HTTP fallback 없음. 대응: REQ-024 degrade 정책으로 신규 매매 중단으로 영향 한정. **A-5 (core 자율 안전 매도) 가 미구현 상태**이므로 운영 release 전에 broker outage 시 열린 포지션 처리 절차(운영 도구 또는 수동 SQL)를 별도 트래킹.
|
||||
- R-2 (Medium, dcy-006 R-5): big-bang 마이그레이션 — HTTP 제거 시점과 전략 모듈 MQ 전환이 어긋나면 통신 단절. 대응: REQ-021/022/023/025 한 batch + stub 사전 검증 + release 단계에서 cut-over 순서(전략 모듈 → trex-core release) 합의.
|
||||
- R-3 (Medium): 멱등 dedup store 선택 — intent_log(BAT-002, REQ-007) 를 그대로 dedup 게이트로 재사용할지, RabbitMQ consumer 전용 dedup table 을 새로 둘지. 대응: design 단계에서 결정 후 ack 시퀀스에 반영. 기본 추정은 intent_log 재사용(dcy-006 OQ-3 의 dcy-003 correlation_id idempotency 명시).
|
||||
- R-4 (Medium): pika 자동 재연결 미지원으로 백오프 + 채널 재선언 + consumer rebind 를 직접 구현해야 함. 잘못 짜면 메시지 유실/중복 위험. 대응: design 단계에서 재연결 상태 머신 + 재선언 책임 명시 + 회귀 테스트.
|
||||
- R-5 (Low): pika BlockingConnection 의 thread-safety 미보장 — 스레드별 connection/channel 또는 `add_callback_threadsafe` 규약을 design 으로 고정하고 stub/실 어댑터 둘 다 회귀 테스트.
|
||||
- R-6 (Low): 실 RabbitMQ 인프라 미가용 — verification evidence 가 stub 수준에 집중될 수 있음. 대응: PG/KIS 와 동일하게 `TREX_RABBITMQ_TEST_URL` 게이트로 분리해 미가용 시 skip 명시. 실 통합 evidence 는 운영 단계에서 보강.
|
||||
- R-7 (Low): dcy-005(스냅샷 read 계약) 가 아직 REQ 로 정규화되지 않은 상태에서 본 batch 의 snapshot RPC 가 먼저 도입됨. 응답 셰이프는 stub 수준에서 잠정 정의하고, dcy-005 REQ 가 확정되면 contract 정합을 후속 batch 에서 보강.
|
||||
@@ -0,0 +1,104 @@
|
||||
# BAT-007 Verification
|
||||
|
||||
- Status: approved
|
||||
- Batch: BAT-007
|
||||
|
||||
## Acceptance Mapping
|
||||
- REQ-021:
|
||||
- AC-1: 데몬 기동 시 `trex.snapshot.req`, `trex.intent.req` 큐와 `trex.events` 토픽 익스체인지 선언 evidence (stub + 실 RabbitMQ).
|
||||
- AC-2: 스냅샷 RPC 응답 logical 필드 + `correlation_id` 일치 evidence.
|
||||
- AC-3: intent admission RPC 가 admission 응답을 reply-to 로 반환하고 체결/종료는 후속 이벤트로 발행되는 2단계 evidence.
|
||||
- AC-4: strategy_id=A 이벤트가 `*.A.#` 바인딩 queue 만 수신 evidence (stub + 실 RabbitMQ).
|
||||
- AC-5: 요청 메시지 payload 검사로 `view`/`strategy_id` 가 payload 에 있고 routing key 에 없음 evidence.
|
||||
- REQ-022:
|
||||
- AC-1: `InMemoryTransport` stub publish/subscribe/RPC 외부 broker 없이 동작 evidence.
|
||||
- AC-2: `RabbitMQTransport` 가 `TREX_RABBITMQ_URL` 로 connection/channel 열고 송수신 evidence (게이트 통과, 실 broker 실행됨).
|
||||
- AC-3: `Daemon` lifecycle 에서 intent/snapshot RPC + execution/ledger 스레드 동시 동작 + graceful shutdown(connection close 포함) evidence. `uvicorn.run` 의존 0 evidence (정적 import 가드).
|
||||
- AC-4: connection drop 후 백오프 재연결 + degrade 정책에 따른 신규 처리 중단 evidence (재연결 코드 + stub 가용성 토글 회귀 가드).
|
||||
- AC-5: `tests/domain/test_domain_import_sweep.py` 가 `pika`/`adapters.messaging` 0 import 확인 (NFR-1).
|
||||
- REQ-023:
|
||||
- AC-1: 동일 `correlation_id` intent 메시지 2회 처리 → 슬롯 전이 1회 + dedup evidence (NFR-2).
|
||||
- AC-2: ack-after-commit 시퀀스 + intent_log durable dedup 으로 재전달 시 추가 전이 0 evidence (간접: dedup 테스트가 ack 순서를 전제로 통과).
|
||||
- AC-3: intent 큐 토폴로지가 durable + DLQ pointer + prefetch=1 검사 evidence (실 broker PRECONDITION_FAILED 검사로 확인).
|
||||
- AC-4: per-strategy durable queue 의 catch-up 동작은 토폴로지 args (`x-message-ttl`/`x-max-length`/`x-overflow=drop-head`/`x-dead-letter-exchange`) + 실 broker 의 per-strategy filter 테스트로 evidence.
|
||||
- AC-5: 이벤트 페이로드에 `sequence_at` 단조 토큰 포함 evidence (테스트 단언).
|
||||
- AC-6: publisher confirms + UnroutableError → DLQ 라우팅 코드 + stub DLQ 수집기 evidence.
|
||||
- AC-7: TTL/max-length drop-oldest 는 토폴로지 args 선언으로 evidence (실 broker queue arguments 일치).
|
||||
- REQ-024:
|
||||
- AC-1: broker 불가 상태에서 publish/RPC 시 `TransportUnavailableError` 즉시 실패 + 슬롯 전이 0 evidence.
|
||||
- AC-2: 로컬 버퍼링 없음 — `MessagingTransport` 인터페이스에 enqueue 가 없음 + 어댑터 코드 review.
|
||||
- AC-3: `transport.health()` enum 노출 + 어댑터 `_mark_disconnected` 상태 머신 evidence.
|
||||
- AC-4: A-5 정책 contract 가 REQ-024 Notes 와 BAT-007 implementation/verification Remaining Risks 에 명시 evidence.
|
||||
- AC-5: 어댑터에 outbox/버퍼 없음 (코드 review) + 발행 실패가 슬롯 전이를 롤백하지 않음 evidence.
|
||||
- REQ-025:
|
||||
- AC-1: `tests/runtime/test_daemon_no_http_surface.py::test_adapters_api_tree_does_not_exist` + `::test_no_fastapi_or_uvicorn_in_trex_core_source` evidence.
|
||||
- AC-2: 데몬 import 가드 (`test_daemon_module_has_no_fastapi_or_uvicorn_import`) evidence.
|
||||
- AC-3: `test_config_env_no_longer_references_api_host_or_port` evidence.
|
||||
- AC-4: `test_pyproject_dependencies_have_no_fastapi_or_uvicorn` evidence.
|
||||
- AC-5: dcy-002 헤더 transport supersede 메모 + dcy-005 가 이미 dcy-006 cross-reference 갖추고 있음 evidence.
|
||||
- AC-6: `Daemon` 클래스는 `signal.SIGINT/SIGTERM` 만 처리하고 HTTP 포트 바인딩 없음 (코드 review).
|
||||
- REQ-026:
|
||||
- AC-1: 3 baseline 문서 messaging 섹션 신설 + `Interface Summary`/`Covered Entry Points`/구조 트리에 반영 evidence.
|
||||
- AC-2: baseline ↔ 코드 정합 manual review evidence.
|
||||
- AC-3: 3 baseline 문서 Change Log 에 2026-06-05 BAT-007 항목 evidence.
|
||||
- AC-4: `docs/interface-contract.md` 의 HTTP `/v1` 섹션 제거 + `docs/project-structure.md` 트리에서 `adapters/api/` 제거 evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
### Test
|
||||
- 명령: `TREX_RABBITMQ_TEST_URL="amqp://admin:admin@127.0.0.1:5672/" .venv/bin/python -m pytest -q`
|
||||
- 결과: `135 passed, 12 skipped` (PG/KIS 게이트만 skip; 실 RabbitMQ 통합 7건 모두 실행/통과).
|
||||
- REQ-021 AC-1: `tests/adapters/messaging/test_rabbitmq_transport.py::test_declare_topology_creates_core_entities` 가 두 번 declare 후 멱등 + `TransportHealth.CONNECTED` 확인.
|
||||
- REQ-021 AC-2: `tests/application/test_messaging_snapshot_consumer.py::test_snapshot_returns_all_slots_and_capacity` 응답 셰이프 확인 + `tests/adapters/messaging/test_rabbitmq_transport.py::test_rpc_roundtrip` 가 `correlation_id` 일치 확인.
|
||||
- REQ-021 AC-3: `tests/application/test_messaging_intent_consumer.py::test_buy_admission_returns_admitted_and_transitions_slot` + `tests/application/test_messaging_event_publisher.py::test_fill_emits_slot_filled_event_with_routing_key_and_state` 의 조합으로 admission 동기 + fill 비동기 이벤트 분리 확인.
|
||||
- REQ-021 AC-4: `tests/application/test_messaging_event_publisher.py::test_event_for_strategy_a_does_not_reach_strategy_b_queue` + `tests/adapters/messaging/test_rabbitmq_transport.py::test_event_publish_and_per_strategy_consume` (실 RabbitMQ).
|
||||
- REQ-021 AC-5: `tests/adapters/messaging/test_topology.py::test_event_routing_key_format` + `tests/adapters/messaging/test_topology.py::test_strategy_queue_name_and_binding_pattern`.
|
||||
- REQ-022 AC-1: `tests/adapters/messaging/test_in_memory_transport.py` 5종.
|
||||
- REQ-022 AC-2: `tests/adapters/messaging/test_rabbitmq_transport.py` 5종 (모두 실 broker 실행 통과).
|
||||
- REQ-022 AC-3: `tests/runtime/test_daemon_no_http_surface.py::test_daemon_module_has_no_fastapi_or_uvicorn_import` + `Daemon` 4 스레드 + close 코드 review.
|
||||
- REQ-022 AC-4: `RabbitMQTransport._sleep_backoff` + `_mark_disconnected` 코드 + `tests/adapters/messaging/test_in_memory_transport.py::test_unavailable_transport_raises_on_publish_and_rpc` degrade 분기 회귀.
|
||||
- REQ-022 AC-5: `tests/domain/test_domain_import_sweep.py::test_domain_has_no_forbidden_imports` (`pika`/`starlette` 포함 금지 prefix 갱신).
|
||||
- REQ-023 AC-1: `tests/application/test_messaging_intent_consumer.py::test_duplicate_correlation_id_dedups_via_intent_log` + `tests/adapters/messaging/test_rabbitmq_intent_e2e.py::test_intent_admission_rpc_dedups_duplicate_correlation_id_over_rabbitmq` (실 RabbitMQ).
|
||||
- REQ-023 AC-2: 위 dedup 테스트가 Postgres durable commit 전제(intent_log) 위에서 통과 — ack-after-commit 순서 evidence. `Daemon._intent_rpc_loop` 가 manual ack-after-handler 사용.
|
||||
- REQ-023 AC-3: `tests/adapters/messaging/test_rabbitmq_intent_e2e.py::test_intent_queue_topology_uses_dlq_pointer` 가 PRECONDITION_FAILED 로 큐 argument(durable + DLQ pointer) 일치 확인.
|
||||
- REQ-023 AC-4: `topology.STRATEGY_QUEUE_ARGS` (`x-message-ttl=3.6e6`, `x-max-length=10000`, `x-overflow=drop-head`, `x-dead-letter-exchange`) + per-strategy filter 테스트가 broker 단 필터링 확인.
|
||||
- REQ-023 AC-5: `tests/application/test_messaging_event_publisher.py::test_fill_emits_slot_filled_event_with_routing_key_and_state` 가 `sequence_at` 포함 확인.
|
||||
- REQ-023 AC-6: `RabbitMQTransport.publish_event` 의 `UnroutableError` → `_publish_dlq` + `_on_message` 의 handler exception NACK(requeue=False) + `tests/adapters/messaging/test_in_memory_transport.py::test_publish_event_with_no_subscriber_routes_to_dlq` evidence.
|
||||
- REQ-023 AC-7: `STRATEGY_QUEUE_ARGS["x-overflow"] == "drop-head"` (`tests/adapters/messaging/test_topology.py::test_strategy_queue_args_have_ttl_and_max_length`) + 스냅샷 reconcile 경로(snapshot RPC handler) 존재.
|
||||
- REQ-024 AC-1: `tests/adapters/messaging/test_in_memory_transport.py::test_unavailable_transport_raises_on_publish_and_rpc` + `tests/application/test_messaging_event_publisher.py::test_publish_failure_does_not_break_execution_loop`.
|
||||
- REQ-024 AC-2: `MessagingTransport` Protocol 에 outbox/enqueue 가 없음 + 어댑터 코드 review (publish 실패 → 즉시 raise/DLQ, 로컬 보관 0).
|
||||
- REQ-024 AC-3: `TransportHealth` enum + `InMemoryTransport.set_available`/`RabbitMQTransport._mark_disconnected` 코드 + AC-1 테스트가 disconnected 상태 노출 검증.
|
||||
- REQ-024 AC-4: REQ-024 본문 Notes + BAT-007 implementation/verification Remaining Risks 에 명시.
|
||||
- REQ-024 AC-5: publisher 실패 시 슬롯 상태 유지 테스트(`test_publish_failure_does_not_break_execution_loop`).
|
||||
- REQ-025 AC-1~4: `tests/runtime/test_daemon_no_http_surface.py` 5종 모두 통과.
|
||||
- REQ-025 AC-5: `docs/discovery/dcy-002_…md` 헤더 supersede 메모 + `docs/discovery/dcy-005_…md` 가 이미 dcy-006 cross-reference 보유.
|
||||
- REQ-025 AC-6: `Daemon.run` 의 signal handler + 포트 바인딩 0(`ss -ltn` 으로 데몬 기동 후 확인 가능; 본 batch 는 import 가드로 충분 — 실 environment 에는 별도 운영 절차).
|
||||
- REQ-026 AC-1/AC-3: `docs/interface-contract.md` / `docs/runtime-flows.md` / `docs/project-structure.md` 모두에 messaging 섹션 + Change Log 2026-06-05 BAT-007 항목 추가됨.
|
||||
- REQ-026 AC-2: 본 verification 의 Manual 섹션 + code-search evidence.
|
||||
- REQ-026 AC-4: `grep "HTTP \`/v1\`" docs/interface-contract.md` → 제거 안내 1건만 잔존(invalidate notice). 트리에서 `adapters/api/` 제거됨.
|
||||
|
||||
### Manual
|
||||
- baseline ↔ 코드 정합 리뷰 (REQ-026 AC-1/AC-2):
|
||||
- `docs/interface-contract.md` 의 `Interface: RabbitMQ messaging` 토폴로지/패턴/payload/Reliability/Degrade 표가 `trex_core/adapters/messaging/topology.py` 의 상수와 `trex_core/adapters/messaging/rabbitmq.py` 의 publish/consume 동작, `trex_core/application/messaging.py` 의 `MessagingTransport` Protocol 시그니처와 정합.
|
||||
- `docs/runtime-flows.md` 의 `데몬 lifecycle`/`스냅샷 RPC`/`intent admission RPC`/`이벤트 발행·구독`/`broker degrade 분기` 흐름이 `trex_core/runtime/daemon.py:Daemon` 클래스(setup/start/shutdown + 4 worker) + `trex_core/application/execution.py:_emit_event` + `trex_core/application/messaging_handlers.py` 와 정합.
|
||||
- `docs/project-structure.md` 디렉토리 트리에서 `trex_core/adapters/api/` 제거 + `trex_core/adapters/messaging/` 추가 + `trex_core/application/messaging.py`/`messaging_handlers.py` 추가 + daemon 의 4 스레드 구성 반영. 실제 디렉토리 트리(`ls trex_core/adapters/`, `ls tests/adapters/`) 와 일치.
|
||||
- code-search (REQ-022 AC-5, REQ-025 AC-1):
|
||||
- `grep -r "import httpx\|from httpx" trex_core/domain/` → 0건.
|
||||
- `grep -r "import pika\|from pika" trex_core/domain/` → 0건.
|
||||
- `grep -r "fastapi\|uvicorn\|starlette" trex_core/` → 0건.
|
||||
- `find trex_core -path '*/adapters/api*'` → 0건.
|
||||
- transport supersede cross-reference (REQ-025 AC-5):
|
||||
- `docs/discovery/dcy-002_…md` 헤더에 dcy-006/BAT-007 supersede 메모 추가됨.
|
||||
- `docs/discovery/dcy-005_…md` 는 본 batch 작업 전부터 dcy-006 cross-reference 보유 (FR-1, A-3, # 9 참조 목록).
|
||||
|
||||
### Logs
|
||||
- `.venv/bin/ruff check trex_core tests` → `All checks passed!`.
|
||||
- RabbitMQ 통합 evidence: `127.0.0.1:5672` admin/admin 으로 7건 통합 테스트(`test_rabbitmq_transport.py` 5 + `test_rabbitmq_intent_e2e.py` 2) 모두 PASSED. 큐/이벤트는 매 테스트가 uuid prefix 로 격리되어 잔존 0.
|
||||
|
||||
## Result
|
||||
- Ready for Release: true
|
||||
- Blocking Issues:
|
||||
- 없음.
|
||||
- Notes:
|
||||
- core 자율 안전 매도(A-5, dcy-006) 는 본 batch 범위 외 — release 전에 운영 절차 (broker 장기 outage 시 열린 포지션 처리) 문서화 또는 별도 Discovery 트래킹 권장.
|
||||
- 전략 모듈 측 RabbitMQ 클라이언트 전환 + cut-over 순서(전략 모듈 → trex-core) 는 release 단계 의제.
|
||||
@@ -14,3 +14,4 @@
|
||||
| BAT-004 | standard | release-candidate | REQ-011, REQ-012, REQ-013, REQ-014, REQ-015 | dcy-003 | [bat-004](./bat-004_20260604_broker-execution-and-outbox/) |
|
||||
| BAT-005 | batch-lite | release-candidate | REQ-016 | dcy-003 | [bat-005](./bat-005_20260604_kis-token-redis-cache/) |
|
||||
| BAT-006 | standard | release-candidate | REQ-017, REQ-018, REQ-019, REQ-020 | dcy-004 | [bat-006](./bat-006_20260604_portfolio-hub-ledger-integration/) |
|
||||
| BAT-007 | standard | release-candidate | REQ-021, REQ-022, REQ-023, REQ-024, REQ-025, REQ-026 | dcy-006 | [bat-007](./bat-007_20260605_strategy-module-rabbitmq-transport/) |
|
||||
|
||||
Reference in New Issue
Block a user