# fix_stuck.dspy - 清除指定项目卡住任务的 claimed_by(仅项目 owner 可操作) user_id = await get_user() if not user_id: return json.dumps({"error": "未登录"}, ensure_ascii=False) project_id = params_kw.get('project_id', '').strip() if not project_id: return json.dumps({"error": "缺少 project_id"}, ensure_ascii=False) dbname = get_module_dbname('pipeline-sdlc') async with DBPools().sqlorContext(dbname) as sor: ok, emsg = await check_project_owner(project_id, user_id, sor) if not ok: return json.dumps({"error": emsg}, ensure_ascii=False) # 清除该项目 submitted/review 状态但有 claimed_by 的僵尸任务 await sor.sqlExe( "UPDATE pipeline_tasks SET claimed_by=NULL " "WHERE tenant_id=${pid}$ AND state IN ('submitted','review') AND claimed_by IS NOT NULL", {"pid": project_id}) await sor.sqlExe("COMMIT", {}) # 查看还有多少卡住的 stuck = await sor.sqlExe( "SELECT id, title, role, state, claimed_by FROM pipeline_tasks " "WHERE tenant_id=${pid}$ AND claimed_by IS NOT NULL", {"pid": project_id}) await sor.sqlExe("COMMIT", {}) result = { "cleared": "done", "remaining_stuck": [{"id": getattr(t,'id','')[:12], "state": getattr(t,'state',''), "claimed_by": getattr(t,'claimed_by','')[:8]} for t in (stuck or [])] } return json.dumps(result, ensure_ascii=False)