From d9b612253acd9fedc5eb2564398decbb9f0cd831 Mon Sep 17 00:00:00 2001 From: gahusb Date: Wed, 13 May 2026 19:56:30 +0900 Subject: [PATCH] =?UTF-8?q?fix(stock-lab):=20snapshot=20flow=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20100=EC=A2=85=EB=AA=A9=20+=20busy=5Ftimeout=202?= =?UTF-8?q?=EB=B6=84=20(writer=20=EC=B6=A9=EB=8F=8C=20=EC=99=84=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 자동 잡 16:30 KST 실패 원인: - agent-office httpx timeout 180s - 그러나 snapshot/refresh의 flow 스크래핑(500종목 × 0.2-0.5s) = 100~250s - 180s 초과 시 client timeout → 서버 background 처리 계속 - 곧 /run 호출 → snapshot의 long write transaction과 INSERT 충돌 - WAL은 reader/writer 분리만, writer 두 명은 직렬 → busy_timeout 30s 초과 lock Fix: - DEFAULT_FLOW_TOP_N 500 → 100 (시총 상위 100종목 × 0.2s = ~20s) - busy_timeout 30s → 120s (snapshot write 시간보다 충분히 김) - connect timeout 30s → 120s 외국인 매수 시그널은 대형주에서 의미 큼. 상위 100종목으로 충분. 더 많은 커버리지 필요 시 별도 cron으로 snapshot/refresh와 /run 시간 분리. --- stock-lab/app/screener/router.py | 7 ++++--- stock-lab/app/screener/snapshot.py | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/stock-lab/app/screener/router.py b/stock-lab/app/screener/router.py index bbf6905..43c0cfe 100644 --- a/stock-lab/app/screener/router.py +++ b/stock-lab/app/screener/router.py @@ -46,10 +46,11 @@ def _db_path() -> str: def _conn() -> sqlite3.Connection: # WAL 모드 + busy_timeout으로 동시 read/write lock 회피 - # (snapshot/refresh 직후 /run이 SELECT 시 OperationalError 'database is locked' 방지) - conn = sqlite3.connect(_db_path(), timeout=30.0) + # WAL은 reader vs writer 동시성만 해결 — writer 두 명은 직렬이므로 busy_timeout이 + # snapshot/refresh의 write 시간보다 길어야 함 (네이버 스크래핑 ~20초 + DB upsert). + conn = sqlite3.connect(_db_path(), timeout=120.0) conn.execute("PRAGMA journal_mode=WAL") - conn.execute("PRAGMA busy_timeout=30000") + conn.execute("PRAGMA busy_timeout=120000") return conn diff --git a/stock-lab/app/screener/snapshot.py b/stock-lab/app/screener/snapshot.py index 6633f6a..00a7eb5 100644 --- a/stock-lab/app/screener/snapshot.py +++ b/stock-lab/app/screener/snapshot.py @@ -22,8 +22,11 @@ NAVER_HEADERS = { "Referer": "https://finance.naver.com/", } -DEFAULT_FLOW_TOP_N = 500 +DEFAULT_FLOW_TOP_N = 100 DEFAULT_RATE_LIMIT_SEC = 0.2 +# 시총 상위 100종목 × 0.2초 = ~20초 — agent-office httpx timeout(180s) 안에 여유롭게 완료 +# 외국인 매수 시그널은 대형주에서 의미가 크므로 상위 100종목으로 충분. +# 더 많은 종목이 필요하면 별도 cron으로 분리 권장. @dataclass