Files
trex-core/docs/srs/Interface/req-080_strategy-state-set-rpc.md
T
genichinandClaude Opus 4.8 e0d4e71304 feat(slot,intent): slot strategy-state 저장소 (dcy-028) + sell retryable 플래그 (issue #27)
BAT-042 (dcy-028 / issue #26 C-1/C-2/C-2b/C-3, REQ-079~082 + REQ-073/074 CHG):
- slot_strategy_state 별도 테이블 + StrategyStateStore(in-memory+PG) + occupancy_seq·version CAS + opaque UTF-8 data + 2단 size cap (REQ-079)
- trex.slots.strategy_state.set write RPC — reject reason 집합, 멱등 (REQ-080)
- Slot.occupancy_seq 필드 + inactive→pending_buy bump + →INACTIVE close 삭제 훅 → 점유 전환 ABA 구조적 차단 (REQ-081)
- slots.req 응답 행에 strategy_state 맵(batched 조립)·occupancy_seq additive (REQ-073 AC-7/REQ-074 AC-6)
- 마이그레이션 014(occupancy_seq)/015(slot_strategy_state), baseline 문서 정합 (REQ-082)

BAT-043 (issue #27 / REQ-007 CHG):
- rejected SellIntent 응답에 additive retryable: bool (core 소유 reason→retryable 매핑, 미인식 기본 true, bad_request* false) — 손절매 재시도 안전 경로 decoupling

검증: 487 passed, 47 skipped (신규 41: store CAS 6+ABA, occupancy bump/close 4경로, set RPC 9, slots read 5, retryable 8, PG 게이트), ruff clean.
REQ-079·080·081·082·073·074·007 → Implemented. issue #27 close. PG 경로 실 DB 검증은 release 위임.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:27:57 +09:00

5.7 KiB

req-080: trex.slots.strategy_state.set write RPC 계약 — occupancy_seq·version CAS

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

Intent

  • 전략 데몬이 슬롯의 opaque strategy-state 를 write 하는 신규 RPC 계약을 정의한다. read 는 기존 trex.slots.req(REQ-073) 에 piggyback 하고(추가 왕복 없음), write 만 별도 RPC 로 분리해 evaluate() 순수성과 재시도 격리를 보존한다. (dcy-028 FR-2/OQ-2, issue #26 C-2)

Requirement

  • 신규 RPC trex.slots.strategy_state.set 를 기존 계약 패턴(direct reply-to + JSON + per-instance queue_name({base}.{instance_key}))으로 신설한다.
  • 요청 payload: {slot_id, strategy_id, expected_version:int, expected_occupancy_seq:int, data:str}. correlation_id = "{slot_id}:{strategy_id}:{expected_version}"(멱등 키), delivery persistent.
  • 성공 응답: {ok:true, slot_id, strategy_id, version:<new>}.
  • 실패 응답 reason 전체 집합 = {occupancy_changed, version_conflict, slot_inactive, state_too_large, bad_request}:
    • occupancy_changed: 슬롯 현재 occupancy_seq ≠ expected_occupancy_seq → {ok:false, reason, occupancy_seq:<cur>} (저장 안 함; 데몬 re-read 후 fresh restart).
    • version_conflict: stored version ≠ expected_version → {ok:false, reason, version:<cur>}.
    • slot_inactive: 슬롯 inactive/미존재 → {ok:false, reason} (저장 안 함).
    • state_too_large: data 가 size cap(REQ-079/NFR) 초과 → {ok:false, reason} (저장 안 함).
    • bad_request:<detail>: malformed payload(기존 intent 핸들러 패턴) → {ok:false, reason}.
  • 핸들러는 REQ-079 StrategyStateStore 의 CAS 로 위임한다(저장 의미는 REQ-079 소유). data 는 opaque 로 전달하고 핸들러는 해석하지 않는다.
  • 동일 correlation_id 재전송은 부작용 없음(멱등). 미인식 reason 에 대해 소비자 fail-closed 를 계약에 명시한다.

Acceptance Criteria

  1. Given 기동된 데몬, When 토폴로지 선언, Then trex.slots.strategy_state.set(per-instance) 큐가 존재하고 direct reply-to 로 응답한다.
  2. Given 유효 요청(occupancy_seq·version 일치), When set, Then {ok:true, version:<+1>} 를 반환하고 저장된다.
  3. Given occupancy_seq 불일치, Then {ok:false, reason:"occupancy_changed", occupancy_seq:<cur>}. Given version 불일치, Then {ok:false, reason:"version_conflict", version:<cur>}. 둘 다 저장되지 않는다.
  4. Given inactive 슬롯, Then {ok:false, reason:"slot_inactive"}. Given size cap 초과, Then {ok:false, reason:"state_too_large"}. Given malformed payload, Then {ok:false, reason:"bad_request:<detail>"}.
  5. Given 동일 correlation_id 재전송, When 처리, Then 부작용 없이 동일 결과가 반환된다.
  6. Given 응답 reason, When 집합 검사, Then {occupancy_changed, version_conflict, slot_inactive, state_too_large, bad_request} 외 값이 없다.

Impacted Area

  • Docs: docs/interface-contract.md(strategy_state.set 계약 — REQ-082), docs/runtime-flows.md(write 흐름 — REQ-082)
  • Modules: trex_core/adapters/messaging/topology.py(큐명), trex_core/application/messaging_handlers.py(신규 set 핸들러 — REQ-079 store 위임), trex_core/runtime/daemon.py(핸들러 와이어링)
  • Tests: tests/application/(set 핸들러 6 reason 케이스 + 멱등), tests/adapters/messaging/(토폴로지)

Notes

  • 저장·CAS 의미는 REQ-079 가 소유한다 — 본 REQ 는 RPC 계약(요청/응답 shape, reason 운반, 멱등, 큐). 핸들러는 store 로 위임만 한다.
  • read piggyback(REQ-073/074)과의 비대칭(read 무료/write 분리)은 dcy-028 OQ-2 의도. 사이클당 다중 슬롯 write 시 N개 set RPC — optional batch 변형은 v1 범위 밖 후속.
  • 출처: dcy-028 FR-2(C-2), OQ-2(별도 RPC), reject reason 집합(trex-tsl #4705990067 답변 정합).

Change Log

CHG-20260615-03

  • Date: 2026-06-15
  • Author: Justin Ko
  • Type: status
  • Summary: Approved → Implemented (confirm-req-implemented). 근거: BAT-042 verification — trex.slots.strategy_state.set 큐(topology/rabbitmq declare) + make_strategy_state_set_handler(store 위임) + daemon consumer 스레드. AC-1~6 evidence: tests/application/test_strategy_state_set_handler.py(성공+5 reason+bad_request 2종+멱등+reason 집합). 479 passed, ruff clean. Blocking Issues 없음.

CHG-20260615-02

  • Date: 2026-06-15
  • Author: Justin Ko
  • Type: status
  • Summary: Proposed → Approved (confirm-req). 필수 필드·구체 AC(6개) 충족, source dcy-028(OQ-2 정합) 일치, reject reason 집합 trex-tsl #4705990067 답변과 정합. blocker 없음.

CHG-20260615-01

  • Date: 2026-06-15
  • Author: Justin Ko

Change Summary

  • dcy-028 FR-2/OQ-2 로부터 최초 생성(Proposed). strategy_state.set write RPC 계약 + occupancy_seq·version CAS + reject reason 전체 집합.

Intent

  • write 를 별도 RPC 로 분리해 evaluate 순수성·재시도 격리 보존, read 는 slots.req piggyback.

Acceptance Criteria Delta

  • Added: 큐/성공/occupancy·version reject/inactive·size·bad_request/멱등/reason 집합 6개 기준
  • Updated: 없음
  • Removed: 없음

Impacted Area Delta

  • Docs: interface-contract.md, runtime-flows.md(REQ-082)
  • Modules: topology.py, messaging_handlers.py, daemon.py
  • Tests: set 핸들러 reason 케이스, 토폴로지

Delivery Trace Delta

  • Batches: none (편성 예정)
  • Releases: none

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req 후 batch 편성(REQ-079/081/082 + REQ-073/074 CHG 동일 batch)

Validation Plan

  • set 핸들러 단위 테스트(6 reason 케이스 + 멱등) + 토폴로지 선언 테스트로 RPC 계약 검증.