fix(kis-api): 키움 토큰 갱신 race 제거 (asyncio.Lock + double-check)
장 시작 09:00 토큰 만료 시 여러 잡이 동시 재발급 → 키움 앱키당 토큰 1개 정책으로 무효 토큰을 붙들어 ka10001 전건 실패(ok:0) → 시세 stale(텔레그램 현재가 불일치). KiwoomToken.get()에 락+재확인 추가, _refresh 분리. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,10 +44,19 @@ scheduler = AsyncIOScheduler(timezone="Asia/Seoul")
|
|||||||
class KiwoomToken:
|
class KiwoomToken:
|
||||||
token: str = ""
|
token: str = ""
|
||||||
expires_at: datetime = datetime.min
|
expires_at: datetime = datetime.min
|
||||||
|
_lock = asyncio.Lock()
|
||||||
|
|
||||||
async def get(self, client: httpx.AsyncClient) -> str:
|
async def get(self, client: httpx.AsyncClient) -> str:
|
||||||
if self.token and datetime.now() < self.expires_at:
|
if self.token and datetime.now() < self.expires_at:
|
||||||
return self.token
|
return self.token
|
||||||
|
# 동시 갱신 방지: 락 안에서 재확인(double-check) — 키움은 앱키당 토큰 1개만
|
||||||
|
# 유효(재발급 시 이전 토큰 무효화)하므로 thundering-herd 시 무효 토큰을 붙들게 됨
|
||||||
|
async with self._lock:
|
||||||
|
if self.token and datetime.now() < self.expires_at:
|
||||||
|
return self.token
|
||||||
|
return await self._refresh(client)
|
||||||
|
|
||||||
|
async def _refresh(self, client: httpx.AsyncClient) -> str:
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
f"{KIWOOM_BASE_URL}/oauth2/token",
|
f"{KIWOOM_BASE_URL}/oauth2/token",
|
||||||
json={"grant_type": "client_credentials",
|
json={"grant_type": "client_credentials",
|
||||||
|
|||||||
Reference in New Issue
Block a user