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>
6.3 KiB
6.3 KiB
req-079: Slot strategy-state 저장소 — slot_strategy_state 테이블 + StrategyStateStore 포트 + occupancy_seq·version CAS
- Status: Implemented
- Type: Data
- Priority: High
- Owner: project maintainers
Intent
- 전략 데몬(trex-tsl 등)이 슬롯 점유 동안 누적하는 opaque 상태(예: TSL peak)를 슬롯 수명에 묶어 server-side 영속화할 저장소를 신설한다. trex-core 는 값을 해석하지 않고(opaque) 저장/조회/CAS 만 책임진다. 슬롯이 source of truth 이자 GC 가 되어 데몬은 cleanup 책임이 없다. (dcy-028 FR-2/OQ-1/OQ-4, issue #26 C-2)
Requirement
- 별도 테이블
slot_strategy_state를 신설한다(슬롯 행 JSONB 미사용 — dcy-028 OQ-4): 복합 PK(slot_id, strategy_id), 컬럼version int,data text,updated_at timestamptz, 그리고 점유 식별occupancy_seq int(REQ-081 가드 참조). strategy 당 1행. StrategyStateStore포트(Protocol)를 정의하고 PG 구현과 in-memory 구현(복합키 dict)을 함께 제공한다(paper/테스트 무중단).- CAS upsert 의미:
- occupancy_seq 일치 + version 일치 → commit, version+1 반환.
- occupancy 불일치 →
occupancy_changed(저장 안 함). version 불일치 →version_conflict(저장 안 함). 슬롯 inactive/미존재 →slot_inactive(저장 안 함). - 최초(엔트리 없음 + expected_version=0 + occupancy 일치) → version=1 생성.
- 동일 입력(같은 expected_version) 재적용은 부작용 없음(멱등).
data는 opaque UTF-8 문자열로 저장한다. core 검증은 (1) 유효 UTF-8 + (2) byte 크기 상한뿐 — JSON/base64 를 강제하지 않는다. 상한은 2단(기본 1~2KB / hard ceiling 4KB byte). 초과 시state_too_large로 저장 거부(REQ-080 RPC 가 reason 운반).- 조회 API 는 slot_id 집합으로 batched 조회를 지원해 C-1 read(REQ-073/074) 가 추가 왕복 없이 행별 맵으로 조립할 수 있어야 한다.
Acceptance Criteria
- Given 비어 있는
(slot_id, strategy_id), When expected_version=0 + 일치 occupancy_seq 로 set, Then version=1 로 생성되고 같은 키 조회 시 data·version=1 이 반환된다. - Given version=N 인 엔트리, When expected_version=N + 일치 occupancy_seq 로 set, Then commit + version=N+1. When expected_version≠N 으로 set, Then
version_conflict로 저장되지 않고 기존 값이 유지된다. - Given 슬롯의 현재 occupancy_seq=k, When expected_occupancy_seq≠k 로 set, Then
occupancy_changed로 저장되지 않는다. Given inactive/미존재 슬롯, When set, Thenslot_inactive로 저장되지 않는다. - Given 크기 상한 초과
data, When set, Thenstate_too_large로 저장 거부된다. Given 유효 UTF-8 + 상한 이내, Then core 가 내용 해석 없이 그대로 저장한다. - Given 여러 slot_id, When batched 조회, Then 각 slot_id 별
{strategy_id: {version,data,updated_at}}맵으로 그룹되어 반환된다(C-1 조립 입력). - Given PG 구현과 in-memory 구현, When 동일 시나리오 테스트, Then 두 구현이 동일한 CAS 의미를 보인다.
Impacted Area
- Docs: docs/data-model.md(
slot_strategy_state스키마), docs/project-structure.md(저장소 구조 — REQ-082) - Modules: trex_core/adapters/persistence/postgresql.py(PG StrategyStateStore + 마이그레이션 SQL), trex_core/domain/slot/in_memory_repository.py 또는 신규 모듈(in-memory), 신규 포트 정의(예: trex_core/application/ports.py 또는 strategy_state 모듈)
- Tests: tests/adapters/persistence/(PG CAS 게이트), tests/(in-memory CAS 6 케이스 — commit/version_conflict/occupancy_changed/slot_inactive/state_too_large/first-create + 멱등)
Notes
- occupancy_seq 컬럼은 REQ-081(슬롯 점유 가드)과 짝을 이룬다 — 본 REQ 는 저장·CAS, REQ-081 은 슬롯 측 occupancy_seq 부여·bump·close 삭제를 소유한다.
- write RPC 계약(요청/응답 shape, reject reason 운반)은 REQ-080 이 소유한다. 본 REQ 는 저장 의미.
- 단일 writer 전제(해당 slot·strategy 데몬 1개). CAS 는 재시도/중복·점유전환 안전용이지 다중 writer 동시성 제어가 아니다.
- 출처: dcy-028 FR-2, OQ-1(인코딩/상한), OQ-4(별도 테이블+맵+slot_id 키), R-2/R-3.
Change Log
CHG-20260615-03
- Date: 2026-06-15
- Author: Justin Ko
- Type: status
- Summary: Approved → Implemented (confirm-req-implemented). 근거: BAT-042(release-candidate) verification —
slot_strategy_state테이블(마이그 015) +StrategyStateStore/InMemoryStrategyStateStore/PgStrategyStateStore+ occupancy_seq·version CAS + opaque UTF-8·size cap. AC-1~6 evidence:tests/application/test_strategy_state_store.py(CAS 6 케이스+ABA+batched+delete) +test_postgresql_repository.py::test_strategy_state_store_pg(PG 게이트). 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(confirmed, Open OQ 0건, OQ-1/OQ-4 정합) 일치. blocker 없음. REQ-080/081/082 + REQ-073/074 CHG 와 동일 batch 편성 예정.
CHG-20260615-01
- Date: 2026-06-15
- Author: Justin Ko
Change Summary
- dcy-028 FR-2/OQ-1/OQ-4 로부터 최초 생성(Proposed). slot_strategy_state 저장소 + StrategyStateStore 포트 + occupancy_seq·version CAS + opaque UTF-8 data + 2단 size cap.
Intent
- 전략 opaque 상태를 슬롯 수명에 묶어 server-side 영속화 — 데몬 재시작/장애에도 상태 보존, orphan-cleanup 제거.
Acceptance Criteria Delta
- Added: first-create/version CAS/occupancy CAS/size cap/batched 조회/PG·in-memory 동등 6개 기준
- Updated: 없음
- Removed: 없음
Impacted Area Delta
- Docs: data-model.md, project-structure.md(REQ-082)
- Modules: postgresql.py, in-memory store, 신규 포트
- Tests: PG CAS, in-memory CAS 6 케이스
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-080/081/082 + REQ-073/074 CHG 와 동일 batch)
Validation Plan
- in-memory CAS 6 케이스 + PG 게이트 테스트로 저장 의미 검증. batched 조회는 C-1 조립 테스트(REQ-073/074)와 연계.