fix(B03): 직접 업로드 마지막 파일 404 + 실패 기록이 실패하던 문제 (E2E 결함 1·4)
결함 1 — 업로드 세션이 인증 세션을 가리고 있었다
- finalize_project_upload가 Depends(verify_session)로 받은 session을 같은 이름으로
덮어써, str(session["role"])이 업로드 세션 행에서 role을 찾다 KeyError를 냈다.
KeyError는 LookupError 하위라 404 {"message": "'role'"}로 나가고 로그도 안 남았다.
- 업로드 세션 변수를 upload_session으로 분리(청크 업로드·finalize·상태 조회 3곳).
- B03_FileInput_Router_Errors.lookup_error_response() 신설: 조회 실패만 404,
KeyError·IndexError는 500 + 예외 로그. 두 라우터의 LookupError 처리 13곳에 적용.
batch 단위 엔드포인트에는 batch_id를, 프로젝트 단위에는 project_id를 로그 필드로 준다.
결함 4 — fail_stage가 예외 문자열을 그대로 넣어 UPDATE가 죽었다
- project_workflow_stages.message는 varchar(255)인데 PermissionError 메시지는 300자를
넘겨 DataError로 실패했고, 단계가 FAILED로 못 가 화면이 영영 "분석 중"이었다.
- 200자로 자르고 말줄임표를 붙인다. 원문은 호출부 로그에 남는다.
검증(실서버, 신규 프로젝트 f45243b3에 표본 5개 직접 청크 업로드):
finalize 성공 11건 / "'role'" 오류 0건, 마지막 파일 complete_upload=true도 성공.
이어서 WF1 자동 분석이 시작됨(stage 0 COMPLETE, stage 1 IN_PROGRESS) — 종전에는
예외가 스케줄링 앞에서 터져 자동 분석이 아예 걸리지 않았다.
ruff format·check 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,7 @@ from B03_FileInput.B03_FileInput_Repository_Temp import (
|
||||
mark_temp_batch_linked,
|
||||
upsert_temp_batch_file,
|
||||
)
|
||||
from B03_FileInput.B03_FileInput_Router_Errors import lookup_error_response
|
||||
from B03_FileInput.B03_FileInput_Schema import (
|
||||
ChunkSessionCreateRequest,
|
||||
ChunkSessionCreateResponse,
|
||||
@@ -232,7 +233,7 @@ async def remove_batch(
|
||||
shutil.rmtree(batch_root, ignore_errors=True)
|
||||
return JSONResponse(content={"status": "success", "batch_id": batch_id})
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except Exception:
|
||||
logger.exception("임시 보관함 삭제 실패: batch_id=%s", batch_id)
|
||||
return JSONResponse(
|
||||
@@ -279,7 +280,7 @@ async def remove_batch_file(
|
||||
}
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except OSError as exc:
|
||||
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
@@ -343,7 +344,7 @@ async def upload_batch_files(
|
||||
batch_id=batch_id, files=results, required_complete=required_complete
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except (OSError, ValueError) as exc:
|
||||
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
@@ -391,7 +392,7 @@ async def create_batch_upload_session(
|
||||
total_chunks=total_chunks,
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except (OSError, ValueError) as exc:
|
||||
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
@@ -447,7 +448,7 @@ async def upload_batch_chunk(
|
||||
chunk_hash=chunk_hash,
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except (OSError, ValueError) as exc:
|
||||
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
@@ -489,7 +490,7 @@ async def get_batch_upload_status(
|
||||
completed_chunk_indexes=completed_indexes,
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except Exception:
|
||||
logger.exception("임시 보관함 업로드 상태 조회 실패: batch_id=%s", batch_id)
|
||||
return JSONResponse(
|
||||
@@ -576,7 +577,7 @@ async def finalize_batch_upload(
|
||||
required_complete=required_complete,
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", batch_id=batch_id)
|
||||
except (OSError, ValueError) as exc:
|
||||
if final_path is not None:
|
||||
final_path.unlink(missing_ok=True)
|
||||
@@ -703,7 +704,7 @@ async def attach_temp_batch(
|
||||
analysis_started=analysis_started,
|
||||
)
|
||||
except LookupError as exc:
|
||||
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
||||
return lookup_error_response(exc, logger, context="B03 보관함", project_id=project_id)
|
||||
except (OSError, ValueError) as exc:
|
||||
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user