feat(scanner): POST /api/scanner/cancel/:jobId (admin)
Cancels a pending or running scan job. Responses: 200 with the job id and status on acceptance, 404 for unknown jobs, 409 for jobs already in a terminal state (completed/failed/cancelled). Additive route in the existing admin scanner group; no contract pins affected.
This commit is contained in:
1 parent
30ecdd4bf3
commit
5b81e19f2f
2 files changed
+24
No files matched your search
@@ -3,6 +3,7 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"bookhoard/internal/services"
|
"bookhoard/internal/services"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -209,6 +210,28 @@ func (h *Handler) GetScanSummary(c *echo.Context) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CancelScan handles POST /api/scanner/cancel/:jobId (admin): requests
|
||||||
|
// cancellation of a pending or running scan job. Cancellation is
|
||||||
|
// cooperative — the file currently being processed finishes, the walk
|
||||||
|
// stops at its next context check, and the archive pass is skipped so
|
||||||
|
// unvisited files are never treated as missing.
|
||||||
|
func (h *Handler) CancelScan(c *echo.Context) error {
|
||||||
|
jobID := c.Param("jobId")
|
||||||
|
|
||||||
|
if err := h.worker.CancelJob(jobID); err != nil {
|
||||||
|
if errors.Is(err, services.ErrJobNotFound) {
|
||||||
|
return c.JSON(http.StatusNotFound, map[string]string{"error": "job not found"})
|
||||||
|
}
|
||||||
|
return c.JSON(http.StatusConflict, map[string]string{"error": err.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||||
|
"message": "scan cancellation requested",
|
||||||
|
"job_id": jobID,
|
||||||
|
"status": "cancelled",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// StartWatchModeForLibrary starts watching a specific library's folders
|
// StartWatchModeForLibrary starts watching a specific library's folders
|
||||||
func (h *Handler) StartWatchModeForLibrary(ctx context.Context, libraryID pgtype.UUID, adminID pgtype.UUID) error {
|
func (h *Handler) StartWatchModeForLibrary(ctx context.Context, libraryID pgtype.UUID, adminID pgtype.UUID) error {
|
||||||
h.mu.Lock()
|
h.mu.Lock()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ func registerScannerRoutes(protected, admin *echo.Group, h *handlers.Handler) {
|
|||||||
admin.POST("/scanner/scan", h.ScanLibrary)
|
admin.POST("/scanner/scan", h.ScanLibrary)
|
||||||
admin.POST("/scanner/start", h.StartScanner)
|
admin.POST("/scanner/start", h.StartScanner)
|
||||||
admin.POST("/scanner/stop", h.StopScanner)
|
admin.POST("/scanner/stop", h.StopScanner)
|
||||||
|
admin.POST("/scanner/cancel/:jobId", h.CancelScan)
|
||||||
admin.GET("/scanner/status/:jobId", h.GetScanStatus)
|
admin.GET("/scanner/status/:jobId", h.GetScanStatus)
|
||||||
admin.GET("/scanner/active", h.GetActiveScans)
|
admin.GET("/scanner/active", h.GetActiveScans)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user