Deliver BAT-005: KIS token Redis cache (REQ-016, minor-change)
Port the trex-orbit Redis token-cache pattern so the KIS access token
survives daemon restarts and is shared across processes, avoiding KIS
token-issuance rate limits. KISBroker._ensure_token now resolves L1
in-memory -> L2 cache -> issue, storing issued tokens back to the cache.
- adapters/broker/token_cache.py: TokenCache protocol + RedisTokenCache
(key trex:broker:kis:{account_ref}:token, token+expiry+app_key suffix
JSON, ex=ttl, best-effort with graceful fallback) + InMemoryTokenCache.
- kis.py: optional token_cache injection.
- runtime config/daemon: TREX_KIS_REDIS_URL wires a RedisTokenCache.
- pyproject: redis>=5.
Verification: 96 passed, ruff clean — cache hit avoids issuance, cache is
shared across instances (restart/multi-process survival), backend errors
fall back to issuance (no regression), and app_key-suffix mismatch
invalidates a stale cache. Tested deterministically with an in-memory
double (no Redis server required). Processed via the minor-change fast
path: REQ-016 -> Implemented, BAT-005 (batch-lite) -> release-candidate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# BAT-005 Implementation
|
||||
|
||||
- Status: completed
|
||||
- Batch: BAT-005
|
||||
|
||||
## Plan Summary
|
||||
- REQ-016: KISBroker 에 선택적 Redis 토큰 캐시(L1 인메모리 → L2 캐시 → 발급) + graceful fallback. orbit Redis 패턴 이식.
|
||||
|
||||
## Changed Files
|
||||
- trex_core/adapters/broker/token_cache.py (신규): `TokenCache` Protocol, `RedisTokenCache`(redis.from_url, 키 `trex:broker:kis:{account_ref}:token`, JSON 토큰+만료+app_key suffix, ex=ttl, 예외 graceful), `InMemoryTokenCache`(더블/폴백).
|
||||
- trex_core/adapters/broker/kis.py: `token_cache` 주입, `_ensure_token` 3-레벨(L1/L2/issue) + 발급 시 store.
|
||||
- trex_core/runtime/config.py: `KISConfig.redis_url` + `TREX_KIS_REDIS_URL`.
|
||||
- trex_core/runtime/daemon.py: redis_url 있으면 `RedisTokenCache` 주입.
|
||||
- pyproject.toml: `redis>=5` 의존.
|
||||
- tests/adapters/broker/test_token_cache.py (신규).
|
||||
|
||||
## Execution Log
|
||||
1. TokenCache 추상화 + Redis/InMemory 구현(app_key suffix 안전, 만료 검증, 예외 graceful).
|
||||
2. KISBroker _ensure_token 3-레벨 + store.
|
||||
3. config/daemon wiring + pyproject redis.
|
||||
4. 테스트 작성, redis 라이브러리 설치 후 실행.
|
||||
|
||||
## Validation
|
||||
- `pytest tests/adapters/broker/test_token_cache.py`: 4 passed (캐시 히트 HTTP 0 / 인스턴스 간 공유 / graceful fallback / app_key suffix 무효화).
|
||||
- 전체 `pytest`: **96 passed** (기존 92 + 신규 4), ruff clean.
|
||||
- 실 Redis 서버 불요: 인메모리 캐시 더블 + httpx.post 스텁으로 결정적 검증. RedisTokenCache 의 redis.from_url 경로는 운영 시 사용(라이브러리 import OK 확인).
|
||||
|
||||
## Remaining Risks
|
||||
- 없음(저위험). Redis 장애 시 graceful fallback(발급 진행). 실 Redis 서버 통합 검증은 운영 환경에서(라이브러리/와이어링 확인 완료).
|
||||
@@ -0,0 +1,28 @@
|
||||
# BAT-005: KIS 토큰 Redis 캐시 (minor-change)
|
||||
|
||||
- Status: release-candidate
|
||||
- Profile: batch-lite
|
||||
- Source Discovery: dcy-003 (REQ-012 운영 견고성 보완)
|
||||
- Included REQ: REQ-016
|
||||
- Excluded REQ: 없음
|
||||
|
||||
## Summary
|
||||
- REQ-016 단일 저위험 Integration 요구사항을 minor-change 로 처리. KISBroker 에 선택적 Redis 토큰 캐시(L1 인메모리 → L2 Redis → 발급)를 더해 재기동/다중 프로세스 토큰 생존 + rate-limit 회피. orbit Redis 캐시 패턴 이식.
|
||||
|
||||
## Scope
|
||||
- In Scope:
|
||||
- `TokenCache` 추상화 + `RedisTokenCache`(redis.from_url, 키 `trex:broker:kis:{account_ref}:token`, app_key suffix 안전, ex=ttl) + 테스트용 인메모리 더블.
|
||||
- KISBroker `_ensure_token` 3-레벨 + graceful fallback. config `TREX_KIS_REDIS_URL` + daemon wiring. pyproject redis 의존.
|
||||
- 캐시 히트/공유/폴백/suffix 단위테스트.
|
||||
- Out of Scope:
|
||||
- 다른 캐시 백엔드(PG/파일), 토큰 외 응답 캐시.
|
||||
|
||||
## Documents
|
||||
- Planning: [planning.md](./planning.md)
|
||||
- Design: none (batch-lite, no external interface/flow change)
|
||||
- Implementation: [implementation.md](./implementation.md)
|
||||
- Verification: [verification.md](./verification.md)
|
||||
|
||||
## Notes
|
||||
- minor-change: 기존 BrokerPort 뒤 토큰 캐시 계층 추가, 외부 인터페이스·슬롯 흐름 불변. design 불요.
|
||||
- 실 Redis 없을 때도 graceful fallback → 단일 데몬 회귀 없음. 테스트는 인메모리 캐시 더블로 결정적 검증(실 Redis 서버 불요).
|
||||
@@ -0,0 +1,32 @@
|
||||
# BAT-005 Planning
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-005
|
||||
- Profile: batch-lite
|
||||
|
||||
## Included REQ
|
||||
- REQ-016 (Integration): KIS 인증 토큰 Redis 캐시
|
||||
|
||||
## Delivery Plan
|
||||
1. `trex_core/adapters/broker/token_cache.py`: `TokenCache` Protocol(load/store) + `RedisTokenCache`(redis.from_url, JSON 토큰+만료+app_key suffix, ex=ttl, 예외 graceful) + `InMemoryTokenCache`(테스트/폴백 더블).
|
||||
2. `kis.py`: `token_cache` 주입, `_ensure_token` = L1 인메모리 → L2 캐시(load, suffix 검증, 만료 확인) → 발급+store.
|
||||
3. `runtime/config.py`: `TREX_KIS_REDIS_URL` → KISConfig.redis_url. `runtime/daemon.py`: redis_url 있으면 RedisTokenCache 주입.
|
||||
4. `pyproject.toml`: `redis>=5` 의존.
|
||||
5. `tests/adapters/broker/test_token_cache.py`: 캐시 히트(HTTP 0)/공유 재사용/graceful fallback/app_key suffix.
|
||||
|
||||
## Dependencies
|
||||
- Internal: REQ-012 KISBroker 확장.
|
||||
- External: redis 라이브러리(+ 운영 시 Redis 서버). 테스트는 인메모리 더블.
|
||||
|
||||
## Design Gate
|
||||
- Design Required Before Implementation: no
|
||||
- Reason: 기존 BrokerPort 뒤 토큰 캐시 계층 추가뿐. 외부 인터페이스/슬롯 런타임 흐름 변경 없음. batch-lite + design 생략(minor-change).
|
||||
|
||||
## Milestones
|
||||
1. M1 — TokenCache + RedisTokenCache + KISBroker 3-레벨.
|
||||
2. M2 — config/daemon wiring + pyproject.
|
||||
3. M3 — 단위테스트 green(히트/공유/폴백/suffix).
|
||||
|
||||
## Risks
|
||||
- R-1 (Low): Redis 장애가 주문 경로를 막음. 대응: 캐시 예외 graceful fallback(발급으로 진행), 캐시는 best-effort.
|
||||
- R-2 (Low): 자격증명 교체 후 stale 토큰. 대응: app_key suffix 검증으로 캐시 무효화(AC-4).
|
||||
@@ -0,0 +1,23 @@
|
||||
# BAT-005 Verification
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-005
|
||||
|
||||
## Acceptance Mapping
|
||||
- REQ-016:
|
||||
- AC1 캐시 히트 → HTTP 발급 없음 → `test_cache_hit_avoids_issuance`(L1 drop 후 L2 히트, token call 1회 유지). **PASS**
|
||||
- AC2 인스턴스 간 공유(재기동/다중프로세스) → `test_shared_cache_across_instances`(B 인스턴스 재발급 0). **PASS**
|
||||
- AC3 graceful fallback → `test_graceful_fallback_when_cache_errors`(캐시 miss/오류 시 발급 진행). **PASS**
|
||||
- AC4 app_key suffix 안전 → `test_app_key_suffix_mismatch_ignores_cache`(자격증명 교체 시 stale 무시 재발급). **PASS**
|
||||
|
||||
## Evidence
|
||||
- Test: `pytest` 4 token-cache passed; 전체 96 passed; ruff clean.
|
||||
- Manual: redis 라이브러리 import + RedisTokenCache wiring 확인. 실 Redis 서버 없이 인메모리 더블로 결정적 검증.
|
||||
|
||||
## no architecture impact confirmed
|
||||
- batch-lite, planning Design Gate=no. 기존 BrokerPort 뒤 토큰 캐시 계층 추가뿐 — 외부 인터페이스/슬롯 런타임 흐름 변경 없음. baseline 문서 영향 없음.
|
||||
|
||||
## Result
|
||||
- Ready for Release: true
|
||||
- Blocking Issues:
|
||||
- 없음. 실 Redis 서버 통합은 운영 환경 검증 사항(라이브러리/와이어링/폴백 검증 완료, 비차단).
|
||||
@@ -12,3 +12,4 @@
|
||||
| BAT-002 | standard | release-candidate | REQ-005, REQ-006, REQ-007, REQ-008, REQ-009 | dcy-002 | [bat-002](./bat-002_20260603_slot-core-daemon-http-api/) |
|
||||
| BAT-003 | batch-lite | release-candidate | REQ-010 | dcy-002 | [bat-003](./bat-003_20260604_daemon-dotenv-config/) |
|
||||
| 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/) |
|
||||
|
||||
Reference in New Issue
Block a user