Rotate a database target's archive monthly, daily or hourly (closes #379)
check / check (push) Successful in 3m27s

A database target's rotation setting (none, monthly, daily or hourly) puts the UTC period of each event's receive time in its archive file name, so each file holds exactly its period's events. It is on the new webhook page and both target forms, and shown in the target list. Renames move every one of a target's files and move them all back if one fails. The sweep prunes one file at a time under the target's lock and deletes a rotated file it leaves empty. Download opens one file at a time, oldest period first, finding each again under the target's current name. The target list names the current file and totals all of them.

Model: opus-5-5
This commit was merged in pull request #482.
This commit is contained in:
2026-10-03 04:18:37 +02:00
parent d8c60c9b67
commit 8b617efa63
36 changed files with 2125 additions and 406 deletions
+41 -1
View File
@@ -328,13 +328,49 @@ func TestNewTargetViews_Database(t *testing.T) {
assert.Equal(
t,
map[string]string{"Archive Expiry": tc.want},
map[string]string{
"Archive Expiry": tc.want,
"Archive Rotation": rotationNone,
},
fieldMap(view.Config),
)
})
}
}
// TestNewTargetViews_DatabaseRotation proves the target list shows a
// database target's rotation, none when it has none stored.
func TestNewTargetViews_DatabaseRotation(t *testing.T) {
t.Parallel()
// Each stored config, and the rotation the list shows for it.
tests := map[string]string{
"": rotationNone,
`{"rotation":""}`: rotationNone,
}
for _, rotation := range []string{
rotationNone, rotationMonthly, rotationDaily, rotationHourly,
} {
tests[`{"rotation":"`+rotation+`"}`] = rotation
}
for config, want := range tests {
t.Run(config, func(t *testing.T) {
t.Parallel()
view := viewFor(t, database.Target{
Type: database.TargetTypeDatabase,
Config: config,
})
assert.Equal(
t, want, fieldMap(view.Config)["Archive Rotation"],
)
})
}
}
func TestNewTargetViews_Log(t *testing.T) {
t.Parallel()
@@ -382,6 +418,10 @@ func TestNewTargetViews_Unpresentable(t *testing.T) {
Type: database.TargetTypeDatabase,
Config: `{"expiry":"a fortnight"}`,
},
"invalid archive rotation": {
Type: database.TargetTypeDatabase,
Config: weeklyConfig,
},
}
for name, target := range tests {