fix(logtail): keep mail.log in /data and reconcile stuck rows (v1.x closure phase 2)
test / test (push) Has been cancelled

Move the delivery log from the ephemeral /var/log to /data/log/mail.log so
the lines that resolve a queued send-log row survive a container recreate.
postlogd writes it as postfix, the panel reads it through the selfpost group
(dir 2750, file 0640, normalised every start); backups exclude log/.

Close the residual gap with a queue sweep: rows queued for over two minutes
whose id postqueue -p no longer lists are marked bounced. The sweep waits
until the tailer has read the log to its end and does nothing when the queue
cannot be listed, so a message in flight is never touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mixeme
2026-08-08 11:35:27 +03:00
parent c839f68c57
commit 9d6d89c79d
25 changed files with 549 additions and 72 deletions
+8 -1
View File
@@ -39,6 +39,10 @@ func seedDataDir(t *testing.T) (dataDir, dbPath string) {
writeFile(t, filepath.Join(dataDir, "setup-token"), "secret-token")
writeFile(t, filepath.Join(dataDir, "selfpost.db-wal"), "wal")
writeFile(t, filepath.Join(dataDir, "selfpost.db-shm"), "shm")
// Postfix's delivery log and its rotated files: diagnostic output, not
// state, and the bulkiest thing under /data.
writeFile(t, filepath.Join(dataDir, "log", "mail.log"), "Aug 8 07:26:41 mail postfix/smtp[1]: ABC: to=<a@example.net>, status=sent (ok)")
writeFile(t, filepath.Join(dataDir, "log", "mail.log.1"), "older")
return dataDir, dbPath
}
@@ -104,7 +108,10 @@ func TestCreateIncludesStateExcludesTransient(t *testing.T) {
}
}
// Excluded.
for _, name := range []string{"setup-token", "selfpost.db-wal", "selfpost.db-shm"} {
for _, name := range []string{
"setup-token", "selfpost.db-wal", "selfpost.db-shm",
"log/mail.log", "log/mail.log.1",
} {
if _, ok := files[name]; ok {
t.Errorf("archive should not contain %s", name)
}