feat: 项目/迭代 CRUD + fix_stuck 加 owner 校验; submit_bug 同机构校验; sd_project_create 写 created_by
This commit is contained in:
parent
33e5a2d045
commit
a3cba2ea49
@ -1,24 +1,33 @@
|
||||
# fix_stuck.dspy - 清除卡住任务的 claimed_by
|
||||
# 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:
|
||||
# 清除 submitted 状态但有 claimed_by 的僵尸任务
|
||||
result = await sor.sqlExe(
|
||||
"UPDATE pipeline_tasks SET claimed_by=NULL WHERE state='submitted' AND claimed_by IS NOT NULL",
|
||||
{})
|
||||
# 同时清除 review 状态但有 claimed_by 的(超时未处理的)
|
||||
result2 = await sor.sqlExe(
|
||||
"UPDATE pipeline_tasks SET claimed_by=NULL WHERE state='review' AND claimed_by IS NOT NULL",
|
||||
{})
|
||||
|
||||
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 claimed_by IS NOT NULL",
|
||||
{})
|
||||
|
||||
"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_submitted": "done",
|
||||
"cleared_review": "done",
|
||||
"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 [])]
|
||||
}
|
||||
|
||||
@ -14,7 +14,10 @@ data = {
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
ok, emsg = await check_project_owner(data.get('project_id', ''), user_id, sor)
|
||||
if not ok:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||
await sor.C('sd_iterations', data)
|
||||
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3,"user_data": data}
|
||||
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3},"user_data": data}
|
||||
except Exception as e:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||
|
||||
@ -8,6 +8,12 @@ if not rec_id:
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
recs = await sor.sqlExe("SELECT project_id FROM sd_iterations WHERE id=${id}$", {"id": rec_id})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
pid = getattr(recs[0], 'project_id', '') if recs else ''
|
||||
ok, emsg = await check_project_owner(pid, user_id, sor)
|
||||
if not ok:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||
await sor.D('sd_iterations', {'id': rec_id})
|
||||
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||
except Exception as e:
|
||||
|
||||
@ -20,6 +20,12 @@ if 'priority' in params_kw:
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
recs = await sor.sqlExe("SELECT project_id FROM sd_iterations WHERE id=${id}$", {"id": rec_id})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
pid = getattr(recs[0], 'project_id', '') if recs else ''
|
||||
ok, emsg = await check_project_owner(pid, user_id, sor)
|
||||
if not ok:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||
await sor.U('sd_iterations', data)
|
||||
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||
except Exception as e:
|
||||
|
||||
@ -13,12 +13,13 @@ data = {
|
||||
'pipeline_id': params_kw.get('pipeline_id', '') or 'sdlc_general',
|
||||
'status': params_kw.get('status', ''),
|
||||
'org_id': org_id,
|
||||
'created_by': user_id,
|
||||
'created_at': curDateString(),
|
||||
}
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
await sor.C('sd_projects', data)
|
||||
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3,"user_data": data}
|
||||
return {"widgettype":"Message","options":{"title":"创建成功","message":"ok","cwidth":16,"cheight":9,"timeout":3},"user_data": data}
|
||||
except Exception as e:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":str(e),"cwidth":16,"cheight":9,"timeout":3}}
|
||||
|
||||
@ -8,6 +8,9 @@ if not rec_id:
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
ok, emsg = await check_project_owner(rec_id, user_id, sor)
|
||||
if not ok:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||
await sor.D('sd_projects', {'id': rec_id})
|
||||
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||
except Exception as e:
|
||||
|
||||
@ -24,6 +24,9 @@ if 'status' in params_kw:
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
ok, emsg = await check_project_owner(rec_id, user_id, sor)
|
||||
if not ok:
|
||||
return {"widgettype":"Error","options":{"title":"操作失败","message":emsg,"cwidth":16,"cheight":9,"timeout":3}}
|
||||
await sor.U('sd_projects', data)
|
||||
return {"widgettype":"Message","options":{"title":"操作成功","message":"ok","cwidth":16,"cheight":9,"timeout":3}}
|
||||
except Exception as e:
|
||||
|
||||
@ -24,6 +24,22 @@ data = {
|
||||
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||
# 同机构校验:人类报告的 bug 须与项目同机构(agent 报告跳过)
|
||||
if reporter_type == 'human' and data.get('iteration_id'):
|
||||
it = await sor.sqlExe(
|
||||
"SELECT project_id FROM sd_iterations WHERE id=${iid}$",
|
||||
{"iid": data['iteration_id']})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
pid = getattr(it[0], 'project_id', '') if it else ''
|
||||
if pid:
|
||||
p = await sor.sqlExe("SELECT org_id FROM sd_projects WHERE id=${pid}$", {"pid": pid})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
proj_org = getattr(p[0], 'org_id', '') if p else ''
|
||||
u = await sor.sqlExe("SELECT orgid FROM users WHERE id=${u}$", {"u": user_id})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
user_org = getattr(u[0], 'orgid', '') if u else ''
|
||||
if proj_org and user_org != proj_org:
|
||||
return json.dumps({'status': 'error', 'message': '仅同机构用户可报告 Bug'}, ensure_ascii=False)
|
||||
await sor.C('sd_bugs', data)
|
||||
return json.dumps({'status': 'ok', 'id': data['id']}, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user