package alert import ( "context" "os" "testing" "time" "github.com/itworx/pulse/internal/database" ) func TestPostgreSQLAlertOperationsAreRevisionSafeAndRestartable(t *testing.T) { dsn := os.Getenv("PULSE_TEST_DATABASE_URL") if dsn == "" { t.Skip("PULSE_TEST_DATABASE_URL is not set") } ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second) defer cancel() pool, err := database.NewPool(ctx, database.Config{URL: dsn, MaxConns: 8, MinConns: 1}) if err != nil { t.Fatal(err) } defer pool.Close() if err := database.Migrate(ctx, pool); err != nil { t.Fatal(err) } document, registry := validDocument(t) document.Enabled = true rules := Repository{Pool: pool, Registry: registry} created, version, err := rules.Create(ctx, "operations-integration", document, "operations test") if err != nil { t.Fatal(err) } store := StateRepository{Pool: pool} base := time.Date(2026, time.January, 4, 12, 0, 0, 0, time.UTC) policy := Policy{PendingSeconds: 0, ResolveSeconds: 0, UnknownBehavior: UnknownRetain} firing, _, _, err := store.ApplyObservation(ctx, StateInput{RuleID: created.ID, RuleVersionID: version.ID, Fingerprint: "operations:test", Policy: policy, Observation: observation(base, "evaluation-1", true)}) if err != nil { t.Fatal(err) } if firing.State != StateFiring { t.Fatalf("state = %s", firing.State) } ack, occurrence, duplicate, err := store.AcknowledgeRevision(ctx, firing.ID, "operator", "ack-operation-1", base.Add(time.Second), firing.Revision) if err != nil || duplicate || ack.State != StateAcknowledged || occurrence.EventType != "acknowledge" { t.Fatalf("ack result=%#v occurrence=%#v duplicate=%v err=%v", ack, occurrence, duplicate, err) } retry, _, duplicate, err := store.AcknowledgeRevision(ctx, firing.ID, "operator", "ack-operation-1", base.Add(time.Second), firing.Revision) if err != nil || !duplicate || retry.Revision != ack.Revision { t.Fatalf("ack retry=%#v duplicate=%v err=%v", retry, duplicate, err) } restarted := StateRepository{Pool: pool} persisted, err := restarted.GetInstance(ctx, firing.ID) if err != nil { t.Fatal(err) } if persisted.State != StateAcknowledged || persisted.AcknowledgedBy != "operator" { t.Fatalf("ack did not survive restart: %#v", persisted) } unack, occurrence, duplicate, err := restarted.Unacknowledge(ctx, firing.ID, "operator", "unack-operation-1", base.Add(2*time.Second), ack.Revision) if err != nil || duplicate || unack.State != StateFiring || unack.AcknowledgedBy != "" || occurrence.EventType != "unacknowledge" { t.Fatalf("unack result=%#v occurrence=%#v duplicate=%v err=%v", unack, occurrence, duplicate, err) } resolved, _, _, err := restarted.ApplyObservation(ctx, StateInput{RuleID: created.ID, RuleVersionID: version.ID, Fingerprint: "operations:test", Policy: policy, Observation: observation(base.Add(3*time.Second), "evaluation-2", false)}) if err != nil { t.Fatal(err) } if resolved.State != StateResolved { t.Fatalf("resolved state was lost after unacknowledge: %#v", resolved) } }