From d57c0f71ceb87fc6921e1ce80b7b1bf7283c2251 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 8 Sep 2026 18:07:10 +0900 Subject: [PATCH] =?UTF-8?q?fix(B03):=20=EC=A7=81=ED=96=89=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=EC=97=90=EB=8F=84=20=EB=B6=84=EC=84=9D=20?= =?UTF-8?q?=EC=A4=91=20=EC=B0=A8=EB=8B=A8=C2=B7=EA=B0=99=EC=9D=80=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=98=9B=20=ED=96=89=20=EB=82=B4=EB=A6=AC?= =?UTF-8?q?=EA=B8=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 창 넷이 DB·저장소를 함께 써 겹침이 실제로 생기는 자리다. 청크·임시배치 갈래에만 있던 보호막 둘이 직행 `/files` 갈래에는 빠져 있었다. - `is_analysis_running` 가드: 분석 중 업로드를 409 로 막는다. 없으면 분석 2개가 같은 산출물 경로에서 부딪힌다. - `supersede_previous_input_files`: 같은 이름 옛 행을 SUPERSEDED 로 내린다. 없으면 같은 파일이 두 줄로 활성이라 어느 것으로 도는지 순서에 달린다. 세 갈래가 같은 보호막을 쓰는지 지키는 시험을 `tmp/tests` 에 남김. Co-Authored-By: Claude Opus 5 (1M context) --- B03_FileInput/B03_FileInput_Router.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/B03_FileInput/B03_FileInput_Router.py b/B03_FileInput/B03_FileInput_Router.py index 2af94831..76956605 100644 --- a/B03_FileInput/B03_FileInput_Router.py +++ b/B03_FileInput/B03_FileInput_Router.py @@ -22,6 +22,7 @@ from B03_FileInput.B03_FileInput_Repository import ( get_project_storage_relative_path, list_incomplete_upload_sessions, list_project_input_files, + supersede_previous_input_files, ) # 분리 전 이 파일에 있던 이름은 그대로 다시 내보낸다 — 옛 이름을 참조하는 @@ -112,6 +113,7 @@ from common_util.common_util_storage import resolve_stored_project_path from common_util.common_util_workflow import load_project_workflow from common_util.common_util_workflow_state import ( get_workflow_state, + is_analysis_running, ) from config.config_db import get_db_pool from config.config_system import ( @@ -199,6 +201,14 @@ async def upload_project_files( async with pool.acquire() as connection: stored_path = await get_project_storage_relative_path(connection, project_id) project_root = Path(resolve_stored_project_path(stored_path)) + # 분석이 도는 중이면 새 자료를 받지 않는다 — 청크·임시배치 경로와 같은 가드다 + # (2026-09-08). 이 갈래만 빠져 있어 분석 2개가 같은 산출물 경로에서 부딪혔다. + async with connection.cursor(aiomysql.DictCursor) as cursor: + if await is_analysis_running(cursor, str(project_id)): + return JSONResponse( + status_code=409, + content={"status": "error", "message": _ANALYSIS_RUNNING_MESSAGE}, + ) await connection.begin() try: @@ -229,6 +239,14 @@ async def upload_project_files( crs_epsg=int(crs_epsg) if crs_epsg is not None else None, metadata=metadata, ) + # 같은 이름의 옛 행은 내려 둔다 — 청크 경로와 같은 처리다(2026-09-08). + # 이 갈래만 빠져 있어 같은 파일이 두 줄로 활성으로 남았다. + await supersede_previous_input_files( + connection, + project_id, + descriptor.original_filename, + input_file_id, + ) results.append( UploadedFileResult( input_file_id=input_file_id,