ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
detections / detections (push) Canceled after 0s
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
package db
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTaskQueuePreservesBootstrapAndFIFOPosition(t *testing.T) {
|
|
d, err := Open(testDSN(t))
|
|
if err != nil {
|
|
t.Skipf("postgres unavailable (%v) - skipping", err)
|
|
}
|
|
defer d.Close()
|
|
|
|
task, err := d.CreateTask("queue metadata", "keep first-run mode", nil, 0, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer d.DeleteTask(task.ID)
|
|
|
|
if err := d.Enqueue(task.ID, "bootstrap"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, err := d.GetTask(task.ID)
|
|
if err != nil || first == nil || first.QueuedAt == nil {
|
|
t.Fatalf("first enqueue: task=%+v err=%v", first, err)
|
|
}
|
|
|
|
// A follow-up/rerun can try to admit an already queued task as resume. The
|
|
// original bootstrap mode and FIFO timestamp must remain authoritative.
|
|
time.Sleep(time.Millisecond)
|
|
if err := d.Enqueue(task.ID, "resume"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
second, err := d.GetTask(task.ID)
|
|
if err != nil || second == nil {
|
|
t.Fatalf("second enqueue: task=%+v err=%v", second, err)
|
|
}
|
|
if second.QueueMode != "bootstrap" {
|
|
t.Fatalf("queue mode=%q, want bootstrap", second.QueueMode)
|
|
}
|
|
if second.QueuedAt == nil || !second.QueuedAt.Equal(*first.QueuedAt) {
|
|
t.Fatalf("repeated enqueue moved FIFO position: first=%v second=%v", first.QueuedAt, second.QueuedAt)
|
|
}
|
|
|
|
// Pausing a queued task removes it from the queue but keeps its required
|
|
// startup mode. A later requeue receives a new tail position.
|
|
if err := d.Dequeue(task.ID, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
paused, err := d.GetTask(task.ID)
|
|
if err != nil || paused == nil || paused.Queued || paused.QueueMode != "bootstrap" {
|
|
t.Fatalf("paused queue metadata: task=%+v err=%v", paused, err)
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
if err := d.Enqueue(task.ID, "bootstrap"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
requeued, err := d.GetTask(task.ID)
|
|
if err != nil || requeued == nil || requeued.QueuedAt == nil {
|
|
t.Fatalf("requeue: task=%+v err=%v", requeued, err)
|
|
}
|
|
if !requeued.QueuedAt.After(*first.QueuedAt) {
|
|
t.Fatalf("requeue did not move to FIFO tail: first=%v requeued=%v", first.QueuedAt, requeued.QueuedAt)
|
|
}
|
|
}
|