internal/adminapi/task_retry_handler.go
Rama main · réplica de lectura del repositorio original.
package adminapi
import (
"context"
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/yeomyeonggeori/blueclaw/internal/connectors"
"github.com/yeomyeonggeori/blueclaw/internal/task"
)
type TaskRunRetryer interface {
RetryTaskRun(context.Context, string) (task.TaskRun, error)
}
type taskRunRetryRequest struct {
TaskRunID string `json:"taskRunID"`
ViewerEmail string `json:"viewerEmail"`
ViewerIsAdmin bool `json:"viewerIsAdmin"`
}
func (taskMonitorHandler TaskMonitorHandler) HandleRetryTaskRun(responseWriter http.ResponseWriter, request *http.Request) {
var retryRequest taskRunRetryRequest
if errorValue := json.NewDecoder(request.Body).Decode(&retryRequest); errorValue != nil {
http.Error(responseWriter, "invalid task run retry request", http.StatusBadRequest)
return
}
taskRunID := strings.TrimSpace(retryRequest.TaskRunID)
if taskRunID == "" {
http.Error(responseWriter, "taskRunID is required", http.StatusBadRequest)
return
}
if !retryRequest.ViewerIsAdmin && strings.TrimSpace(retryRequest.ViewerEmail) == "" {
http.Error(responseWriter, "viewer identity is required", http.StatusBadRequest)
return
}
taskRun, isFound := taskMonitorHandler.TaskRunService.FindTaskRun(taskRunID)
if !isFound {
http.Error(responseWriter, "task run not found", http.StatusNotFound)
return
}
requesterPersonID, isViewerAllowed := taskMonitorHandler.requesterScopeForViewer(retryRequest.ViewerEmail, retryRequest.ViewerIsAdmin)
if !retryRequest.ViewerIsAdmin && strings.TrimSpace(retryRequest.ViewerEmail) != "" && taskMonitorHandler.IdentityService == nil {
http.Error(responseWriter, "task retry is unavailable", http.StatusServiceUnavailable)
return
}
if !isViewerAllowed || (requesterPersonID != "" && taskRun.RequesterPersonID != requesterPersonID) {
http.Error(responseWriter, "task run not found", http.StatusNotFound)
return
}
if taskRun.Status != task.TaskStatusFailed {
http.Error(responseWriter, "task run is not failed", http.StatusConflict)
return
}
if taskMonitorHandler.RetryTaskRun == nil {
http.Error(responseWriter, "task retry is unavailable", http.StatusServiceUnavailable)
return
}
retriedTaskRun, errorValue := taskMonitorHandler.RetryTaskRun.RetryTaskRun(request.Context(), taskRunID)
if errorValue != nil {
taskMonitorHandler.writeRetryTaskRunError(responseWriter, errorValue)
return
}
writeJSON(responseWriter, http.StatusAccepted, map[string]string{"taskRunID": retriedTaskRun.TaskRunID, "status": string(retriedTaskRun.Status)})
}
func (taskMonitorHandler TaskMonitorHandler) writeRetryTaskRunError(responseWriter http.ResponseWriter, errorValue error) {
switch {
case errors.Is(errorValue, task.ErrTaskRunNotFound):
http.Error(responseWriter, "task run not found", http.StatusNotFound)
case errors.Is(errorValue, connectors.ErrTaskRetryConflict):
http.Error(responseWriter, errorValue.Error(), http.StatusConflict)
case errors.Is(errorValue, connectors.ErrTaskRetryUnavailable):
http.Error(responseWriter, errorValue.Error(), http.StatusServiceUnavailable)
default:
http.Error(responseWriter, "task retry is unavailable", http.StatusServiceUnavailable)
}
}