Fail deliveries on archive errors; validate expiry at creation (#43)
Some checks failed
check / check (push) Failing after 57s

Two review findings on the database archiving target:

- An archive error now records the attempt as failed with the
  error string and marks the delivery failed, instead of logging
  the error and reporting success. A target that could not do its
  one job must not claim it did.
- The archive expiry is now actually configurable: the add-target
  form gains an expiry field for database targets, and the value
  is validated at creation time via the new
  delivery.ValidateArchiveExpiry (empty, "never", or a positive
  Go duration), rejecting bad values with a 400 at the only place
  a human can fix them, mirroring how Slack target URLs are
  validated at creation.

Test updates: a forced archive failure asserts a failed delivery
with a recorded error and no archive file; config builder tests
cover empty/never/duration and rejection paths; the two engine
tests that exercise the database target now build engines with a
real webhook DB manager since archiving is no longer a no-op; the
reopen-debounce test uses a wider window so parallel test load
cannot make two rapid writes straddle it.
This commit is contained in:
2026-08-07 16:36:43 +00:00
parent 38cfe76d49
commit d35ad0c49e
8 changed files with 345 additions and 47 deletions

View File

@@ -342,33 +342,29 @@ func TestDeliverDatabase_ImmediateSuccess(
t.Parallel()
db := testWebhookDB(t)
e := testEngine(t, 1)
event := seedEvent(t, db, `{"db":"target"}`)
dlv := seedDelivery(
t, db, event.ID, uuid.New().String(),
database.DeliveryStatusPending,
// The database target archives for real now, so the engine
// needs a webhook DB manager to locate the data directory.
e := delivery.NewTestEngineWithDB(
nil,
database.NewTestWebhookDBManager(t.TempDir()),
slog.New(slog.NewTextHandler(
os.Stderr,
&slog.HandlerOptions{Level: slog.LevelDebug},
)),
&http.Client{Timeout: 5 * time.Second},
1,
)
d := &database.Delivery{
EventID: event.ID,
TargetID: dlv.TargetID,
Status: database.DeliveryStatusPending,
Event: event,
Target: database.Target{
Name: "test-db",
Type: database.TargetTypeDatabase,
},
}
d.ID = dlv.ID
event := seedEvent(t, db, `{"db":"target"}`)
d := seedDatabaseTargetDelivery(t, db, event, "")
e.ExportDeliverDatabase(db, d)
var updated database.Delivery
require.NoError(t, db.First(
&updated, "id = ?", dlv.ID,
&updated, "id = ?", d.ID,
).Error)
assert.Equal(t,
@@ -379,7 +375,7 @@ func TestDeliverDatabase_ImmediateSuccess(
var result database.DeliveryResult
require.NoError(t, db.Where(
"delivery_id = ?", dlv.ID,
"delivery_id = ?", d.ID,
).First(&result).Error)
assert.True(t, result.Success)
@@ -1158,7 +1154,19 @@ func TestProcessDelivery_RoutesToCorrectHandler(
t.Parallel()
db := testWebhookDB(t)
e := testEngine(t, 1)
// The database target archives for real now, so the engine
// needs a webhook DB manager to locate the data directory.
e := delivery.NewTestEngineWithDB(
nil,
database.NewTestWebhookDBManager(t.TempDir()),
slog.New(slog.NewTextHandler(
os.Stderr,
&slog.HandlerOptions{Level: slog.LevelDebug},
)),
&http.Client{Timeout: 5 * time.Second},
1,
)
tests := []struct {
name string