79 lines
2.5 KiB
Go
79 lines
2.5 KiB
Go
package assignment
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestRetryWindowDefaultAndOverride(t *testing.T) {
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", "")
|
|
if got := retryWindow(); got != 120*time.Minute {
|
|
t.Fatalf("default window = %v, want 2h", got)
|
|
}
|
|
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", "45")
|
|
if got := retryWindow(); got != 45*time.Minute {
|
|
t.Fatalf("override window = %v, want 45m", got)
|
|
}
|
|
|
|
// 0 restores the old single-round behaviour.
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", "0")
|
|
if got := retryWindow(); got != 0 {
|
|
t.Fatalf("zero window = %v, want 0", got)
|
|
}
|
|
|
|
// A typo must not disable retries.
|
|
for _, bad := range []string{"abc", "-5", "1.5"} {
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", bad)
|
|
if got := retryWindow(); got != 120*time.Minute {
|
|
t.Fatalf("bad value %q gave %v, want the 2h default", bad, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWithinRetryWindow(t *testing.T) {
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", "120")
|
|
now := time.Now()
|
|
|
|
if !withinRetryWindow(now.Add(-10*time.Minute).Unix(), now) {
|
|
t.Fatal("10 minutes in should still retry")
|
|
}
|
|
if withinRetryWindow(now.Add(-121*time.Minute).Unix(), now) {
|
|
t.Fatal("121 minutes in should give up")
|
|
}
|
|
// Messages queued before this change carry no timestamp; they get a
|
|
// window starting now rather than being dropped.
|
|
if !withinRetryWindow(0, now) {
|
|
t.Fatal("a message without first_queued_at should retry")
|
|
}
|
|
|
|
t.Setenv("ASSIGNMENT_RETRY_WINDOW_MINUTES", "0")
|
|
if withinRetryWindow(now.Add(-time.Second).Unix(), now) {
|
|
t.Fatal("window 0 should never start another round")
|
|
}
|
|
}
|
|
|
|
// Messages already on the ASSIGNMENTS stream when this ships were published
|
|
// with only booking_id and kind. They must still decode and act as round 1.
|
|
func TestAssignmentRequestDecodesOldPayload(t *testing.T) {
|
|
var req assignmentRequest
|
|
if err := json.Unmarshal([]byte(`{"booking_id":664517,"kind":"express"}`), &req); err != nil {
|
|
t.Fatalf("old payload failed to decode: %v", err)
|
|
}
|
|
if req.BookingID != 664517 || req.Kind != kindExpress {
|
|
t.Fatalf("decoded %+v", req)
|
|
}
|
|
if req.Round != 0 || req.FirstQueuedAt != 0 || req.NotBefore != 0 {
|
|
t.Fatalf("new fields should be zero on an old payload, got %+v", req)
|
|
}
|
|
}
|
|
|
|
// requeueNextRound must refuse (return false) rather than panic when
|
|
// JetStream is not connected, so the caller falls back to giving up cleanly.
|
|
func TestRequeueWithoutJetStream(t *testing.T) {
|
|
if requeueNextRound(assignmentRequest{BookingID: 1, Kind: kindExpress, Round: 1}, time.Now()) {
|
|
t.Fatal("requeue should report false with no JetStream connection")
|
|
}
|
|
}
|