feat(B03): 업로드 잠금에 이름을 붙임 — 지금 누가 올리는 중인지 화면에 뜸
계획서 0-8 의 남은 하나. 서버는 분석이 도는 동안 새 자료를 이미 막고 있었고 (`is_analysis_running`), 없던 것은 **막힌 까닭을 사람에게 보이는 것**이었음. 여럿이 한 프로젝트를 보면 「왜 안 올라가지」가 됨. - 분석을 띄우는 **경로 넷 모두** 시작한 사람을 `params.started_by` 로 담음. - `analysis_lock_owner` 가 그 id 로 이름을 붙여 냄 — 옛 자료는 id 가 없어 **이름 없이 잠금만** 돎(막는 것이 먼저). - `/upload-overview` 응답에 `analysis_lock` 을 실어 B03 화면이 띠로 보임. 화면 실측 — 「엄상돈 님이 올린 자료를 분석하는 중입니다」 띠가 경고색으로 뜸(응답을 잠깐 가로채 확인하고 곧바로 되돌림). 지금 도는 분석이 없어 실제 잠금 화면은 다음 업로드 때 볼 것. 시험 넷 추가(도는 중 아님·이름 붙음·옛 자료·경로 넷 대조), 전체 1211 통과·실패 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -268,6 +268,57 @@ async def is_analysis_running(cursor: aiomysql.DictCursor, project_id: str) -> b
|
||||
return not await _surface_run_settled(cursor, project_id)
|
||||
|
||||
|
||||
async def analysis_lock_owner(
|
||||
cursor: aiomysql.DictCursor, project_id: str
|
||||
) -> Dict[str, Any] | None:
|
||||
"""**지금 누가 올리는 중인지** — 도는 중이 아니면 `None`.
|
||||
|
||||
잠금 자체는 `is_analysis_running` 이 판정한다. 여기서는 그 잠금에 **이름을 붙인다** —
|
||||
한 프로젝트를 여럿이 볼 때 「왜 못 올리지」가 아니라 「누가 올리는 중이구나」가 되게.
|
||||
시작한 사람은 `start_stage` 가 담아 둔 `params.started_by`(사용자 id)에서 읽고,
|
||||
이름은 그때그때 `users` 에서 가져온다(옛 자료는 id 가 없어 이름 없이 잠금만 돈다).
|
||||
"""
|
||||
if not await is_analysis_running(cursor, project_id):
|
||||
return None
|
||||
await cursor.execute(
|
||||
"""
|
||||
SELECT params, started_at
|
||||
FROM project_workflow_stages
|
||||
WHERE project_id = %s AND stage_no = 1
|
||||
""",
|
||||
(project_id,),
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if not row:
|
||||
return None
|
||||
raw = row["params"] if isinstance(row, dict) else row[0]
|
||||
started_at = row["started_at"] if isinstance(row, dict) else row[1]
|
||||
params: Dict[str, Any] = {}
|
||||
if isinstance(raw, str):
|
||||
try:
|
||||
params = json.loads(raw)
|
||||
except json.JSONDecodeError:
|
||||
params = {}
|
||||
elif isinstance(raw, dict):
|
||||
params = raw
|
||||
user_id = params.get("started_by")
|
||||
name: str | None = None
|
||||
email: str | None = None
|
||||
if user_id is not None:
|
||||
await cursor.execute("SELECT name, email FROM users WHERE id = %s", (user_id,))
|
||||
user = await cursor.fetchone()
|
||||
if user:
|
||||
name = user["name"] if isinstance(user, dict) else user[0]
|
||||
email = user["email"] if isinstance(user, dict) else user[1]
|
||||
return {
|
||||
"running": True,
|
||||
"user_id": user_id,
|
||||
"name": name,
|
||||
"email": email,
|
||||
"started_at": started_at.isoformat() if started_at else None,
|
||||
}
|
||||
|
||||
|
||||
# 계산이 끝나 사용자의 다음 조작을 기다리는 진행 단계 — 도는 중이 아니다.
|
||||
_SETTLED_SURFACE_STAGES = frozenset({"awaiting_confirmation", "completed", "failed"})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user