feat(api): 支持取消本地排队任务

This commit is contained in:
chengcheng
2026-06-09 19:09:20 +08:00
parent a8fa8dd212
commit e8df26da9b
6 changed files with 319 additions and 0 deletions
+43
View File
@@ -1452,6 +1452,7 @@ func matchedRateLimitRule(policy map[string]any, metric string) map[string]any {
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/tasks [get]
// @Router /api/v1/tasks [get]
// @Router /tasks [get]
func (s *Server) listTasks(w http.ResponseWriter, r *http.Request) {
user, ok := auth.UserFromContext(r.Context())
if !ok {
@@ -1560,6 +1561,7 @@ func boolValue(body map[string]any, key string) bool {
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/tasks/{taskID} [get]
// @Router /api/v1/tasks/{taskID} [get]
// @Router /tasks/{taskID} [get]
func (s *Server) getTask(w http.ResponseWriter, r *http.Request) {
task, err := s.store.GetTask(r.Context(), r.PathValue("taskID"))
if err == nil {
@@ -1574,6 +1576,45 @@ func (s *Server) getTask(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusInternalServerError, "get task failed")
}
// cancelTask godoc
// @Summary 取消异步任务
// @Description 仅取消仍在网关本地排队且尚未提交上游的任务;任务已运行、已提交上游或已结束时返回不可取消,客户端应继续查询结果。
// @Tags tasks
// @Produce json
// @Security BearerAuth
// @Param taskID path string true "任务 ID"
// @Success 200 {object} TaskCancelResponse
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/tasks/{taskID}/cancel [post]
// @Router /api/v1/tasks/{taskID}/cancel [post]
// @Router /v1/tasks/{taskID}/cancel [post]
// @Router /tasks/{taskID}/cancel [post]
func (s *Server) cancelTask(w http.ResponseWriter, r *http.Request) {
user, ok := auth.UserFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
result, err := s.runner.CancelTask(r.Context(), r.PathValue("taskID"), user)
if err == nil {
writeJSON(w, http.StatusOK, result)
return
}
if store.IsNotFound(err) {
writeError(w, http.StatusNotFound, "task not found")
return
}
if errors.Is(err, runner.ErrTaskAccessDenied) {
writeError(w, http.StatusForbidden, "task access denied")
return
}
s.logger.Error("cancel task failed", "error", err)
writeError(w, http.StatusInternalServerError, "cancel task failed")
}
// taskParamPreprocessing godoc
// @Summary 获取任务参数预处理日志
// @Description 返回指定任务在执行前的参数改写、校验或模板处理日志。
@@ -1587,6 +1628,7 @@ func (s *Server) getTask(w http.ResponseWriter, r *http.Request) {
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/tasks/{taskID}/param-preprocessing [get]
// @Router /api/v1/tasks/{taskID}/param-preprocessing [get]
// @Router /tasks/{taskID}/param-preprocessing [get]
func (s *Server) taskParamPreprocessing(w http.ResponseWriter, r *http.Request) {
task, err := s.store.GetTask(r.Context(), r.PathValue("taskID"))
if err != nil {
@@ -1620,6 +1662,7 @@ func (s *Server) taskParamPreprocessing(w http.ResponseWriter, r *http.Request)
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/tasks/{taskID}/events [get]
// @Router /api/v1/tasks/{taskID}/events [get]
// @Router /tasks/{taskID}/events [get]
func (s *Server) taskEvents(w http.ResponseWriter, r *http.Request) {
task, err := s.store.GetTask(r.Context(), r.PathValue("taskID"))
if err != nil {