feat: support batch repetition and selective case import
This commit is contained in:
1 parent
df66897ff4
commit
4d6560dbd4
16 files changed
+296
-37
No files matched your search
@@ -30,6 +30,7 @@ class BatchRequest(ReportPreferences):
|
||||
device_serial: str = Field(min_length=1, max_length=200)
|
||||
profile: Literal["flash", "pro"] = "flash"
|
||||
stop_on_failure: bool = False
|
||||
repeat_count: int = Field(default=1, ge=1, strict=True)
|
||||
timeout_seconds: int = Field(
|
||||
default_factory=lambda: settings.ARTEMIS_TASK_TIMEOUT_SECONDS,
|
||||
ge=30,
|
||||
@@ -52,6 +53,7 @@ def preferences():
|
||||
return {
|
||||
**store.preferences(),
|
||||
"batch_timeout_seconds": settings.ARTEMIS_TASK_TIMEOUT_SECONDS,
|
||||
"batch_max_executions": settings.ARTEMIS_BATCH_MAX_EXECUTIONS,
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +258,12 @@ def history(
|
||||
[*args, size, (page - 1) * size],
|
||||
).fetchall()
|
||||
items = [dict(row) for row in rows]
|
||||
jobs = store.jobs_for_sessions([item["session_id"] for item in items])
|
||||
for item in items:
|
||||
if item["case_id"]:
|
||||
if job := jobs.get(item["session_id"]):
|
||||
item["name"] = task_import.execution_title(job)
|
||||
item["iteration"] = job.get("iteration", 1)
|
||||
item["repeat_count"] = job.get("repeat_count", 1)
|
||||
elif item["case_id"]:
|
||||
item["name"] = task_import.case_title(item)
|
||||
return {"items": items, "total": total, "page": page, "size": size}
|
||||
@@ -28,7 +28,7 @@ try:
|
||||
from admin_console.services.media_service import media_service
|
||||
from admin_console.services.model_service import model_service
|
||||
from admin_console.services.automation_store import store
|
||||
from admin_console.services.task_import import case_title
|
||||
from admin_console.services.task_import import execution_title
|
||||
except ImportError:
|
||||
from apps.admin_console.core.state import state
|
||||
from apps.admin_console.database.repositories.session_repository import session_repo
|
||||
@@ -36,7 +36,7 @@ except ImportError:
|
||||
from apps.admin_console.services.media_service import media_service
|
||||
from apps.admin_console.services.model_service import model_service
|
||||
from apps.admin_console.services.automation_store import store
|
||||
from apps.admin_console.services.task_import import case_title
|
||||
from apps.admin_console.services.task_import import execution_title
|
||||
|
||||
|
||||
router = APIRouter(tags=["sessions"])
|
||||
@@ -83,7 +83,9 @@ def _list_sessions_sync():
|
||||
if job:
|
||||
case = job.get("case") or {}
|
||||
row_dict["case_id"] = case.get("case_id") or ""
|
||||
row_dict["display_name"] = case_title(case) or row_dict.get("initial_goal")
|
||||
row_dict["display_name"] = execution_title(job) or row_dict.get("initial_goal")
|
||||
row_dict["iteration"] = job.get("iteration", 1)
|
||||
row_dict["repeat_count"] = job.get("repeat_count", 1)
|
||||
row_dict["error"] = job.get("error") or ""
|
||||
if job.get("status") in {"completed", "failed", "cancelled", "interrupted", "skipped"}:
|
||||
row_dict["status"] = job["status"]
|
||||
|
||||
@@ -9,7 +9,7 @@ from uuid import UUID
|
||||
|
||||
from apps.admin_console.core.state import state
|
||||
from apps.admin_console.services.automation_store import RECOVERY_ERRORS, store, new_id
|
||||
from apps.admin_console.services.task_import import case_goal, case_title
|
||||
from apps.admin_console.services.task_import import case_goal, execution_title
|
||||
from artemis.config.settings import settings
|
||||
from artemis.runtime.task_limits import task_timeout
|
||||
|
||||
@@ -297,7 +297,7 @@ async def tick_batches():
|
||||
runtime_overrides=options,
|
||||
session_id=job["session_id"],
|
||||
ingress="batch",
|
||||
display_name=case_title(job["case"]),
|
||||
display_name=execution_title(job),
|
||||
)
|
||||
if response.get("status") == "rejected" or not response.get("tasks"):
|
||||
raise ValueError(response.get("error") or "队列拒绝接收任务")
|
||||
@@ -330,6 +330,15 @@ def has_legacy_replay(batch_id: str) -> bool:
|
||||
|
||||
|
||||
def create_batch(payload: dict) -> dict:
|
||||
repeat_count = payload.get("repeat_count", 1)
|
||||
if type(repeat_count) is not int or repeat_count < 1:
|
||||
raise ValueError("循环次数必须为正整数")
|
||||
cases = payload["cases"]
|
||||
total = len(cases) * repeat_count
|
||||
if not cases or total > settings.ARTEMIS_BATCH_MAX_EXECUTIONS:
|
||||
raise ValueError(
|
||||
f"请选择用例;用例数 × 循环次数不能超过 {settings.ARTEMIS_BATCH_MAX_EXECUTIONS} 次执行"
|
||||
)
|
||||
bid = new_id()
|
||||
batch = {
|
||||
"id": bid,
|
||||
@@ -342,21 +351,28 @@ def create_batch(payload: dict) -> dict:
|
||||
"timeout_seconds": payload.get("timeout_seconds") or settings.ARTEMIS_TASK_TIMEOUT_SECONDS,
|
||||
"stop_on_failure": payload.get("stop_on_failure", False),
|
||||
"request_id": payload.get("request_id"),
|
||||
"repeat_count": repeat_count,
|
||||
"case_count": len(cases),
|
||||
"total_executions": total,
|
||||
}
|
||||
jobs = []
|
||||
for number, case in enumerate(payload["cases"], 1):
|
||||
jobs.append(
|
||||
{
|
||||
"session_id": new_id(),
|
||||
"batch_id": bid,
|
||||
"position": number,
|
||||
"case": case,
|
||||
"status": "pending",
|
||||
"formats": batch["formats"],
|
||||
"created_at": time.time(),
|
||||
"device_serial": batch["device_serial"],
|
||||
}
|
||||
)
|
||||
for iteration in range(1, repeat_count + 1):
|
||||
for number, case in enumerate(cases, 1):
|
||||
jobs.append(
|
||||
{
|
||||
"session_id": new_id(),
|
||||
"batch_id": bid,
|
||||
"position": len(jobs) + 1,
|
||||
"iteration": iteration,
|
||||
"repeat_count": repeat_count,
|
||||
"case_position": number,
|
||||
"case": case,
|
||||
"status": "pending",
|
||||
"formats": batch["formats"],
|
||||
"created_at": batch["created_at"],
|
||||
"device_serial": batch["device_serial"],
|
||||
}
|
||||
)
|
||||
return store.create_batch(batch, jobs, payload)
|
||||
|
||||
|
||||
@@ -412,7 +428,13 @@ def batch_action(batch_id: str, action: str) -> dict:
|
||||
if not failed:
|
||||
raise ValueError("没有可重跑的失败或中断任务")
|
||||
revised = create_batch(
|
||||
{**batch, "name": batch["name"] + " · 失败项重跑", "cases": [j["case"] for j in failed]}
|
||||
{
|
||||
**batch,
|
||||
"name": batch["name"] + " · 失败项重跑",
|
||||
"cases": [j["case"] for j in failed],
|
||||
"repeat_count": 1,
|
||||
"request_id": None,
|
||||
}
|
||||
)
|
||||
return revised
|
||||
else:
|
||||
|
||||
@@ -22,7 +22,7 @@ from artemis.config import IMAGES_DIR, TRACES_PATH, WORKSPACE_ROOT
|
||||
from apps.admin_console.database.repositories.session_repository import SessionRepository
|
||||
from apps.admin_console.database.repositories.step_repository import StepRepository
|
||||
from apps.admin_console.services.automation_store import store, identifier
|
||||
from apps.admin_console.services.task_import import case_title
|
||||
from apps.admin_console.services.task_import import execution_title
|
||||
|
||||
EXPORT_ROOT = WORKSPACE_ROOT / "artifacts" / "reports"
|
||||
EXPORT_LOCK = threading.RLock()
|
||||
@@ -190,7 +190,9 @@ def session_report(session_id: str, db_path=None) -> dict:
|
||||
)
|
||||
return {
|
||||
"id": session_id,
|
||||
"name": case_title(case) or session.get("initial_goal", session_id)[:120],
|
||||
"name": execution_title(meta) or session.get("initial_goal", session_id)[:120],
|
||||
"iteration": meta.get("iteration", 1),
|
||||
"repeat_count": meta.get("repeat_count", 1),
|
||||
"goal": case.get("goal") or session.get("initial_goal", ""),
|
||||
"expected": case.get("expected", ""),
|
||||
"status": status,
|
||||
|
||||
@@ -189,3 +189,11 @@ def case_title(case: dict) -> str:
|
||||
case_id = str(case.get("case_id") or "").strip()
|
||||
name = str(case.get("name") or "").strip()
|
||||
return " ".join(part for part in (case_id, name) if part)
|
||||
|
||||
|
||||
def execution_title(job: dict) -> str:
|
||||
"""Distinguish repeated executions without altering the original case or prompt."""
|
||||
title = case_title(job.get("case") or {})
|
||||
if job.get("repeat_count", 1) > 1:
|
||||
title += f" · 第 {job['iteration']} / {job['repeat_count']} 轮"
|
||||
return title
|
||||
Reference in new issue
Block a user