Ctrl K
ComunidadGuías…

internal/adminapi/task_retry_handler.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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)
	}
}