122 lines
4.6 KiB
Go
122 lines
4.6 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestCleanupStoppedTaskBatchesAndKeepsDurableStopState(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
cmd := currentCall("cancelled-000")
|
|
for i := 0; i < 205; i++ {
|
|
cmd.EventID = fmt.Sprintf("cancelled-%03d", i)
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := s.PrepareControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop", "stop-batch"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
confirmCleanupFeedback(t, s, "stop-batch", "task.control")
|
|
result, err := s.CleanupStoppedTask(context.Background(), cmd.DispatcherID, "stop-batch")
|
|
if err != nil || result.DeletedRows != 206 {
|
|
t.Fatalf("batched cleanup=%+v err=%v", result, err)
|
|
}
|
|
requireCleanupCount(t, s, "dispatcher_inbox", 0)
|
|
requireCleanupCount(t, s, "dispatcher_outbox", 0)
|
|
requireCleanupCount(t, s, "dispatcher_tasks", 1)
|
|
if admitted, err := s.CanAdmit(cmd.DispatcherID, cmd.TenantID, cmd.TaskID); err != nil || admitted {
|
|
t.Fatalf("stopped task reopened: %t %v", admitted, err)
|
|
}
|
|
}
|
|
|
|
func TestCleanupStoppedTaskKeepsStopProofAcrossPartialFailure(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
cmd := currentCall("cancelled-bad")
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cmd.EventID = "cancelled-good"
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.PrepareControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop", "stop-partial"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
confirmCleanupFeedback(t, s, "stop-partial", "task.control")
|
|
if _, err := s.db.Exec(`CREATE TRIGGER cleanup_one_fault BEFORE DELETE ON dispatcher_inbox WHEN OLD.event_id='cancelled-bad' BEGIN SELECT RAISE(ABORT,'one call failure'); END`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result, err := s.CleanupStoppedTask(context.Background(), cmd.DispatcherID, "stop-partial"); err == nil || result.DeletedRows != 1 {
|
|
t.Fatalf("independent cancelled call was not cleaned: %+v %v", result, err)
|
|
}
|
|
requireCleanupCount(t, s, "dispatcher_inbox", 1)
|
|
requireCleanupCount(t, s, "dispatcher_outbox", 1)
|
|
if _, err := s.db.Exec(`DROP TRIGGER cleanup_one_fault`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result, err := s.CleanupStoppedTask(context.Background(), cmd.DispatcherID, "stop-partial"); err != nil || result.DeletedRows != 2 {
|
|
t.Fatalf("partial stop cleanup did not resume: %+v %v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestCleanupStoppedTaskPreservesAcknowledgmentWhenInterrupted(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
cmd := currentCall("cancelled-context")
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.PrepareControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop", "stop-context"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
confirmCleanupFeedback(t, s, "stop-context", "task.control")
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
if _, err := s.CleanupStoppedTask(ctx, cmd.DispatcherID, "stop-context"); err == nil {
|
|
t.Fatal("interruption was ignored")
|
|
}
|
|
requireCleanupCount(t, s, "dispatcher_inbox", 1)
|
|
requireCleanupCount(t, s, "dispatcher_outbox", 1)
|
|
if result, err := s.CleanupStoppedTask(context.Background(), cmd.DispatcherID, "stop-context"); err != nil || result.DeletedRows != 2 {
|
|
t.Fatalf("restart-style retry=%+v err=%v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestCleanupPendingBatchSeesCancellationAndChangedCommand(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
cmd := currentCall("buffered-stop")
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pending, err := s.ListPendingExecute(cmd.DispatcherID)
|
|
if err != nil || len(pending) != 1 {
|
|
t.Fatalf("pending=%v err=%v", pending, err)
|
|
}
|
|
if err := s.PrepareControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if current, err := s.IsCurrentPending(pending[0]); err != nil || current {
|
|
t.Fatalf("cancelled batch remained eligible: %t %v", current, err)
|
|
}
|
|
if err := s.CompleteControl(cmd.DispatcherID, cmd.TenantID, cmd.TaskID, "stop", "stop-buffered"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
confirmCleanupFeedback(t, s, "stop-buffered", "task.control")
|
|
if _, err := s.CleanupStoppedTask(context.Background(), cmd.DispatcherID, "stop-buffered"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if current, err := s.IsCurrentPending(pending[0]); err != nil || current {
|
|
t.Fatalf("cleaned batch remained eligible: %t %v", current, err)
|
|
}
|
|
}
|