From 011eac76824a6561e64ffd406ed204a4404c6d74 Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 7 Apr 2026 04:51:06 +0900 Subject: [PATCH] =?UTF-8?q?fix(realestate-lab):=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EC=9E=AC=EA=B3=84=EC=82=B0=20DB=20lock=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sqlite3.connect timeout=10 추가 (기본 0초 → 즉시 실패 방지) - run_matching() 단일 connection으로 통합 (프로필 조회~매칭~저장) - matches/refresh 엔드포인트 에러 핸들링 추가 Co-Authored-By: Claude Opus 4.6 --- realestate-lab/app/db.py | 2 +- realestate-lab/app/main.py | 6 +++++- realestate-lab/app/matcher.py | 17 ++++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/realestate-lab/app/db.py b/realestate-lab/app/db.py index 6465b85..2bba4d2 100644 --- a/realestate-lab/app/db.py +++ b/realestate-lab/app/db.py @@ -11,7 +11,7 @@ DB_PATH = "/app/data/realestate.db" def _conn(): - c = sqlite3.connect(DB_PATH) + c = sqlite3.connect(DB_PATH, timeout=10) c.row_factory = sqlite3.Row c.execute("PRAGMA journal_mode=WAL;") c.execute("PRAGMA foreign_keys=ON;") diff --git a/realestate-lab/app/main.py b/realestate-lab/app/main.py index f2292e6..4066239 100644 --- a/realestate-lab/app/main.py +++ b/realestate-lab/app/main.py @@ -159,7 +159,11 @@ def api_matches(page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100)) @app.post("/api/realestate/matches/refresh") def api_matches_refresh(): - run_matching() + try: + run_matching() + except Exception as e: + logger.exception("매칭 실행 실패") + raise HTTPException(status_code=500, detail=str(e)) return {"ok": True} diff --git a/realestate-lab/app/matcher.py b/realestate-lab/app/matcher.py index bfefd4c..e1cc6f6 100644 --- a/realestate-lab/app/matcher.py +++ b/realestate-lab/app/matcher.py @@ -2,7 +2,7 @@ import json import logging from typing import Dict, Any, List -from .db import get_profile, _conn +from .db import _conn, _profile_row_to_dict logger = logging.getLogger("realestate-lab") @@ -115,13 +115,16 @@ def _compute_score( def run_matching(): - """프로필 기반 매칭을 실행하여 결과를 저장한다.""" - profile = get_profile() - if not profile: - logger.info("프로필 미설정 — 매칭 건너뜀") - return - + """프로필 기반 매칭을 실행하여 결과를 저장한다. + 단일 connection으로 프로필 조회 + 매칭 + 저장을 처리하여 DB lock 방지. + """ with _conn() as conn: + profile_row = conn.execute("SELECT * FROM user_profile WHERE id = 1").fetchone() + if not profile_row: + logger.info("프로필 미설정 — 매칭 건너뜀") + return + profile = _profile_row_to_dict(profile_row) + anns = conn.execute( "SELECT * FROM announcements WHERE status IN ('청약예정', '청약중')" ).fetchall()