Store events and create deliveries in the delivery engine (closes #544)
check / check (push) Waiting to run

The receiver, resubmit and replay handlers now read and check the
request and make one call. Engine.StoreEvent stores an event with a
pending delivery for each active target and the totals in one
transaction, then queues them; Engine.CreateReplay does the same for
one replay delivery. The handlers take *delivery.Engine, so the
Notifier interface and its bridge are gone, and the engine's notify is
no longer exported. Archives and CircuitBreakers stay because the
handler tests fake them. The tests that read a queued task moved to
the engine's tests; the handler tests use an engine that is never
started.

Model: opus-5-5
This commit is contained in:
2026-10-15 22:32:49 +00:00
parent 8406c77949
commit cb5fbb4db7
21 changed files with 893 additions and 761 deletions
+17 -25
View File
@@ -171,37 +171,29 @@ func loadResubmitSource(
return src, true, nil
}
// queueResubmit stores the copy and fans it out to the webhook's
// active targets.
// queueResubmit has the delivery engine store the copy, with a delivery
// for each of the webhook's active targets as they stand now, through
// the same StoreEvent the receiver uses. The one difference is that the
// copy leaves its entrypoint's last event as it is, since it did not
// arrive on that URL.
func (h *Handlers) queueResubmit(
w http.ResponseWriter,
r *http.Request,
webhook database.Webhook,
src resubmitSource,
) {
// The receiver's own query, run now: an active target created
// after the original event arrived is included, and an
// inactive one is skipped rather than refused.
targets, err := h.loadActiveTargets(webhook.ID)
if err != nil {
h.serverError(w, r, "failed to query targets", err)
return
event := &database.Event{
WebhookID: webhook.ID,
EntrypointID: src.EntrypointID,
Method: src.Method,
RawQuery: src.RawQuery,
Headers: src.Headers,
ContentType: src.ContentType,
Body: string(src.Body),
ResubmittedFromID: &src.ID,
}
event, tasks, err := h.createAndFanOut(
eventSource{
WebhookID: webhook.ID,
EntrypointID: src.EntrypointID,
Method: src.Method,
RawQuery: src.RawQuery,
HeadersJSON: src.Headers,
ContentType: src.ContentType,
Body: src.Body,
ResubmittedFromID: &src.ID,
},
targets,
)
deliveries, err := h.engine.StoreEvent(event)
if err != nil {
h.serverError(w, r, "failed to store resubmitted event", err)
@@ -215,11 +207,11 @@ func (h *Handlers) queueResubmit(
"webhook_id", webhook.ID,
"event_id", event.ID,
"resubmitted_from_id", src.ID,
"target_count", len(tasks),
"target_count", deliveries,
)
code := resubmitQueued
if len(tasks) == 0 {
if deliveries == 0 {
code = resubmitNoTargets
}