diff --git a/internal/delivery/export_test.go b/internal/delivery/export_test.go index b3974c8..9dd2531 100644 --- a/internal/delivery/export_test.go +++ b/internal/delivery/export_test.go @@ -352,6 +352,21 @@ func (e *Engine) ExportFailMissingTarget( e.failMissingTarget(webhookDB, webhookID, d) } +// ExportSendRecoveredDeliveries exposes sendRecoveredDeliveries, so a +// test can hand it a target map that lacks a delivery's target. +func (e *Engine) ExportSendRecoveredDeliveries( + ctx context.Context, + webhookDB *gorm.DB, + deliveries []database.Delivery, + webhookID string, + targetMap map[string]database.Target, + settled map[string]struct{}, +) { + e.sendRecoveredDeliveries( + ctx, webhookDB, deliveries, webhookID, targetMap, settled, + ) +} + // ExportDeliveryCh returns the delivery channel. func (e *Engine) ExportDeliveryCh() chan Task { return e.deliveryCh diff --git a/internal/delivery/terminal_state_test.go b/internal/delivery/terminal_state_test.go index d448271..8eda81a 100644 --- a/internal/delivery/terminal_state_test.go +++ b/internal/delivery/terminal_state_test.go @@ -696,6 +696,53 @@ func TestSweepPending_TargetDeleted(t *testing.T) { assert.Contains(t, last.Error, "was deleted") } +// TestSendRecoveredDeliveries_TargetMissingFromMap: the batch's target +// map is empty when its query failed, so every delivery in the batch is +// looked up on its own. A healthy one is sent to the target that lookup +// finds. +func TestSendRecoveredDeliveries_TargetMissingFromMap( + t *testing.T, +) { + t.Parallel() + + s := newISetup(t) + + targetID := uuid.New().String() + + iCreateTarget( + t, s.MainDB, targetID, s.WebhookID, "found-on-lookup", + database.TargetTypeLog, "", 0, + ) + + event := iSeedEvent( + t, s.WebhookDB, s.WebhookID, `{"map":"empty"}`, + ) + + d := iSeedDelivery( + t, s.WebhookDB, event.ID, targetID, + database.DeliveryStatusPending, + ) + + s.Engine.ExportSendRecoveredDeliveries( + context.Background(), s.WebhookDB, + []database.Delivery{d}, s.WebhookID, + map[string]database.Target{}, nil, + ) + + tasks := fDrain(s.Engine) + require.Len(t, tasks, 1, + "the healthy delivery was not queued exactly once", + ) + assert.Equal(t, d.ID, tasks[0].DeliveryID) + assert.Equal(t, targetID, tasks[0].TargetID) + assert.Equal(t, database.TargetTypeLog, tasks[0].TargetType) + + iAssertStatus( + t, s.WebhookDB, d.ID, + database.DeliveryStatusPending, + ) +} + // TestRecoverPending_TargetUnreadable_LeavesDeliveryAlone: a failed // read of the main database is not a deleted target. Restart recovery // holds every pending delivery of the webhook in one batch, so failing