Move the archive files into their own package (closes #541)
check / check (push) Canceled after 0s

The SQLite archive files the database target writes are now managed by
internal/archive: file names, rotation, the writer of each target,
pruning, renames, the gzipped JSON export, the idle sweep, and the
rename lock, which was Handlers.renameMu. The database target stays in
internal/delivery and writes through archive.Writers; the engine still
closes the writers when it stops, so the stop order is unchanged. The
handlers take the rename lock from archive.Archives.RenameLock, and
rename and evict through archive.Archives.

Exported names drop their Archive prefix in the new package. The tests
moved with the code; the two that check a delivery's recorded attempt
stay in delivery.

Model: opus-5-5
This commit was merged in pull request #552.
This commit is contained in:
2026-10-15 21:03:43 +02:00
parent f10440b7cc
commit 0cdda43e6c
42 changed files with 2178 additions and 1772 deletions
+16 -16
View File
@@ -6,8 +6,8 @@ import (
"net/http"
"time"
"sneak.berlin/go/webhooker/internal/archive"
"sneak.berlin/go/webhooker/internal/database"
"sneak.berlin/go/webhooker/internal/delivery"
)
// downloadWriteTimeout is how long one write of a download may wait
@@ -16,7 +16,7 @@ const downloadWriteTimeout = 60 * time.Second
// HandleTargetDownload serves a database target's archive as one
// gzipped JSON file, named for the webhook, the target and the time;
// see delivery.ArchiveExport.WriteGzipJSON for what it holds. Other
// see archive.Export.WriteGzipJSON for what it holds. Other
// target types have no archive and are a 404.
//
// A download runs for as long as the client keeps reading: it reads
@@ -37,7 +37,7 @@ func (h *Handlers) HandleTargetDownload() http.HandlerFunc {
w.Header().Set("Content-Type", "application/gzip")
w.Header().Set(
"Content-Disposition",
`attachment; filename="`+delivery.ArchiveExportFileName(
`attachment; filename="`+archive.ExportFileName(
webhook.Name, target.Name, now,
)+`"`,
)
@@ -82,17 +82,17 @@ func (d downloadWriter) Write(b []byte) (int, error) {
// listTargetArchive lists the archive files of the request's database
// target for export. It reports false once it has written the response.
//
// It holds renameMu, which every archive rename runs under, while it
// reads the stored names and lists the files, so the files it lists
// are the ones those names give. It lets go before the export is
// streamed, which takes renameMu again for each file only while it
// It holds the rename lock, which every archive rename runs under,
// while it reads the stored names and lists the files, so the files it
// lists are the ones those names give. It lets go before the export is
// streamed, which takes the lock again for each file only while it
// finds the file under the names stored then and opens it.
func (h *Handlers) listTargetArchive(
w http.ResponseWriter,
r *http.Request,
) (database.Webhook, *database.Target, *delivery.ArchiveExport, bool) {
h.renameMu.Lock()
defer h.renameMu.Unlock()
) (database.Webhook, *database.Target, *archive.Export, bool) {
h.archives.RenameLock().Lock()
defer h.archives.RenameLock().Unlock()
webhook, target, ok := h.ownedTarget(w, r)
if !ok {
@@ -105,9 +105,9 @@ func (h *Handlers) listTargetArchive(
return database.Webhook{}, nil, nil, false
}
export, err := delivery.NewArchiveExport(
delivery.ArchivePath(h.dbMgr, &webhook, target),
&h.renameMu,
export, err := archive.NewExport(
archive.Path(h.dbMgr, &webhook, target),
h.archives.RenameLock(),
func() (string, error) {
return h.storedArchivePath(webhook.ID, target.ID)
},
@@ -122,9 +122,9 @@ func (h *Handlers) listTargetArchive(
return webhook, target, export, true
}
// storedArchivePath returns the path delivery.ArchivePath gives a
// storedArchivePath returns the path archive.Path gives a
// database target under the names stored for it and its webhook now.
// Its caller holds renameMu. A webhook or target deleted since is still
// Its caller holds the rename lock. A webhook or target deleted since is still
// found, since deleting one leaves its archive files under their names.
func (h *Handlers) storedArchivePath(
webhookID, targetID string,
@@ -143,5 +143,5 @@ func (h *Handlers) storedArchivePath(
return "", err
}
return delivery.ArchivePath(h.dbMgr, &webhook, &target), nil
return archive.Path(h.dbMgr, &webhook, &target), nil
}