feat: add audited task review and linked manual retries
This commit is contained in:
76
pulse/service/recovery_test.go
Normal file
76
pulse/service/recovery_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
||||
core "git.yuntuo.hk/k2safe/orbit/model"
|
||||
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
||||
pulse "git.yuntuo.hk/k2safe/orbit/pulse/model"
|
||||
)
|
||||
|
||||
type recoveryValidationStore struct {
|
||||
Store
|
||||
reviews, retries int
|
||||
retry ManualRetryInput
|
||||
}
|
||||
|
||||
func (s *recoveryValidationStore) ReviewTask(context.Context, auth.Token, core.ID, string, ReviewInput) (ReviewResult, error) {
|
||||
s.reviews++
|
||||
return ReviewResult{}, nil
|
||||
}
|
||||
func (s *recoveryValidationStore) RetryTask(_ context.Context, _ auth.Token, _ core.ID, _ string, in ManualRetryInput) (ManualRetryResult, error) {
|
||||
s.retries++
|
||||
s.retry = in
|
||||
return ManualRetryResult{}, nil
|
||||
}
|
||||
|
||||
func TestRecoveryRequiresExplicitEvidenceAndConfirmation(t *testing.T) {
|
||||
id := core.ID(strings.Repeat("1", 32))
|
||||
s := &recoveryValidationStore{}
|
||||
api := New(s)
|
||||
base := ReviewInput{ExpectedRevision: 7, Reason: "verified externally", EvidenceRef: "evidence:record-1", ExecutionSettled: true, Outcome: pulse.TaskFailed, Result: json.RawMessage(`{"n":9007199254740993}`)}
|
||||
for name, change := range map[string]func(*ReviewInput){
|
||||
"no revision": func(v *ReviewInput) { v.ExpectedRevision = 0 },
|
||||
"blank reason": func(v *ReviewInput) { v.Reason = " " },
|
||||
"large reason": func(v *ReviewInput) { v.Reason = strings.Repeat("x", 1025) },
|
||||
"empty evidence": func(v *ReviewInput) { v.EvidenceRef = "" },
|
||||
"secret whitespace": func(v *ReviewInput) { v.EvidenceRef = "receipt:\nvalue" },
|
||||
"too long evidence": func(v *ReviewInput) { v.EvidenceRef = strings.Repeat("x", 513) },
|
||||
"unsettled": func(v *ReviewInput) { v.ExecutionSettled = false },
|
||||
"reopen": func(v *ReviewInput) { v.Outcome = pulse.TaskWaiting },
|
||||
"cancel": func(v *ReviewInput) { v.Outcome = pulse.TaskCancelled },
|
||||
"null": func(v *ReviewInput) { v.Result = json.RawMessage(`null`) },
|
||||
"duplicate fields": func(v *ReviewInput) { v.Result = json.RawMessage(`{"n":1,"n":2}`) },
|
||||
"large result": func(v *ReviewInput) { v.Result = json.RawMessage(`"` + strings.Repeat("a", 256<<10) + `"`) },
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
in := base
|
||||
change(&in)
|
||||
if _, err := api.ReviewTask(context.Background(), auth.Token{}, id, "review", in); fault.Code(err) != "INVALID_ARGUMENT" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
if s.reviews != 0 {
|
||||
t.Fatal("invalid review reached persistence")
|
||||
}
|
||||
if _, err := api.ReviewTask(context.Background(), auth.Token{}, id, "review", base); err != nil || s.reviews != 1 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
in := ManualRetryInput{ExpectedRevision: 7, Reason: "verified retry", EvidenceRef: "evidence:retry", SafeToRetry: true, TaskTimeoutMS: 30000}
|
||||
for _, bad := range []ManualRetryInput{{ExpectedRevision: 7, Reason: in.Reason, EvidenceRef: in.EvidenceRef, TaskTimeoutMS: 30000}, {ExpectedRevision: 7, Reason: in.Reason, EvidenceRef: in.EvidenceRef, SafeToRetry: true}, {ExpectedRevision: 7, Reason: in.Reason, EvidenceRef: in.EvidenceRef, SafeToRetry: true, TaskTimeoutMS: 30*86400000 + 1}} {
|
||||
if _, err := api.RetryTask(context.Background(), auth.Token{}, id, "retry", bad); fault.Code(err) != "INVALID_ARGUMENT" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
tm := time.Date(2026, 9, 17, 12, 0, 0, 0, time.FixedZone("example", 8*60*60))
|
||||
in.AvailableAt = &tm
|
||||
if _, err := api.RetryTask(context.Background(), auth.Token{}, id, "retry", in); err != nil || s.retries != 1 || s.retry.AvailableAt.Location() != time.UTC {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user