Spaces:
Runtime error
Runtime error
Claude commited on
fix: 코드 리뷰 지적사항 반영 (db.py 스키마 체크 안정성 개선)
Browse files- _is_connection_error: httpx/ssl 예외 타입 체크 우선 적용, 과도한 키워드("connection","reset") 제거
- check_schema_columns: 루프 즉시 raise → 루프 완주 후 raise (부분 성공 결과 유실 방지)
- _schema(): 예외 삼킬 때 warning 로그 추가
https://claude.ai/code/session_016DE3uHLsVmA5Uv7gZGGaKT
db.py
CHANGED
|
@@ -87,12 +87,25 @@ def _is_rls_permission_error(error: Exception) -> bool:
|
|
| 87 |
|
| 88 |
|
| 89 |
_CONNECTION_ERROR_KEYWORDS = (
|
| 90 |
-
"
|
| 91 |
-
"
|
|
|
|
|
|
|
| 92 |
)
|
| 93 |
|
| 94 |
|
| 95 |
def _is_connection_error(error: Exception) -> bool:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
msg = str(error).lower()
|
| 97 |
return any(k in msg for k in _CONNECTION_ERROR_KEYWORDS)
|
| 98 |
|
|
@@ -145,16 +158,22 @@ def check_schema_columns() -> dict:
|
|
| 145 |
]
|
| 146 |
|
| 147 |
results = {}
|
|
|
|
| 148 |
for key, query_fn in checks:
|
| 149 |
try:
|
| 150 |
query_fn()
|
| 151 |
results[key] = True
|
| 152 |
except Exception as e:
|
| 153 |
if _is_connection_error(e):
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
logger.info("schema_columns 체크 완료: %s", results)
|
| 160 |
return results
|
|
@@ -164,7 +183,8 @@ def _schema() -> dict:
|
|
| 164 |
"""check_schema_columns를 안전하게 호출 — 연결 오류 시 빈 dict 반환."""
|
| 165 |
try:
|
| 166 |
return check_schema_columns()
|
| 167 |
-
except Exception:
|
|
|
|
| 168 |
return {}
|
| 169 |
|
| 170 |
|
|
|
|
| 87 |
|
| 88 |
|
| 89 |
_CONNECTION_ERROR_KEYWORDS = (
|
| 90 |
+
"network", "eof",
|
| 91 |
+
"unreachable", "broken pipe", "remote end closed",
|
| 92 |
+
"connection refused", "connection reset", "connection timed out", "connection closed",
|
| 93 |
+
"ssl", "timed out", "read timeout", "connect timeout",
|
| 94 |
)
|
| 95 |
|
| 96 |
|
| 97 |
def _is_connection_error(error: Exception) -> bool:
|
| 98 |
+
# 예외 타입으로 먼저 확인 (키워드보다 신뢰성 높음)
|
| 99 |
+
try:
|
| 100 |
+
import httpx
|
| 101 |
+
if isinstance(error, (httpx.ConnectError, httpx.TimeoutException,
|
| 102 |
+
httpx.RemoteProtocolError, httpx.ReadError)):
|
| 103 |
+
return True
|
| 104 |
+
except ImportError:
|
| 105 |
+
pass
|
| 106 |
+
import ssl as _ssl
|
| 107 |
+
if isinstance(error, _ssl.SSLError):
|
| 108 |
+
return True
|
| 109 |
msg = str(error).lower()
|
| 110 |
return any(k in msg for k in _CONNECTION_ERROR_KEYWORDS)
|
| 111 |
|
|
|
|
| 158 |
]
|
| 159 |
|
| 160 |
results = {}
|
| 161 |
+
connection_error: Exception | None = None
|
| 162 |
for key, query_fn in checks:
|
| 163 |
try:
|
| 164 |
query_fn()
|
| 165 |
results[key] = True
|
| 166 |
except Exception as e:
|
| 167 |
if _is_connection_error(e):
|
| 168 |
+
connection_error = e
|
| 169 |
+
results[key] = False
|
| 170 |
+
else:
|
| 171 |
+
logger.info("컬럼 미존재 확인 [%s]: %s", key, e)
|
| 172 |
+
results[key] = False
|
| 173 |
+
|
| 174 |
+
if connection_error is not None:
|
| 175 |
+
# 연결 오류 발생 시 결과를 캐시하지 않고 예외 전파 → 다음 호출 시 재시도
|
| 176 |
+
raise RuntimeError(f"Supabase 연결 오류로 스키마 체크 실패: {connection_error}") from connection_error
|
| 177 |
|
| 178 |
logger.info("schema_columns 체크 완료: %s", results)
|
| 179 |
return results
|
|
|
|
| 183 |
"""check_schema_columns를 안전하게 호출 — 연결 오류 시 빈 dict 반환."""
|
| 184 |
try:
|
| 185 |
return check_schema_columns()
|
| 186 |
+
except Exception as e:
|
| 187 |
+
logger.warning("스키마 체크 실패, 기능 플래그를 기본값(False)으로 처리합니다: %s", e)
|
| 188 |
return {}
|
| 189 |
|
| 190 |
|