Files
DDI/server/internal/app/retention_test.go
T
sir_melonchenandClaude Opus 5.5 dd77485efd feat(server): retention for audit entries and configuration revisions
retention.audit_days and retention.revisions_keep (DDI_RETENTION_*) drive
a cleanup five minutes after the start and then daily. The latest
revision, revisions agents run, fall back to or target, and revisions
with pending deployments are never deleted; deployment rows stay. A
cleanup that deletes anything records retention.cleanup in the audit log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:32:45 +02:00

65 lines
1.7 KiB
Go

// SPDX-License-Identifier: LicenseRef-DDI-Proprietary
package app
import (
"context"
"io"
"log/slog"
"testing"
"time"
"git.beugsiud.de/beug.k/DDI/server/internal/config"
"git.beugsiud.de/beug.k/DDI/server/internal/service"
"git.beugsiud.de/beug.k/DDI/server/internal/store"
"git.beugsiud.de/beug.k/DDI/server/internal/store/storetest"
)
func TestRetentionJob(t *testing.T) {
st := storetest.New(t)
ctx := context.Background()
if err := st.Q().InsertAudit(ctx, &store.AuditEntry{ActorName: "admin", Action: "old.one", ObjectType: "test"}); err != nil {
t.Fatal(err)
}
if _, err := st.Pool().Exec(ctx, `UPDATE audit_log SET at = now() - interval '10 days'`); err != nil {
t.Fatal(err)
}
log := slog.New(slog.NewTextHandler(io.Discard, nil))
cfg := config.Defaults()
core := &Core{Config: cfg, Store: st, Log: log, Service: service.New(service.Options{Store: st, Logger: log})}
// Disabled policy: returns at once.
done := make(chan struct{})
go func() { retention(ctx, core, 0, time.Hour); close(done) }()
select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("disabled retention job did not return")
}
core.Config.Retention.AuditDays = 7
jobCtx, cancel := context.WithCancel(ctx)
done = make(chan struct{})
go func() { retention(jobCtx, core, 10*time.Millisecond, time.Hour); close(done) }()
deadline := time.Now().Add(10 * time.Second)
for {
entries, err := st.Q().ListAudit(ctx, store.AuditFilter{Action: "old.one"})
if err != nil {
t.Fatal(err)
}
if len(entries) == 0 {
break
}
if time.Now().After(deadline) {
t.Fatal("old audit entry was not deleted")
}
time.Sleep(20 * time.Millisecond)
}
cancel()
select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("retention job did not stop")
}
}