retention: write the audit row before the actions_log cap

RetainWithAudit appends the 'retain' audit row inside the same transaction and
before the cap, so the cap counts it. After a run, actions_log holds at most
EMAIL_AGENT_ACTIONS_LOG_MAX_ROWS rows, including the audit row. Adds a test.
This commit is contained in:
Builder
2026-10-13 10:42:44 +11:00
parent e5cce1c93a
commit d8788ef8e7
3 changed files with 50 additions and 7 deletions

View File

@@ -121,6 +121,35 @@ func TestRetainCapsActionsLog(t *testing.T) {
}
}
func TestRetainWithAuditCountsItsOwnRow(t *testing.T) {
s, ctx := testStore(t)
for i := 0; i < 5; i++ {
if err := s.LogAction(ctx, "fetch", "scheduler", "pass"); err != nil {
t.Fatalf("LogAction() %d error = %v", i, err)
}
}
res, err := s.RetainWithAudit(ctx, RetentionPolicy{ActionsLogMaxRows: 3}, "scheduler", "bodies_cleared=0")
if err != nil {
t.Fatalf("RetainWithAudit() error = %v", err)
}
// 5 existing + 1 audit = 6; keep 3, so 3 are deleted.
if res.ActionsDeleted != 3 {
t.Errorf("ActionsDeleted = %d, want 3", res.ActionsDeleted)
}
entries, err := s.RecentActions(ctx, 100)
if err != nil {
t.Fatalf("RecentActions() error = %v", err)
}
if len(entries) != 3 {
t.Fatalf("actions_log rows = %d, want 3 (cap counts the audit row)", len(entries))
}
if entries[0].Action != "retain" {
t.Errorf("newest row action = %q, want retain", entries[0].Action)
}
}
func TestRetainDisabledPolicyIsNoOp(t *testing.T) {
s, ctx := testStore(t)