71 lines
2.4 KiB
Go
71 lines
2.4 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
|
core "git.yuntuo.hk/k2safe/orbit/model"
|
|
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
|
"git.yuntuo.hk/k2safe/orbit/pulse/service"
|
|
)
|
|
|
|
// CancelTask 将取消意图与开始授权串行化;已开始的尝试仍须确认结果或到期核查。
|
|
func (s *TaskStore) CancelTask(ctx context.Context, token auth.Token, id core.ID, key string, in service.CancelInput) (service.CancelResult, error) {
|
|
var out service.CancelResult
|
|
err := s.transaction(ctx, token, "tasks:cancel", func(tx *sql.Tx, p auth.Permissions) error {
|
|
view, err := readTask(ctx, tx, token.NamespaceID, id, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !p.AllowsQueue(view.QueueID) {
|
|
return fault.NotFound
|
|
}
|
|
identity, cached, err := reserveIdentity(ctx, tx, token.NamespaceID, "task.cancel", string(id), key, "task", id, in)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cached != nil {
|
|
if err := json.Unmarshal(cached, &out); err != nil {
|
|
return err
|
|
}
|
|
out.Deduplicated = true
|
|
return nil
|
|
}
|
|
// 应用额度 → 队列 → 任务 → 尝试 → 许可;取消不获取 Worker 会话锁。
|
|
if _, _, err := lockQueue(ctx, tx, token.NamespaceID, view.QueueID); err != nil {
|
|
return err
|
|
}
|
|
task, err := readExecutionTask(ctx, tx, token.NamespaceID, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
view = task.view
|
|
if view.Revision != in.ExpectedRevision || view.State.Terminal() || view.CancelRequestedAt != nil {
|
|
return fault.Conflict
|
|
}
|
|
var owner sql.NullString
|
|
if err := tx.QueryRowContext(ctx, "SELECT owner_kind FROM pulse_tasks WHERE namespace_id=? AND id=?", token.NamespaceID, id).Scan(&owner); err != nil {
|
|
return err
|
|
}
|
|
if owner.Valid && owner.String != "schedule" {
|
|
return fault.Conflict
|
|
}
|
|
now, err := dbNow(ctx, tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out.Task, err = cancelExecutionTask(ctx, tx, token.NamespaceID, task, now, "CANCEL_REQUESTED")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := appendAudit(ctx, tx, token, identity, id, "task", "task.cancel", in.Reason, map[string]any{"state": view.State, "revision": fmt.Sprint(view.Revision)}, map[string]any{"state": out.Task.State, "revision": fmt.Sprint(out.Task.Revision), "cancel_requested_at": now}); err != nil {
|
|
return err
|
|
}
|
|
return saveIdentity(ctx, tx, token.NamespaceID, identity, out)
|
|
})
|
|
return out, err
|
|
}
|