Name each database target's archive for its webhook and target (closes #376)
check / check (push) Waiting to run
check / check (push) Waiting to run
Each database target now has its own archive file, archive-WEBHOOKNAME-TARGETNAME-TARGETID.db, instead of one archive-WEBHOOKID.db per webhook. delivery.ArchiveFileName builds the name: each name is lowercased, keeps ASCII letters and digits, turns every other run of characters into one dash, and is cut to 40 characters. A change of webhook or target name renames its archive files under the archive writer's lock, before the new name is saved, and back again if the save fails. A rename never replaces a file: if one already has the new name, the edit is refused. Deleting a target evicts only that target's writer. Archive files are never deleted, and nothing looks for files under the old name. Model: opus-5-5
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
@@ -150,11 +151,42 @@ func (h *Handlers) applyTargetEdit(
|
||||
target.MaxRetries = retries
|
||||
}
|
||||
|
||||
oldName := target.Name
|
||||
target.Name = name
|
||||
target.Config = configJSON
|
||||
|
||||
err = h.db.DB().Save(target).Error
|
||||
// A new name renames the archive file before it is saved (see
|
||||
// delivery.Engine.Rename). If either step fails, it goes back to
|
||||
// the name that is still stored.
|
||||
err = h.renameTargetArchive(target, webhook.Name, oldName, name)
|
||||
if err == nil {
|
||||
err = h.db.DB().Save(target).Error
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
restoreErr := h.renameTargetArchive(
|
||||
target, webhook.Name, name, oldName,
|
||||
)
|
||||
if restoreErr != nil {
|
||||
h.log.Error(
|
||||
"failed to rename archive back",
|
||||
"target_id", target.ID,
|
||||
"error", restoreErr,
|
||||
)
|
||||
}
|
||||
|
||||
if errors.Is(err, delivery.ErrArchiveNameTaken) {
|
||||
http.Error(
|
||||
w,
|
||||
"Not saved: "+err.Error()+
|
||||
". Move that file out of the data directory, "+
|
||||
"then save again.",
|
||||
http.StatusConflict,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
h.serverError(w, r, "failed to update target", err)
|
||||
|
||||
return
|
||||
@@ -165,6 +197,21 @@ func (h *Handlers) applyTargetEdit(
|
||||
)
|
||||
}
|
||||
|
||||
// renameTargetArchive renames a database target's archive file from
|
||||
// the target name oldName to newName. It does nothing when the name
|
||||
// is unchanged; other target types have no archive.
|
||||
func (h *Handlers) renameTargetArchive(
|
||||
target *database.Target,
|
||||
webhookName, oldName, newName string,
|
||||
) error {
|
||||
if h.archives == nil || oldName == newName ||
|
||||
target.Type != database.TargetTypeDatabase {
|
||||
return nil
|
||||
}
|
||||
|
||||
return h.archives.Rename(target.ID, webhookName, newName)
|
||||
}
|
||||
|
||||
// renderTargetEdit renders the target edit page with an optional
|
||||
// error message.
|
||||
func (h *Handlers) renderTargetEdit(
|
||||
|
||||
Reference in New Issue
Block a user