feat: voortgang delete in headerbar
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,103 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from backend.app.api.errors import AppError
|
||||
from backend.app.api.schemas import TaskCreateResponse
|
||||
from backend.app.db.history_repository import HistoryRepository
|
||||
from backend.app.db.task_repository import TaskRepository
|
||||
from backend.app.security.path_guard import PathGuard
|
||||
from backend.app.tasks_runner import TaskRunner
|
||||
|
||||
|
||||
class DeleteTaskService:
|
||||
def __init__(
|
||||
self,
|
||||
path_guard: PathGuard,
|
||||
repository: TaskRepository,
|
||||
runner: TaskRunner,
|
||||
history_repository: HistoryRepository | None = None,
|
||||
):
|
||||
self._path_guard = path_guard
|
||||
self._repository = repository
|
||||
self._runner = runner
|
||||
self._history_repository = history_repository
|
||||
|
||||
def create_delete_task(self, path: str, recursive: bool = False) -> TaskCreateResponse:
|
||||
try:
|
||||
resolved_target = self._path_guard.resolve_existing_path(path)
|
||||
|
||||
if resolved_target.absolute.is_file():
|
||||
kind = "file"
|
||||
elif resolved_target.absolute.is_dir():
|
||||
kind = "directory"
|
||||
if not recursive and any(resolved_target.absolute.iterdir()):
|
||||
raise AppError(
|
||||
code="directory_not_empty",
|
||||
message="Directory is not empty",
|
||||
status_code=409,
|
||||
details={"path": resolved_target.relative},
|
||||
)
|
||||
else:
|
||||
raise AppError(
|
||||
code="type_conflict",
|
||||
message="Unsupported path type for delete",
|
||||
status_code=409,
|
||||
details={"path": resolved_target.relative},
|
||||
)
|
||||
|
||||
task_id = str(uuid.uuid4())
|
||||
task = self._repository.create_task(
|
||||
operation="delete",
|
||||
source=resolved_target.relative,
|
||||
destination="",
|
||||
task_id=task_id,
|
||||
)
|
||||
self._record_history(
|
||||
entry_id=task_id,
|
||||
operation="delete",
|
||||
status="queued",
|
||||
path=resolved_target.relative,
|
||||
)
|
||||
self._runner.enqueue_delete_path(
|
||||
task_id=task["id"],
|
||||
target=str(resolved_target.absolute),
|
||||
kind=kind,
|
||||
recursive=recursive,
|
||||
)
|
||||
return TaskCreateResponse(task_id=task["id"], status=task["status"])
|
||||
except AppError as exc:
|
||||
self._record_history(
|
||||
operation="delete",
|
||||
status="failed",
|
||||
path=path,
|
||||
error_code=exc.code,
|
||||
error_message=exc.message,
|
||||
finished_at=self._now_iso(),
|
||||
)
|
||||
raise
|
||||
except OSError as exc:
|
||||
error = AppError(
|
||||
code="io_error",
|
||||
message="Filesystem operation failed",
|
||||
status_code=500,
|
||||
details={"reason": str(exc)},
|
||||
)
|
||||
self._record_history(
|
||||
operation="delete",
|
||||
status="failed",
|
||||
path=path,
|
||||
error_code=error.code,
|
||||
error_message=error.message,
|
||||
finished_at=self._now_iso(),
|
||||
)
|
||||
raise error
|
||||
|
||||
def _record_history(self, **kwargs) -> None:
|
||||
if self._history_repository:
|
||||
self._history_repository.create_entry(**kwargs)
|
||||
|
||||
@staticmethod
|
||||
def _now_iso() -> str:
|
||||
return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
|
||||
Reference in New Issue
Block a user