fix(paper): BAT-039 — paper order seq Redis 영속화 (재시작 멱등 키 충돌 방지, REQ-011/issue #4)
REQ-011 change-req(CHG-20260612-01)→구현→confirm-req-implemented(CHG-20260612-02)
전체 delivery. paper 한정 결정성 버그(프로덕션 무관).
- seq_store.py 신규: SeqStore 포트 + RedisSeqStore(원자 INCR, 재시작 단조·영속)
+ InMemorySeqStore(폴백/테스트). REQ-016 token_cache 패턴 재사용.
- paper.py: optional seq_store 주입. 미주입 시 기존 in-memory 동작 byte-for-byte 유지.
- config.py/daemon.py: TREX_PAPER_REDIS_URL → RedisSeqStore wiring
(key=trex:broker:paper:{instance_key}:order-seq).
- 런타임 Redis 오류는 전파(silent in-memory 폴백 금지 — 버그 재현 방지).
- tests: 재시작 단조성/correlation_id 비충돌/in-memory 폴백/fake redis INCR (5).
434 passed (+5), ruff clean.
REQ-011 Approved→Implemented, BAT-039 release-candidate. issue #4 close.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,9 @@ class PaperBrokerConfig:
|
||||
fill_after_polls: int = 0
|
||||
qty_per_poll: Optional[int] = None
|
||||
reject_symbols: frozenset[str] = frozenset()
|
||||
# REQ-011 CHG-20260612-01 (issue #4): optional Redis URL for a persistent
|
||||
# order-seq store. Empty => in-memory counter (prior behaviour).
|
||||
redis_url: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -257,6 +260,7 @@ class DaemonConfig:
|
||||
reject_symbols=frozenset(
|
||||
s.strip() for s in reject_raw.split(",") if s.strip()
|
||||
),
|
||||
redis_url=os.environ.get("TREX_PAPER_REDIS_URL", "").strip(),
|
||||
)
|
||||
portfolio_hub: Optional[PortfolioHubConfig] = None
|
||||
pf_base = os.environ.get("TREX_PORTFOLIO_HUB_BASE_URL", "").strip()
|
||||
|
||||
@@ -84,10 +84,19 @@ def _build_broker(config: DaemonConfig) -> BrokerPort:
|
||||
base_url=k.base_url, timeout=k.timeout, allow_live=k.allow_live,
|
||||
token_cache=token_cache,
|
||||
)
|
||||
seq_store = None
|
||||
if config.paper.redis_url:
|
||||
from trex_core.adapters.broker.seq_store import RedisSeqStore
|
||||
|
||||
seq_store = RedisSeqStore(
|
||||
config.paper.redis_url,
|
||||
key=f"trex:broker:paper:{config.instance_key}:order-seq",
|
||||
)
|
||||
return PaperBroker(
|
||||
fill_after_polls=config.paper.fill_after_polls,
|
||||
qty_per_poll=config.paper.qty_per_poll,
|
||||
reject_symbols=set(config.paper.reject_symbols),
|
||||
seq_store=seq_store,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user