Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidateTopicName ¶
ValidateTopicName ensures a topic name is valid. Topic names must be non-empty, at most 255 characters, and contain only lowercase letters, numbers, underscores, and hyphens.
Types ¶
type Consumer ¶
type Consumer interface {
// Register adds a controller to the consumer. Must be called before Start().
Register(controller Controller) error
// Start subscribes to all registered controllers' topics and begins consuming messages.
// Context is cancelled when the consumer is stopped, the implementation should propagate it to the controllers
// running message processing. The implementation can react immediately to the context cancellation by returning `ctx.Err()` instead of starting the message processing,
// but can also opt out to defer the cancellation after the message processing routine is set up.
// Start() will only be called once at the application startup, so it does not need to be idempotent.
Start(ctx context.Context) error
// Stop gracefully shuts down all controllers with the specified timeout.
// timeoutMs is the maximum time in milliseconds to wait for graceful shutdown.
// Returns error if shutdown times out.
// Stop() will only be called once at the application shutdown, so it does not need to be idempotent.
Stop(timeoutMs int64) error
}
Consumer orchestrates multiple queue consumers. It handles subscription lifecycle, message consumption, ack/nack, and graceful shutdown for the entire pipeline. Start(), Register() and Stop() are always called in this order so they do not need to be concurrently-safe between one another, but the implementation must be thread-safe between message processing and Register()/Stop() operations.
func New ¶
func New(logger *zap.SugaredLogger, scope tally.Scope, registry TopicRegistry, classifiers ...errs.Classifier) Consumer
New creates a new consumer.
registry provides queue and subscription config for topics. classifiers are the per-backend error classifiers used to decide whether an error returned by a controller is retryable (nack for redelivery) or non-retryable (reject to DLQ). The consumer runs errs.Classify(err, classifiers...) exactly once per failing delivery and then drives ack/nack/reject from the resulting chain via plain errs.IsRetryable type checks. Pass any backend-specific classifiers the controllers rely on (e.g. core/errs/mysql.Classifier); passing none is fine for tests where controllers always return explicit framework-wrapped errors.
type Controller ¶
type Controller interface {
Process(ctx context.Context, delivery Delivery) error
// Name returns the controller name for logging and metrics.
Name() string
// TopicKey returns the topic key this controller subscribes to.
TopicKey() TopicKey
// ConsumerGroup returns the consumer group for offset tracking.
// Multiple controllers can share a consumer group to load-balance across workers.
// Different consumer groups consume independently.
ConsumerGroup() string
}
Controller processes queue deliveries. Controllers contain business logic and are registered with the Consumer. The Controller interface enables clean separation of concerns: - Controller focuses on business logic (deserialize, process, return error status) - Consumer handles infrastructure (subscription, ack/nack, metrics, lifecycle) The implementation of the controller should be idempotent and stateless. The controller is expected to be retried for the same message multiple times and should process side effects gracefully. The implementation must be thread-safe.
type Delivery ¶
type Delivery interface {
// Message returns the delivered message.
Message() queue.Message
// ExtendVisibilityTimeout extends the time before this message becomes
// visible to other consumers. Use when processing takes longer than expected.
ExtendVisibilityTimeout(ctx context.Context, durationMillis int64) error
// DeliveryID returns a backend-specific identifier for this delivery.
DeliveryID() string
// Attempt returns how many times this message has been delivered.
// Starts at 1 for first delivery.
Attempt() int
// ReceivedAt returns when this delivery was received (Unix milliseconds).
ReceivedAt() int64
// Metadata returns backend-specific delivery metadata.
Metadata() map[string]string
}
Delivery is the consumer package's view of a queue delivery. It exists to hide Ack/Nack from controllers — the Consumer framework handles those automatically based on the error returned from Process(). Controllers only see message data, metadata, and ExtendVisibilityTimeout (a business-level concern for long-running processing).
To signal outcome from Process():
- Return nil to ack the message (success).
- Return an error to nack the message for retry.
- Return a non-retryable error to reject a poison pill message (removes it from the queue).
type TopicConfig ¶
type TopicConfig struct {
// Key is the fixed pipeline stage identifier.
Key TopicKey
// Name is the actual queue topic name (e.g. "request", "my-custom-request").
Name string
// Queue is the queue backend for this topic.
Queue queue.Queue
// Subscription is the subscription configuration for this topic.
// Leave at zero value for publish-only topics.
Subscription queue.SubscriptionConfig
}
TopicConfig combines all configuration for a single pipeline topic: the fixed key, the actual queue topic name, the queue backend, and (optionally) subscription settings.
type TopicKey ¶
type TopicKey string
TopicKey identifies a pipeline stage. It is a fixed key used to look up queue backends, topic names, and subscription configs in the TopicRegistry. The actual queue topic name is provided separately via TopicConfig.Name so that library consumers can choose their own naming conventions.
const ( // TopicKeyStart is the pipeline stage where new requests arrive from the gateway. TopicKeyStart TopicKey = "start" // TopicKeyCancel is the pipeline stage where cancellation requests arrive from the gateway. TopicKeyCancel TopicKey = "cancel" // TopicKeyValidate is the pipeline stage where requests are published for validation. TopicKeyValidate TopicKey = "validate" // TopicKeyBatch is the pipeline stage where validated requests are published for batching. TopicKeyBatch TopicKey = "batch" // TopicKeyScore is the pipeline stage where batches are published for scoring. TopicKeyScore TopicKey = "score" // TopicKeySpeculate is the pipeline stage where scored batches are published for speculation. TopicKeySpeculate TopicKey = "speculate" // TopicKeyBuild is the pipeline stage where speculated batches are published for builds. TopicKeyBuild TopicKey = "build" // TopicKeyBuildSignal is the polling stage for triggered builds. Each // message carries a Build; the consumer calls BuildRunner.Status, // persists the latest status, publishes the batch ID to TopicKeySpeculate // so the state machine re-evaluates, and re-publishes itself via // PublishAfter when the build has not yet reached a terminal state. TopicKeyBuildSignal TopicKey = "buildsignal" // TopicKeyMerge is the pipeline stage where speculated batches are published for merging. TopicKeyMerge TopicKey = "merge" // TopicKeyConclude is the pipeline stage where merged requests are published for conclusion. TopicKeyConclude TopicKey = "conclude" // TopicKeyLog is the pipeline stage where per-request logs are written. TopicKeyLog TopicKey = "log" )
type TopicRegistry ¶
type TopicRegistry struct {
// contains filtered or unexported fields
}
TopicRegistry provides queue, topic name, and subscription config for topics. Each topic can have a different queue backend and topic name.
func NewTopicRegistry ¶
func NewTopicRegistry(configs []TopicConfig) (TopicRegistry, error)
NewTopicRegistry creates a new TopicRegistry from a list of TopicConfigs. Returns an error if any topic name is invalid.
func (TopicRegistry) Queue ¶
func (r TopicRegistry) Queue(key TopicKey) (queue.Queue, bool)
Queue returns the queue backend for the given topic key. Returns ok=false if no queue is registered for this key.
func (TopicRegistry) SubscriptionConfig ¶
func (r TopicRegistry) SubscriptionConfig(key TopicKey, consumerGroup string) (queue.SubscriptionConfig, bool)
SubscriptionConfig returns the subscription configuration for the given topic key and consumer group. Returns ok=false if no configuration is registered.