server: Go 服务器(REST+WSS 网关+JWT+Argon2+配对+素材直链+任务状态机);修复并发下线 send-on-closed-channel、下发查询 SQL 优先级、配对码原子占用、上传体积上限、JWT 默认密钥告警
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package task
|
||||
|
||||
// 任务状态
|
||||
const (
|
||||
Draft = "draft"
|
||||
PendingReview = "pending_review"
|
||||
Rejected = "rejected"
|
||||
Queued = "queued"
|
||||
Dispatched = "dispatched"
|
||||
Running = "running"
|
||||
Success = "success"
|
||||
Failed = "failed"
|
||||
Suspended = "suspended"
|
||||
Cancelled = "cancelled"
|
||||
)
|
||||
|
||||
// 动作
|
||||
type Action string
|
||||
|
||||
const (
|
||||
ActionSubmit Action = "submit"
|
||||
ActionApprove Action = "approve"
|
||||
ActionReject Action = "reject"
|
||||
ActionResubmit Action = "resubmit"
|
||||
ActionDispatch Action = "dispatch"
|
||||
ActionStart Action = "start"
|
||||
ActionSuccess Action = "success"
|
||||
ActionFail Action = "fail"
|
||||
ActionRetry Action = "retry"
|
||||
ActionSuspend Action = "suspend"
|
||||
ActionResume Action = "resume"
|
||||
ActionCancel Action = "cancel"
|
||||
)
|
||||
|
||||
// transitions 状态转移表
|
||||
var transitions = map[string]map[Action]string{
|
||||
Draft: {
|
||||
ActionSubmit: PendingReview,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
PendingReview: {
|
||||
ActionApprove: Queued,
|
||||
ActionReject: Rejected,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Rejected: {
|
||||
ActionResubmit: PendingReview,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Queued: {
|
||||
ActionDispatch: Dispatched,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Dispatched: {
|
||||
ActionStart: Running,
|
||||
ActionFail: Failed,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Running: {
|
||||
ActionSuccess: Success,
|
||||
ActionFail: Failed,
|
||||
ActionSuspend: Suspended,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Failed: {
|
||||
ActionRetry: Queued,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Suspended: {
|
||||
ActionResume: Queued,
|
||||
ActionCancel: Cancelled,
|
||||
},
|
||||
Success: {},
|
||||
Cancelled: {},
|
||||
}
|
||||
|
||||
// Next 校验并返回下一状态;非法转移返回 ok=false
|
||||
func Next(current string, a Action) (string, bool) {
|
||||
next, ok := transitions[current][a]
|
||||
return next, ok
|
||||
}
|
||||
|
||||
// Can 当前状态是否接受该动作
|
||||
func Can(current string, a Action) bool {
|
||||
_, ok := transitions[current][a]
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package task
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestHappyPath(t *testing.T) {
|
||||
path := []struct {
|
||||
action Action
|
||||
want string
|
||||
}{
|
||||
{ActionSubmit, PendingReview},
|
||||
{ActionApprove, Queued},
|
||||
{ActionDispatch, Dispatched},
|
||||
{ActionStart, Running},
|
||||
{ActionSuccess, Success},
|
||||
}
|
||||
cur := Draft
|
||||
for _, step := range path {
|
||||
next, ok := Next(cur, step.action)
|
||||
if !ok || next != step.want {
|
||||
t.Fatalf("step %s from %s: got %s ok=%v, want %s", step.action, cur, next, ok, step.want)
|
||||
}
|
||||
cur = next
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailureRetry(t *testing.T) {
|
||||
cur, ok := Next(Draft, ActionSubmit)
|
||||
if !ok {
|
||||
t.Fatal("submit failed")
|
||||
}
|
||||
cur, ok = Next(cur, ActionApprove)
|
||||
if !ok {
|
||||
t.Fatal("approve failed")
|
||||
}
|
||||
cur, ok = Next(cur, ActionDispatch)
|
||||
if !ok {
|
||||
t.Fatal("dispatch failed")
|
||||
}
|
||||
cur, ok = Next(cur, ActionStart)
|
||||
if !ok {
|
||||
t.Fatal("start failed")
|
||||
}
|
||||
cur, ok = Next(cur, ActionFail)
|
||||
if !ok || cur != Failed {
|
||||
t.Fatalf("fail: got %s ok=%v", cur, ok)
|
||||
}
|
||||
cur, ok = Next(cur, ActionRetry)
|
||||
if !ok || cur != Queued {
|
||||
t.Fatalf("retry: got %s ok=%v", cur, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuspendResume(t *testing.T) {
|
||||
cur, _ := Next(Running, ActionSuspend)
|
||||
if cur != Suspended {
|
||||
t.Fatalf("suspend: got %s", cur)
|
||||
}
|
||||
cur, ok := Next(cur, ActionResume)
|
||||
if !ok || cur != Queued {
|
||||
t.Fatalf("resume: got %s ok=%v", cur, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIllegalTransitions(t *testing.T) {
|
||||
cases := []struct {
|
||||
cur string
|
||||
action Action
|
||||
}{
|
||||
{Draft, ActionApprove},
|
||||
{PendingReview, ActionStart},
|
||||
{Queued, ActionSuccess},
|
||||
{Success, ActionRetry},
|
||||
{Cancelled, ActionResubmit},
|
||||
{Running, ActionApprove},
|
||||
{Dispatched, ActionSuspend},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if _, ok := Next(c.cur, c.action); ok {
|
||||
t.Fatalf("illegal transition should fail: %s -> %s", c.cur, c.action)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user