Documentation
¶
Overview ¶
Package hook holds the domain-neutral mechanics of the hooks framework: the controller that turns hook events on a queue into hook.Hook calls, the reconciler for the events that never made it, and the helper a producer publishes an event through.
The controller is domain-neutral. Each domain runs its own hook topic and its own instance of this stage — "per-domain" is about the topic and the wiring, not about the logic, which is the same everywhere: decode, validate, resolve, invoke. The domain-specific parts are the topic name the host maps the key to and the hooks its resolver returns.
The contract this stage consumes is api/base/hook; the hooks it invokes implement platform/extension/hook.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Publish ¶
func Publish( ctx context.Context, registry consumer.TopicRegistry, event *basehook.HookEvent, partitionKey string, ) error
Publish sends one hook event to the domain's hook topic, partitioned by partitionKey. The topic key is not a parameter: a domain runs a single hook topic, and the caller's registry is what binds that key to a wire topic.
The event id is the message id, so a redelivery republishing the same event dedups into the original message instead of enqueuing a second one. Callers pass the partition key their own topic partitions on, carrying that ordering across the seam.
Errors are returned unclassified, leaving retryability to the caller's classifier: a malformed event is the caller's bug, not a transient fault.
Types ¶
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller consumes hook events and runs the hooks each one resolves to.
func NewController ¶
func NewController( logger *zap.SugaredLogger, scope tally.Scope, hooks hookext.Hooks, topicKey consumer.TopicKey, consumerGroup string, ) *Controller
NewController builds the hook controller for a host. A host registers the stage even when it has no integrations yet — a resolver that returns no hooks still acks, so "off" and "lost" stay distinguishable.
func (*Controller) ConsumerGroup ¶
func (c *Controller) ConsumerGroup() string
ConsumerGroup returns the consumer group for offset tracking.
func (*Controller) Name ¶
func (c *Controller) Name() string
Name returns the controller name for logging and metrics.
func (*Controller) Process ¶
Process decodes the delivery's hook event, validates it, and runs every hook the resolver returns for it. Returns nil to ack, or an error to nack (retry) / reject (DLQ).
An ack means "no hook still has work to do with this event", not "something acted on it": a hook that does not care returns nil, and an event no hook resolves to is acked unhandled.
func (*Controller) TopicKey ¶
func (c *Controller) TopicKey() consumer.TopicKey
TopicKey returns the topic key this controller subscribes to.
type DLQController ¶
type DLQController struct {
// contains filtered or unexported fields
}
DLQController is the reconciler for the hook topic's dead-letter queue. Implements consumer.Controller.
It reconciles nothing, because there is nothing it may touch: a hook never writes pipeline state, so a hook event that could not be delivered leaves no half-finished transition behind. What is lost is the side effect — a comment not posted, a row not exported — which only a person can decide how to recover. So this controller makes the loss impossible to miss and hands it over: it records the complete event and why it failed, counts it on a metric meant to page, and acks so the event does not sit in the DLQ unnoticed. Republishing the logged event recovers it.
That is a deliberate step up from the log topic's DLQ, which warns and moves on. Dropping an observability row costs a gap in a read model; dropping a merge-failure comment costs a support ticket, and nothing else in the system will notice it is missing.
func NewDLQController ¶
func NewDLQController( logger *zap.SugaredLogger, scope tally.Scope, topicKey consumer.TopicKey, consumerGroup string, ) *DLQController
NewDLQController builds the DLQ reconciler for a host's hook topic. topicKey is the dead-letter key (the hook topic key plus the queue's DLQ suffix), not the primary one.
func (*DLQController) ConsumerGroup ¶
func (c *DLQController) ConsumerGroup() string
ConsumerGroup returns the consumer group for offset tracking.
func (*DLQController) Name ¶
func (c *DLQController) Name() string
Name returns the controller name for logging and metrics.
func (*DLQController) Process ¶
Process records a dropped hook event and acks it.
It never returns an error: a failure here would re-deliver the message forever, since the DLQ consumer has no DLQ of its own and treats everything as retryable. The record is the outcome, so the only way to fail is not to write one.
func (*DLQController) TopicKey ¶
func (c *DLQController) TopicKey() consumer.TopicKey
TopicKey returns the topic key this controller subscribes to.