mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 15:31:59 +00:00
9d8b41430e
- 完善口径编辑、只读试运行、统一质量验证与执行语义指纹 - 增加可执行指标约束、有预算的主动调查和过程评测 - 提取发布检查、证据读取与起草服务,支持任务停止、重试和检查点恢复 - 增加版本传递影响分析,修复并发覆盖、敏感值遮罩、异常评分及页面状态问题 - 修复 SQLite 复合查询追溯和 microVM 可选依赖缺失处理 - 纳入当前设计文档及部署配置调整 验证:相关主回归 3822 项通过,4 项跳过、8 项预期失败;补充回归通过。 前端构建、文案检查及 git diff --check 通过。 全量检查仍有环境权限、PostgreSQL 可选依赖和既有部署配置、SQLite 文件基线差异导致的未通过项。
105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
"""后台任务运行时上移到 core/job_runtime.py(docs/design/next-round/00-总方案.md X5)。
|
||
|
||
守三件事:老路径 data/catalog_job_runtime 拿到的是同一个模块(同一条队、同一批名字,起草、剖析的 import 不用改);
|
||
同源队里的事是开放的——新的一种登记一行就和起草、剖析排进同一条队、同源串行;没登记的 kind 当场报错,不会悄悄排成
|
||
一种谁都不认识的事。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import asyncio
|
||
|
||
import pytest
|
||
|
||
from app.core import job_runtime
|
||
|
||
|
||
def test_the_old_path_is_the_same_module():
|
||
from app.data import catalog_job_runtime as old
|
||
from app.data.catalog_job_runtime import lanes
|
||
|
||
assert old is job_runtime
|
||
assert lanes is job_runtime.lanes
|
||
# 起草、剖析照旧从老路径导入,登记的几种事都在
|
||
import app.data.catalog_jobs # noqa: F401
|
||
import app.data.catalog_profile_jobs # noqa: F401
|
||
|
||
assert {"draft", "profile", "sync_draft", "import"} <= set(job_runtime.lane_kinds())
|
||
assert job_runtime.lane_label("profile") == "剖析"
|
||
|
||
|
||
def test_an_unregistered_kind_is_refused():
|
||
lanes = job_runtime.SourceLanes()
|
||
|
||
async def go() -> None:
|
||
with pytest.raises(ValueError, match="没有登记"):
|
||
await lanes.enter("src", "nonsense-kind")
|
||
|
||
asyncio.run(go())
|
||
|
||
|
||
def test_a_registered_label_cannot_change():
|
||
job_runtime.register_lane_kind("test-open-kind", "测试用")
|
||
job_runtime.register_lane_kind("test-open-kind", "测试用") # 同一个叫法再登记无害
|
||
with pytest.raises(ValueError, match="已经登记"):
|
||
job_runtime.register_lane_kind("test-open-kind", "别的叫法")
|
||
|
||
|
||
def test_a_new_kind_queues_behind_the_existing_ones_on_the_same_source():
|
||
"""新登记的一种(第 2 波的后台探查就是这样加进来的)和起草排进同一条队:同源串行,不同源并行。"""
|
||
import app.data.catalog_jobs # noqa: F401 - 登记 draft
|
||
|
||
job_runtime.register_lane_kind("test-introspect", "测试探查")
|
||
lanes = job_runtime.SourceLanes()
|
||
|
||
async def go() -> None:
|
||
first = await lanes.enter("src-a", "draft", "job-1")
|
||
second = await lanes.enter("src-a", "test-introspect", "job-2")
|
||
other = await lanes.enter("src-b", "test-introspect", "job-3")
|
||
assert first.granted.is_set() and not second.granted.is_set()
|
||
assert other.granted.is_set(), "不同源并行"
|
||
assert await lanes.ahead("src-a", "job-2") == ["draft"]
|
||
await first.release()
|
||
await asyncio.wait_for(second.wait(), timeout=1)
|
||
await second.release()
|
||
await other.release()
|
||
|
||
asyncio.run(go())
|
||
|
||
|
||
def test_a_job_without_a_lane_skips_the_queue():
|
||
"""lane_of 返回 None 的任务(以后不占源的评测)不进队、直接执行。"""
|
||
|
||
class _NoLane(job_runtime.JobRun):
|
||
kind = "draft"
|
||
|
||
def lane_of(self, job): # noqa: ANN001
|
||
return None
|
||
|
||
run = _NoLane("whatever")
|
||
assert run.lane_of(object()) is None
|
||
|
||
|
||
def test_starting_an_active_job_twice_does_not_orphan_the_first_task():
|
||
async def go():
|
||
calls = []
|
||
finish = asyncio.Event()
|
||
|
||
class Job:
|
||
def __init__(self, job_id):
|
||
self.job_id, self.task = job_id, None
|
||
|
||
async def run(self):
|
||
calls.append(self.job_id)
|
||
await finish.wait()
|
||
|
||
manager = job_runtime.JobManager(Job, label="幂等启动测试", name="test_start_once")
|
||
manager.start("one")
|
||
manager.start("one")
|
||
await asyncio.sleep(0)
|
||
assert calls == ["one"] and manager.running("one")
|
||
finish.set()
|
||
await manager.wait("one")
|
||
assert not manager.running("one")
|
||
|
||
asyncio.run(go())
|