定时任务小修:输入模板的字段名去掉首尾空白再存,后台通知任务的异常记日志

- 「 stat_date」原样交给运行,入口节点认不出它、必填项照样报缺:保存时去掉首尾空白,去掉后重名的拦下
- 通知扫描是另起的后台任务、没人 await:出错时异常留在任务里,只会在回收时冒出一句「从未取回的异常」。
  包一层,出错记日志,下一拍照常
This commit is contained in:
ThearchyHelios
2026-10-05 08:47:18 +08:00
parent 6d11145a39
commit bb176f6f9d
3 changed files with 25 additions and 4 deletions
+9 -1
View File
@@ -116,6 +116,14 @@ async def tick(now: datetime | None = None) -> None:
await webhook.notify_due(now)
async def _notify(webhook) -> None: # noqa: ANN001 - 传进来的是 app.scheduler.webhook 模块
"""后台跑一遍通知扫描。出错只记日志:这个任务没人 await,异常留在里面只会变成一句「从未取回的异常」。"""
try:
await webhook.notify_due()
except Exception: # noqa: BLE001
logger.exception("定时任务的通知推送这一拍出错,下一拍照常进行")
class _Runner:
"""调度循环的任务。照 sandbox/manager.py 回收闲置会话的写法:一个 asyncio 任务,出错记日志接着下一拍。"""
@@ -142,7 +150,7 @@ class _Runner:
try:
await fire_due()
if self.notify is None or self.notify.done():
self.notify = asyncio.create_task(webhook.notify_due(), name="agentlab-scheduler-notify")
self.notify = asyncio.create_task(_notify(webhook), name="agentlab-scheduler-notify")
except asyncio.CancelledError:
raise
except Exception: # noqa: BLE001 - 这一拍出错不该让循环停下
+9 -3
View File
@@ -107,13 +107,19 @@ def check_template(template: Any) -> dict[str, str]:
return {}
if not isinstance(template, dict):
raise TemplateError("输入模板需要是「字段名:模板」的对象,例如 stat_date 对应 {{ schedule.yesterday }}")
for name, text in template.items():
if not isinstance(name, str) or not name.strip():
out: dict[str, str] = {}
for raw, text in template.items():
# 字段名去掉首尾空白再存:「 stat_date」交给运行,入口节点认不出它,必填项照样报缺
name = raw.strip() if isinstance(raw, str) else ""
if not name:
raise TemplateError("输入模板里有空的字段名,请填写工作流的输入字段名")
if name in out:
raise TemplateError(f"输入模板里字段「{name}」写了两次,请只保留一个")
if not isinstance(text, str):
raise TemplateError(f"输入「{name}」的值需要是文本(可以带 {{{{ schedule.yesterday }}}} 这样的变量),当前为「{text}」")
_check_text(name, text)
return dict(template)
out[name] = text
return out
def _check_text(name: str, text: str) -> None:
+7
View File
@@ -124,6 +124,13 @@ def test_bad_templates_explain_in_chinese(template, fragments):
assert fragment in str(caught.value), str(caught.value)
def test_field_names_are_trimmed_and_unique():
assert service.check_template({" stat_date ": "{{ schedule.yesterday }}"}) == {"stat_date": "{{ schedule.yesterday }}"}
with pytest.raises(TemplateError) as caught:
service.check_template({"stat_date": "a", "stat_date ": "b"})
assert "stat_date" in str(caught.value) and "两次" in str(caught.value)
def test_variable_catalog():
items = service.variables(datetime(2026, 10, 5, 1, 0, tzinfo=UTC), "Asia/Shanghai")
names = [i["name"] for i in items]