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 writes its own archive file, archive-WEBHOOKNAME-TARGETNAME-TARGETID.db, named by delivery.ArchiveFileName, in place of one archive per webhook keyed on its UUID. Renaming a webhook or a target renames its archive files (with any -wal and -shm) before the new name is saved, never over an existing file, and moves every one back if a rename or the save fails. The webhook edit, the target edit and target creation share one lock so no two interleave. Deleting a webhook or target leaves its files on disk. Nothing looks for the old archive-WEBHOOKID.db files. The README gives the naming and the recovery steps. Model: opus-5-5
This commit was merged in pull request #418.
This commit is contained in:
@@ -635,3 +635,100 @@ func assertWebhookOfAnotherUser404s(
|
||||
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
||||
|
||||
// renamedTargetName is the name the rename tests give a target.
|
||||
const renamedTargetName = "Long Term"
|
||||
|
||||
// TestHandleTargetEditSubmit_RenamesArchive proves that renaming a
|
||||
// database target renames its archive, that a save that keeps the
|
||||
// name renames nothing, that a target of another type has no archive
|
||||
// to rename, and that a target whose archive cannot be renamed keeps
|
||||
// its stored name. When a file already has the archive's new name,
|
||||
// the edit is refused with an error naming that file.
|
||||
func TestHandleTargetEditSubmit_RenamesArchive(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := setupSourceTest(t)
|
||||
wh := seedWebhookWithRetention(t, env.db, 7)
|
||||
archive := seedTarget(t, env.db, wh.ID, database.TargetTypeDatabase)
|
||||
rename := url.Values{"name": {renamedTargetName}}
|
||||
|
||||
w := submitTargetEdit(env, wh.ID, archive.ID, rename)
|
||||
require.Equal(t, http.StatusSeeOther, w.Code, w.Body.String())
|
||||
assert.Equal(
|
||||
t,
|
||||
[]archiveRename{{archive.ID, wh.Name, renamedTargetName}},
|
||||
env.archives.Renames(),
|
||||
)
|
||||
|
||||
w = submitTargetEdit(env, wh.ID, archive.ID, rename)
|
||||
require.Equal(t, http.StatusSeeOther, w.Code, w.Body.String())
|
||||
assert.Len(
|
||||
t, env.archives.Renames(), 1,
|
||||
"a save that keeps the name renames nothing",
|
||||
)
|
||||
|
||||
httpWebhook, httpTarget := seedHTTPTarget(t, env, "", "")
|
||||
|
||||
w = submitTargetEdit(
|
||||
env, httpWebhook.ID, httpTarget.ID,
|
||||
editForm(editOriginalURL, "", ""),
|
||||
)
|
||||
require.Equal(t, http.StatusSeeOther, w.Code, w.Body.String())
|
||||
assert.Len(
|
||||
t, env.archives.Renames(), 1,
|
||||
"an HTTP target has no archive to rename",
|
||||
)
|
||||
|
||||
again := url.Values{"name": {"Again"}}
|
||||
|
||||
env.archives.FailRenames(archive.ID, errInjectedRename)
|
||||
|
||||
w = submitTargetEdit(env, wh.ID, archive.ID, again)
|
||||
require.Equal(t, http.StatusInternalServerError, w.Code)
|
||||
assert.Equal(
|
||||
t, renamedTargetName, storedTarget(t, env, archive.ID).Name,
|
||||
"a target whose archive was not renamed keeps its name",
|
||||
)
|
||||
|
||||
env.archives.FailRenames(archive.ID, errNameTaken)
|
||||
|
||||
w = submitTargetEdit(env, wh.ID, archive.ID, again)
|
||||
require.Equal(t, http.StatusConflict, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "archive-taken.db")
|
||||
assert.Equal(
|
||||
t, renamedTargetName, storedTarget(t, env, archive.ID).Name,
|
||||
)
|
||||
}
|
||||
|
||||
// TestHandleTargetEditSubmit_FailedSaveRenamesBack proves that when a
|
||||
// database target's archive is renamed but the new name cannot be
|
||||
// saved, the archive is renamed back to the stored name and the
|
||||
// stored name stays.
|
||||
func TestHandleTargetEditSubmit_FailedSaveRenamesBack(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := setupSourceTest(t)
|
||||
wh := seedWebhookWithRetention(t, env.db, 7)
|
||||
archive := seedTarget(t, env.db, wh.ID, database.TargetTypeDatabase)
|
||||
|
||||
failSaveOnTable(t, env.db, "targets")
|
||||
|
||||
form := url.Values{}
|
||||
form.Set("name", renamedTargetName)
|
||||
|
||||
w := submitTargetEdit(env, wh.ID, archive.ID, form)
|
||||
require.Equal(t, http.StatusInternalServerError, w.Code)
|
||||
assert.Equal(
|
||||
t, archive.Name, storedTarget(t, env, archive.ID).Name,
|
||||
)
|
||||
|
||||
assert.Equal(
|
||||
t,
|
||||
[]archiveRename{
|
||||
{archive.ID, wh.Name, renamedTargetName},
|
||||
{archive.ID, wh.Name, archive.Name},
|
||||
},
|
||||
env.archives.Renames(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user