feat(workbench): keep only actionable notifications

This commit is contained in:
2026-09-24 15:18:18 +08:00
parent e374b5b3cb
commit db092b0f5e
8 changed files with 192 additions and 38 deletions
+77 -25
View File
@@ -179,9 +179,6 @@ class OperationalTaskService:
run = self._new_run(task_id, 1, now)
await self.repo.insert_run(_json(run))
await self._run_event(run, now, queued=True)
await self._notify(
task_id, "task_created", command.title, "工况任务已进入待执行队列", now
)
await self.repo.save_request(
scope, request_id, digest(body), {"task_id": str(task_id)}
)
@@ -602,10 +599,6 @@ class OperationalTaskService:
occurred_at=now,
metadata={"task_id": str(task_id), "run_id": str(active_run["run_id"])},
)
await self._notify(
task_id, "report_updated", command.report.title,
command.report.current_conclusion, now,
)
if current_plan is None:
stored_plan = await self.repo.get_latest_plan(str(task_id))
if stored_plan is not None:
@@ -704,7 +697,7 @@ class OperationalTaskService:
)
await self._task_event(task, now)
await self._notify(
task_id, "action_pending", task["title"], command.reason, now,
task_id, "action_approval_pending", task["title"], command.reason, now,
required_permission=approval_permission,
)
await self._save_request(
@@ -783,9 +776,27 @@ class OperationalTaskService:
)
task = await self.detail(task_id)
outcome = await dispatcher.dispatch(
context=self.context, task=task, action=action, credential=credential
)
try:
outcome = await dispatcher.dispatch(
context=self.context, task=task, action=action, credential=credential
)
except Exception:
async with self.repo.transaction():
await self.repo.lock(f"action:{action_id}")
current = await self._action(task_id, action_id)
if (
current.version == action.version
and current.execution_status == "unknown"
):
await self._notify(
task_id,
"external_coordination_failed",
task.title,
"外部系统提交中断,执行结果未知,请核对回执",
self._now(),
required_permission=action.required_execution_permission,
)
raise
async with self.repo.transaction():
await self.repo.lock(f"request:{scope}:{command.request_id}")
@@ -801,14 +812,24 @@ class OperationalTaskService:
"execution_detail": outcome.detail,
})
await self.repo.update_action(str(task_id), _json(current))
await self._action_event(current, self._now())
outcome_recorded_at = self._now()
await self._action_event(current, outcome_recorded_at)
if outcome.status in {"unknown", "failed", "unsupported"}:
await self._notify(
task_id,
"external_coordination_failed",
task.title,
outcome.detail,
outcome_recorded_at,
required_permission=action.required_execution_permission,
)
if outcome.status in {"succeeded", "failed", "unsupported"}:
task_document = await self._task(task_id)
await self._requeue_task(task_document, self._now())
await self._requeue_task(task_document, outcome_recorded_at)
await self.repo.update_task(
_task_json(OperationalTaskSummary.model_validate(task_document))
)
await self._task_event(task_document, self._now())
await self._task_event(task_document, outcome_recorded_at)
await self._save_request(scope, command.request_id, body, {"action": _json(current)})
return current
@@ -842,19 +863,34 @@ class OperationalTaskService:
current = await self._action(task_id, action_id)
require(current.version == action.version, "VERSION_CONFLICT",
"Action changed while reconciling", status=409)
previous_execution_status = current.execution_status
current = current.model_copy(update={
"version": current.version + 1, "execution_status": outcome.status,
"receipt": outcome.receipt, "execution_detail": outcome.detail,
})
await self.repo.update_action(str(task_id), _json(current))
await self._action_event(current, self._now())
outcome_recorded_at = self._now()
await self._action_event(current, outcome_recorded_at)
if (
outcome.status in {"unknown", "failed", "unsupported"}
and outcome.status != previous_execution_status
):
task = await self._task(task_id)
await self._notify(
task_id,
"external_coordination_failed",
task["title"],
outcome.detail,
outcome_recorded_at,
required_permission=action.required_execution_permission,
)
if outcome.status in {"succeeded", "failed", "unsupported"}:
task_document = await self._task(task_id)
await self._requeue_task(task_document, self._now())
await self._requeue_task(task_document, outcome_recorded_at)
await self.repo.update_task(
_task_json(OperationalTaskSummary.model_validate(task_document))
)
await self._task_event(task_document, self._now())
await self._task_event(task_document, outcome_recorded_at)
await self._save_request(
scope, command.request_id, body, {"action": _json(current)}
)
@@ -961,9 +997,9 @@ class OperationalTaskService:
occurred_at=now,
metadata={"task_id": str(task_id), "namespace": "operational-task"},
)
if task["status"] in {"completed", "failed"}:
if task["status"] == "failed":
await self._notify(
task_id, "task_completed" if task["status"] == "completed" else "task_failed",
task_id, "task_failed",
task["title"], command.detail, now,
)
response = {
@@ -1195,9 +1231,6 @@ class OperationalTaskService:
"version": schedule.version + 1, "updated_at": now,
})
await self.repo.advance_schedule(_json(next_schedule))
await self._notify(
task_id, "task_created", task.title, "定时流程已进入待执行队列", now
)
await self._run_event(run, now, queued=True)
await self._task_event(_task_json(task), now)
task_ids.append(task_id)
@@ -1283,14 +1316,33 @@ class OperationalTaskService:
await self.repo.update_task(_task_json(OperationalTaskSummary.model_validate(task)))
await self._run_event(run_model, now)
await self._task_event(task, now)
if lifecycle in {"completed", "failed"}:
if lifecycle == "failed":
await self._notify(
task_id,
"task_completed" if lifecycle == "completed" else "task_failed",
"task_failed",
task["title"],
"工况任务流程状态已更新",
failure_detail or "工况任务执行失败",
now,
)
elif lifecycle == "waiting_human":
pending_actions = any(
action.approval_status == "pending" for action in actions
)
pending_access = any(
request.get("status") == "pending"
for request in (
await self.repo.list_access_requests(str(task_id))
if hasattr(self.repo, "list_access_requests") else []
)
)
if not pending_actions and not pending_access:
await self._notify(
task_id,
"human_input_required",
task["title"],
"任务等待人工补充信息或业务确认",
now,
)
await self._save_request(scope, command.request_id, body, {"task_id": str(task_id)})
return await self.detail(task_id)