feat: professionalize control plane and standalone delivery
This commit is contained in:
102
tests/test_task_runner.py
Normal file
102
tests/test_task_runner.py
Normal file
@ -0,0 +1,102 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from biliup_next.app.task_runner import process_task
|
||||
from biliup_next.core.models import TaskStep
|
||||
|
||||
|
||||
class FakeRunnerRepo:
|
||||
def __init__(self, task, steps: list[TaskStep]) -> None: # type: ignore[no-untyped-def]
|
||||
self.task = task
|
||||
self.steps = steps
|
||||
self.step_updates: list[tuple] = []
|
||||
self.task_updates: list[tuple] = []
|
||||
self.claims: list[tuple[str, str, str]] = []
|
||||
|
||||
def get_task(self, task_id: str): # type: ignore[no-untyped-def]
|
||||
return self.task if task_id == self.task.id else None
|
||||
|
||||
def list_steps(self, task_id: str) -> list[TaskStep]:
|
||||
return list(self.steps) if task_id == self.task.id else []
|
||||
|
||||
def update_step_status(self, task_id: str, step_name: str, status: str, **kwargs) -> None: # type: ignore[no-untyped-def]
|
||||
self.step_updates.append((task_id, step_name, status, kwargs))
|
||||
for index, step in enumerate(self.steps):
|
||||
if step.task_id == task_id and step.step_name == step_name:
|
||||
self.steps[index] = TaskStep(
|
||||
step.id,
|
||||
step.task_id,
|
||||
step.step_name,
|
||||
status,
|
||||
kwargs.get("error_code", step.error_code),
|
||||
kwargs.get("error_message", step.error_message),
|
||||
kwargs.get("retry_count", step.retry_count),
|
||||
kwargs.get("started_at", step.started_at),
|
||||
kwargs.get("finished_at", step.finished_at),
|
||||
)
|
||||
|
||||
def update_task_status(self, task_id: str, status: str, updated_at: str) -> None:
|
||||
self.task_updates.append((task_id, status, updated_at))
|
||||
if task_id == self.task.id:
|
||||
self.task = SimpleNamespace(**{**self.task.__dict__, "status": status, "updated_at": updated_at})
|
||||
|
||||
def claim_step_running(self, task_id: str, step_name: str, *, started_at: str) -> bool:
|
||||
self.claims.append((task_id, step_name, started_at))
|
||||
for index, step in enumerate(self.steps):
|
||||
if step.task_id == task_id and step.step_name == step_name:
|
||||
self.steps[index] = TaskStep(step.id, step.task_id, step.step_name, "running", None, None, step.retry_count, started_at, None)
|
||||
return True
|
||||
|
||||
|
||||
class TaskRunnerTests(unittest.TestCase):
|
||||
def test_process_task_reset_step_marks_task_back_to_pre_step_status(self) -> None:
|
||||
task = SimpleNamespace(id="task-1", status="failed_retryable", updated_at="2026-01-01T00:00:00+00:00")
|
||||
steps = [
|
||||
TaskStep(None, "task-1", "transcribe", "failed_retryable", "ERR", "boom", 1, "2026-01-01T00:00:00+00:00", "2026-01-01T00:01:00+00:00"),
|
||||
]
|
||||
repo = FakeRunnerRepo(task, steps)
|
||||
state = {
|
||||
"repo": repo,
|
||||
"settings": {"ingest": {}, "paths": {}, "comment": {"enabled": True}, "collection": {"enabled": True}, "publish": {}},
|
||||
}
|
||||
|
||||
with patch("biliup_next.app.task_runner.ensure_initialized", return_value=state), patch(
|
||||
"biliup_next.app.task_runner.record_task_action"
|
||||
), patch("biliup_next.app.task_runner.apply_disabled_step_fallbacks", return_value=False), patch(
|
||||
"biliup_next.app.task_runner.next_runnable_step", return_value=(None, None)
|
||||
):
|
||||
result = process_task("task-1", reset_step="transcribe")
|
||||
|
||||
self.assertTrue(result["processed"][0]["reset"])
|
||||
self.assertEqual(repo.step_updates[0][1], "transcribe")
|
||||
self.assertEqual(repo.step_updates[0][2], "pending")
|
||||
self.assertEqual(repo.task_updates[0][1], "created")
|
||||
|
||||
def test_process_task_sets_task_running_before_execute_step(self) -> None:
|
||||
task = SimpleNamespace(id="task-1", status="created", updated_at="2026-01-01T00:00:00+00:00")
|
||||
steps = [
|
||||
TaskStep(None, "task-1", "transcribe", "pending", None, None, 0, None, None),
|
||||
]
|
||||
repo = FakeRunnerRepo(task, steps)
|
||||
state = {
|
||||
"repo": repo,
|
||||
"settings": {"ingest": {}, "paths": {}, "comment": {"enabled": True}, "collection": {"enabled": True}, "publish": {}},
|
||||
}
|
||||
|
||||
with patch("biliup_next.app.task_runner.ensure_initialized", return_value=state), patch(
|
||||
"biliup_next.app.task_runner.record_task_action"
|
||||
), patch("biliup_next.app.task_runner.apply_disabled_step_fallbacks", return_value=False), patch(
|
||||
"biliup_next.app.task_runner.next_runnable_step", side_effect=[("transcribe", None), (None, None)]
|
||||
), patch("biliup_next.app.task_runner.execute_step", return_value={"task_id": "task-1", "step": "transcribe"}):
|
||||
result = process_task("task-1")
|
||||
|
||||
self.assertEqual(repo.claims[0][1], "transcribe")
|
||||
self.assertEqual(repo.task_updates[0][1], "running")
|
||||
self.assertEqual(result["processed"][0]["step"], "transcribe")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user