dispatch

package
v0.1.0-develop.2026061... Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package dispatch wires outbound-webhook dispatchers into the event router.

An outbound webhook is modeled as an event subscription: the producing cell emits a domain event to the broker on a topic equal to the webhook-dispatch contract ID, and this package registers a kwh.Dispatcher as that subscription's handler. Each consumed outbox.Entry is signed (HMAC-SHA256, vendor-neutral webhook-* headers) and POSTed to the selector-resolved target through an SSRF-guarded *http.Client. Delivery outcomes map to outbox dispositions via kwh.Classify (standard-webhooks aligned: 2xx Ack / every non-2xx + transient transport Requeue / SSRF-blocked Reject).

This mirrors the inbound receiver pattern (runtime/webhook/registry.go BuildRouteGroups) but the dispatch side consumes from the broker rather than mounting HTTP routes, so it drains through the event router (phase6) rather than the HTTP route-group drain (phase5).

Troubleshooting

"webhook dispatchers declared but no source store configured": Bootstrap failed because at least one cell registered a webhook-dispatch contract but WithWebhookSourceStore was not passed to bootstrap. Add the option and provide a populated kwh.SourceStore.

"webhook dispatch: signing source not registered" (sourceId in error details): BuildConsumers found no entry in the SourceStore for the SourceID declared in DispatchSpec. The missing sourceId is reported in the error details. Register the source secret in the store before starting.

"no cell.go struct field for subscribing slice" from gocell generate cell: The cell struct lacks a field whose pointer type package name matches the webhook-dispatch slice ID. Add *<sliceID>.Consumer (or equivalent) to the cell struct and re-run codegen.

"ambiguous field for slice <sliceID>" from gocell generate cell: Multiple cell struct fields match the slice ID. Add field: <fieldName> to the webhook-dispatch contractUsage in slice.yaml to disambiguate.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Consumer

type Consumer struct {
	// Spec is the synthesized event-kind ContractSpec the router subscribes on.
	// Topic == the webhook-dispatch contract ID: the producing cell emits to
	// that topic, this consumer signs and POSTs each delivered entry.
	Spec contractspec.ContractSpec
	// Handler is the dispatcher's Handle method (an outbox.EntryHandler).
	Handler outbox.EntryHandler
	// ConsumerGroup and CellID are both the owning cell ID: replicas of the
	// same cell compete for delivery (one POST per entry), and the cell is the
	// observability owner.
	ConsumerGroup string
	CellID        string
	// BrokerDelaySchedule is the Svix per-attempt retry timeline
	// (DefaultSvixSchedule().Delays()) the bootstrap drain copies onto the
	// outbox.Subscription so the broker honors per-attempt delays (#1458).
	BrokerDelaySchedule []time.Duration
}

Consumer is a built outbound-webhook dispatcher paired with the subscription identity needed to register it on the event router via AddContractHandler.

func BuildConsumers

func BuildConsumers(
	clk clock.Clock,
	reqs []cell.WebhookDispatchRequest,
	store kwh.SourceStore,
	policy *kwh.SafePolicy,
	rec kwh.Metrics,
) ([]Consumer, error)

BuildConsumers turns the accumulated cell.WebhookDispatchRequest values (from RegistrySnapshot.WebhookDispatchers) into Consumer values ready for the bootstrap phase6 drain to register on the event router.

clk is the mandatory positional clock (CLOCK-POSITIONAL-INJECTION-01). store resolves each request's signing secret by SourceID; policy is the shared SSRF guard wired into every dispatcher's *http.Client. Both must be non-nil. Construction is eager so a missing source or bad config fails at startup rather than at first delivery.

DLX: the composition root must configure the broker subscriber's DLX exchange for dispatch subscription topics; permanently-failed deliveries (Reject) are Nack(requeue=false)→DLX and are otherwise silently discarded. rec is the optional dispatch-side metrics recorder (the zero value disables recording); the bootstrap auto-wire passes the registered collector when a metrics provider is configured.

func (Consumer) Validate

func (c Consumer) Validate() error

Validate checks that all required Consumer fields are populated. buildConsumer calls this as a belt-and-suspenders guard before returning, consistent with ReceiverSpec.Validate and DispatchSpec.Validate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL