feat: improve batch task controls and release 1.2.0
This commit is contained in:
1 parent
0e13bb5c29
commit
84e183d28d
38 files changed
+632
-147
No files matched your search
@@ -54,6 +54,13 @@ class AutomationStore:
|
||||
|
||||
def put(self, kind: str, key: str, payload: dict) -> dict:
|
||||
with self.connection() as conn:
|
||||
if kind == "batch":
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
row = conn.execute(
|
||||
"SELECT payload FROM automation_records WHERE kind='batch' AND id=?", (key,)
|
||||
).fetchone()
|
||||
if row is None or json.loads(row[0]).get("status") == "deleting":
|
||||
raise ValueError("批次正在删除或已删除,不能继续更新")
|
||||
conn.execute(
|
||||
"INSERT INTO automation_records VALUES (?,?,?,?) ON CONFLICT(kind,id) DO UPDATE SET payload=excluded.payload,updated_at=excluded.updated_at",
|
||||
(kind, key, json.dumps(payload, ensure_ascii=False), time.time()),
|
||||
@@ -78,6 +85,14 @@ class AutomationStore:
|
||||
|
||||
def save_job(self, payload: dict) -> dict:
|
||||
with self.connection() as conn:
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
if batch_id := payload.get("batch_id"):
|
||||
row = conn.execute(
|
||||
"SELECT payload FROM automation_records WHERE kind='batch' AND id=?",
|
||||
(batch_id,),
|
||||
).fetchone()
|
||||
if row is None or json.loads(row[0]).get("status") == "deleting":
|
||||
raise ValueError("批次正在删除,不能继续派发任务")
|
||||
conn.execute(
|
||||
"INSERT INTO automation_jobs VALUES (?,?,?,?,?,?) ON CONFLICT(session_id) DO UPDATE SET payload=excluded.payload,status=excluded.status,updated_at=excluded.updated_at",
|
||||
(
|
||||
@@ -106,6 +121,25 @@ class AutomationStore:
|
||||
)
|
||||
return [{**json.loads(row[0]), "status": row[1]} for row in rows]
|
||||
|
||||
def jobs_for_sessions(self, session_ids: list[str]) -> dict[str, dict]:
|
||||
"""Load only metadata belonging to the sessions shown in history."""
|
||||
result = {}
|
||||
with self.connection() as conn:
|
||||
for offset in range(0, len(session_ids), 400):
|
||||
chunk = session_ids[offset : offset + 400]
|
||||
markers = ",".join("?" for _ in chunk)
|
||||
rows = conn.execute(
|
||||
f"SELECT session_id,payload,status FROM automation_jobs WHERE session_id IN ({markers})",
|
||||
chunk,
|
||||
).fetchall()
|
||||
result.update(
|
||||
{
|
||||
row["session_id"]: {**json.loads(row["payload"]), "status": row["status"]}
|
||||
for row in rows
|
||||
}
|
||||
)
|
||||
return result
|
||||
|
||||
def preferences(self) -> dict:
|
||||
return self.get("settings", "reports") or {"formats": ["docx", "xlsx"]}
|
||||
|
||||
@@ -164,8 +198,38 @@ class AutomationStore:
|
||||
conn.commit()
|
||||
return batch
|
||||
|
||||
def begin_delete_batch(self, batch_id: str) -> list[dict] | None:
|
||||
"""Reserve an inactive batch for cleanup before any more jobs can start."""
|
||||
with self.connection() as conn:
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
row = conn.execute(
|
||||
"SELECT payload FROM automation_records WHERE kind='batch' AND id=?",
|
||||
(batch_id,),
|
||||
).fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
batch = json.loads(row[0])
|
||||
active = conn.execute(
|
||||
"SELECT 1 FROM automation_jobs WHERE batch_id=? AND status IN "
|
||||
"('queued','running','task_paused','resuming','finalizing') LIMIT 1",
|
||||
(batch_id,),
|
||||
).fetchone()
|
||||
if batch["status"] == "running" or active:
|
||||
raise ValueError("批次仍有任务执行中或排队中,请等待完成后删除")
|
||||
batch["status"] = "deleting"
|
||||
conn.execute(
|
||||
"UPDATE automation_records SET payload=?,updated_at=? WHERE kind='batch' AND id=?",
|
||||
(json.dumps(batch, ensure_ascii=False), time.time(), batch_id),
|
||||
)
|
||||
jobs = conn.execute(
|
||||
"SELECT payload,status FROM automation_jobs WHERE batch_id=? ORDER BY position",
|
||||
(batch_id,),
|
||||
).fetchall()
|
||||
conn.commit()
|
||||
return [{**json.loads(job[0]), "status": job[1]} for job in jobs]
|
||||
|
||||
def delete_batch(self, batch_id: str) -> bool:
|
||||
"""Remove a batch record; retain executed job metadata and its reports."""
|
||||
"""Remove a batch record and all of its jobs after cleanup."""
|
||||
with self.connection() as conn:
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
row = conn.execute(
|
||||
@@ -175,17 +239,9 @@ class AutomationStore:
|
||||
if row is None:
|
||||
return False
|
||||
batch = json.loads(row[0])
|
||||
active = conn.execute(
|
||||
"SELECT 1 FROM automation_jobs WHERE batch_id=? AND status IN "
|
||||
"('queued','running','task_paused','resuming','finalizing') LIMIT 1",
|
||||
(batch_id,),
|
||||
).fetchone()
|
||||
if batch["status"] == "running" or active:
|
||||
raise ValueError("批次仍有任务执行中或排队中,请等待完成后删除")
|
||||
conn.execute(
|
||||
"DELETE FROM automation_jobs WHERE batch_id=? AND status='pending'",
|
||||
(batch_id,),
|
||||
)
|
||||
if batch.get("status") != "deleting":
|
||||
raise ValueError("批次尚未准备删除")
|
||||
conn.execute("DELETE FROM automation_jobs WHERE batch_id=?", (batch_id,))
|
||||
conn.execute(
|
||||
"DELETE FROM automation_records WHERE kind='batch' AND id=?",
|
||||
(batch_id,),
|
||||
|
||||
Reference in new issue
Block a user