85 lines
3.2 KiB
Python
85 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from backend.app.api.errors import AppError
|
|
from backend.app.api.schemas import TaskDetailResponse, TaskListItem, TaskListResponse
|
|
from backend.app.db.history_repository import HistoryRepository
|
|
from backend.app.db.task_repository import TaskRepository
|
|
|
|
FILE_ACTION_CANCELLABLE_OPERATIONS = {"copy", "move", "duplicate", "delete"}
|
|
|
|
|
|
class TaskService:
|
|
def __init__(self, repository: TaskRepository, history_repository: HistoryRepository | None = None):
|
|
self._repository = repository
|
|
self._history_repository = history_repository
|
|
|
|
def create_task(self, operation: str, source: str, destination: str) -> TaskDetailResponse:
|
|
task = self._repository.create_task(operation=operation, source=source, destination=destination)
|
|
return TaskDetailResponse(**task)
|
|
|
|
def get_task(self, task_id: str) -> TaskDetailResponse:
|
|
task = self._repository.get_task(task_id)
|
|
if not task:
|
|
raise AppError(
|
|
code="task_not_found",
|
|
message="Task was not found",
|
|
status_code=404,
|
|
details={"task_id": task_id},
|
|
)
|
|
return TaskDetailResponse(**task)
|
|
|
|
def list_tasks(self) -> TaskListResponse:
|
|
tasks = self._repository.list_tasks()
|
|
return TaskListResponse(
|
|
items=[
|
|
TaskListItem(
|
|
id=task["id"],
|
|
operation=task["operation"],
|
|
status=task["status"],
|
|
source=task["source"],
|
|
destination=task["destination"],
|
|
created_at=task["created_at"],
|
|
finished_at=task["finished_at"],
|
|
)
|
|
for task in tasks
|
|
]
|
|
)
|
|
|
|
def cancel_task(self, task_id: str) -> TaskDetailResponse:
|
|
task = self._repository.get_task(task_id)
|
|
if not task:
|
|
raise AppError(
|
|
code="task_not_found",
|
|
message="Task was not found",
|
|
status_code=404,
|
|
details={"task_id": task_id},
|
|
)
|
|
if task["operation"] not in FILE_ACTION_CANCELLABLE_OPERATIONS:
|
|
raise AppError(
|
|
code="task_not_cancellable",
|
|
message="Task cannot be cancelled",
|
|
status_code=409,
|
|
details={"task_id": task_id, "status": task["status"]},
|
|
)
|
|
if task["status"] not in {"queued", "running", "cancelling"}:
|
|
raise AppError(
|
|
code="task_not_cancellable",
|
|
message="Task cannot be cancelled",
|
|
status_code=409,
|
|
details={"task_id": task_id, "status": task["status"]},
|
|
)
|
|
|
|
updated = self._repository.request_cancellation(task_id)
|
|
if not updated:
|
|
raise AppError(
|
|
code="task_not_cancellable",
|
|
message="Task cannot be cancelled",
|
|
status_code=409,
|
|
details={"task_id": task_id, "status": task["status"]},
|
|
)
|
|
|
|
if updated["status"] == "cancelled" and self._history_repository:
|
|
self._history_repository.update_entry(entry_id=task_id, status="cancelled")
|
|
|
|
return TaskDetailResponse(**updated)
|