Documentation
¶
Index ¶
- Variables
- func DefaultConsumerGroupID(clientID string) string
- func ValidateProtectedQueueContract(expected, persisted types.QueueConfig) error
- type ClientConnectionChecker
- type ClientDeliveryTargetChecker
- type Config
- type Deliverer
- type DeliveryEngine
- func (e *DeliveryEngine) DeliverAll(ctx context.Context)
- func (e *DeliveryEngine) DeliverQueue(ctx context.Context, queueName string) bool
- func (e *DeliveryEngine) Schedule(queueName string)
- func (e *DeliveryEngine) ScheduleAll(ctx context.Context)
- func (e *DeliveryEngine) Start(ctx context.Context)
- func (e *DeliveryEngine) Stop()
- func (e *DeliveryEngine) Unschedule(queueName string)
- type DeliveryMessage
- type DeliveryTargetFunc
- type DistributionMode
- type GroupOpForwarder
- type Manager
- func (m *Manager) Ack(ctx context.Context, queueName, messageID, groupID string) error
- func (m *Manager) CommitOffset(ctx context.Context, queueName, groupID string, offset uint64) error
- func (m *Manager) CreateQueue(ctx context.Context, config types.QueueConfig) error
- func (m *Manager) DeleteQueue(ctx context.Context, queueName string) error
- func (m *Manager) DeliverQueueMessage(ctx context.Context, clientID string, msg *cluster.QueueMessage) error
- func (m *Manager) Enqueue(ctx context.Context, topic string, payload []byte, ...) error
- func (m *Manager) EnqueueLocal(ctx context.Context, topic string, payload []byte, ...) (string, error)
- func (m *Manager) GetLag(ctx context.Context, queueName, groupID string) (uint64, error)
- func (m *Manager) GetMetrics() consumer.Metrics
- func (m *Manager) GetOrCreateQueue(ctx context.Context, queueName string, topics ...string) (*types.QueueConfig, error)
- func (m *Manager) GetQueue(ctx context.Context, queueName string) (*types.QueueConfig, error)
- func (m *Manager) GetRaftManager() *raft.Manager
- func (m *Manager) GroupStore() storage.ConsumerGroupStore
- func (m *Manager) HandleForwardedGroupOp(ctx context.Context, queueName string, opData []byte) error
- func (m *Manager) HandleQueuePublish(ctx context.Context, publish types.PublishRequest, mode types.PublishMode) error
- func (m *Manager) ListQueues(ctx context.Context) ([]types.QueueConfig, error)
- func (m *Manager) Nack(ctx context.Context, queueName, messageID, groupID string) error
- func (m *Manager) NarrowProtectedQueueContracts(contracts []types.QueueConfig) error
- func (m *Manager) ProtectedQueueContracts() []types.QueueConfig
- func (m *Manager) Publish(ctx context.Context, publish types.PublishRequest) error
- func (m *Manager) PublishToDurableStream(ctx context.Context, queueName string, publish types.PublishRequest) error
- func (m *Manager) PublishToMatchingQueues(ctx context.Context, publish types.PublishRequest) error
- func (m *Manager) QueueStore() storage.QueueStore
- func (m *Manager) Reject(ctx context.Context, queueName, messageID, groupID, reason string) error
- func (m *Manager) ReplaceProtectedQueueContracts(ctx context.Context, contracts []types.QueueConfig) error
- func (m *Manager) SetRaftCoordinator(rc raft.QueueCoordinator)
- func (m *Manager) SetRaftManager(rm *raft.Manager)
- func (m *Manager) ShutdownComplete() bool
- func (m *Manager) Start(ctx context.Context) error
- func (m *Manager) Stop() error
- func (m *Manager) Subscribe(ctx context.Context, queueName, pattern string, ...) error
- func (m *Manager) SubscribeExisting(ctx context.Context, queueName, pattern string, ...) error
- func (m *Manager) SubscribeExistingWithCursor(ctx context.Context, queueName, pattern string, ...) error
- func (m *Manager) SubscribeWithCursor(ctx context.Context, queueName, pattern string, ...) error
- func (m *Manager) Unsubscribe(ctx context.Context, queueName, pattern string, clientID, groupID string) error
- func (m *Manager) UpdateConsumerHeartbeat(ctx context.Context, queueName, groupID, consumerID string) error
- func (m *Manager) UpdateHeartbeat(ctx context.Context, clientID string) error
- func (m *Manager) UpdateQueue(ctx context.Context, config types.QueueConfig) error
- func (m *Manager) ValidateProtectedQueueContracts(ctx context.Context) error
- type MetricsProvider
- type RemoteBatchRouter
- type RemoteRouter
- type StreamCommitter
- type WritePolicy
Constants ¶
This section is empty.
Variables ¶
var ( // ErrQueueNotStream is returned when an exact stream publish targets a // queue that exists but is not configured as a stream. ErrQueueNotStream = errors.New("queue is not a stream") // ErrQueueNotDurable is returned when an exact durable publish targets an // ephemeral queue. ErrQueueNotDurable = errors.New("queue is not durable") // ErrQueueNotReserved is returned when an exact internal publish targets a // queue that is no longer protected as a statically reserved queue. ErrQueueNotReserved = errors.New("queue is not reserved") // ErrQueueMessageTooLarge is returned before append when an exact stream // publish exceeds the target queue's configured maximum message size. ErrQueueMessageTooLarge = errors.New("message exceeds queue maximum size") // ErrQueueNotProtected is returned when the exact durable stream publish // path is used for a queue without a registered immutable contract. ErrQueueNotProtected = errors.New("queue has no protected contract") // ErrCaptureStillRunning is returned by Stop when a capture worker is still // inside the queue store after the drain timeout. The manager's resources — // the queue store especially — must not be released while that is true. ErrCaptureStillRunning = errors.New("capture workers did not finish; queue resources left open") // ErrProtectedQueueMutation is returned when a create, update, or delete // would violate a registered queue contract. ErrProtectedQueueMutation = errors.New("protected queue mutation rejected") // ErrProtectedQueueContractDrift is returned when a protected queue's // persisted configuration no longer matches its registered contract. ErrProtectedQueueContractDrift = errors.New("protected queue contract drift") // ErrDurableSyncUnsupported is returned before append when the configured // queue store cannot establish a per-queue durability barrier. ErrDurableSyncUnsupported = errors.New("queue store does not support durable sync") // ErrDurableReplicatedStreamUnsupported prevents a false durability ACK in // clustered mode until the same barrier is carried through leader forwarding. ErrDurableReplicatedStreamUnsupported = errors.New("durable exact stream publish does not support replication") )
Functions ¶
func DefaultConsumerGroupID ¶ added in v0.50.0
DefaultConsumerGroupID returns the queue-mode consumer group used when a subscriber does not provide one explicitly.
func ValidateProtectedQueueContract ¶ added in v0.50.0
func ValidateProtectedQueueContract(expected, persisted types.QueueConfig) error
ValidateProtectedQueueContract compares the persisted fields that define an exact internal publisher's safety and replay guarantees. MaxDepth is deliberately excluded because stream depth is not currently enforced.
Types ¶
type ClientConnectionChecker ¶
ClientConnectionChecker is kept for deliverers where only live connections are valid queue delivery targets.
type ClientDeliveryTargetChecker ¶
ClientDeliveryTargetChecker is optionally implemented by a Deliverer that can tell whether queue delivery has a valid target before queue cursors move. For MQTT, a disconnected persistent session is still a valid delivery target because the broker can enqueue QoS>0 messages for later delivery.
type Config ¶
type Config struct {
// Consumer configuration
VisibilityTimeout time.Duration
MaxDeliveryCount int
ClaimBatchSize int
AutoCommitInterval time.Duration
// Delivery configuration
DeliveryInterval time.Duration
DeliveryBatchSize int
HeartbeatInterval time.Duration
ConsumerTimeout time.Duration
// DLQ configuration
DLQTopicPrefix string
// Work stealing configuration
StealInterval time.Duration
StealEnabled bool
// PEL configuration
MaxPELSize int
// Retention configuration
RetentionCheckInterval time.Duration
// Capture dispatcher configuration. Topic capture runs off the publish
// path so a stalled queue store cannot delay subscribers; these bound how
// much unwritten capture is held and how long shutdown waits for it.
CaptureWorkers int
CaptureQueueDepth int
CaptureDrainTimeout time.Duration
// Replication/distribution configuration
WritePolicy WritePolicy
DistributionMode DistributionMode
// Queue configurations from main config
QueueConfigs []types.QueueConfig
// ProtectedQueueContracts are immutable runtime contracts for queues used
// by exact internal publishers. Only explicitly listed queues are protected;
// Reserved alone does not make a queue immutable.
ProtectedQueueContracts []types.QueueConfig
// OnConsumerRemoved is called when stale consumers are removed during
// heartbeat cleanup. The callback receives the queue name, group ID,
// and the list of removed consumer IDs (prefixed client IDs).
// Must be non-blocking.
OnConsumerRemoved func(queueName, groupID string, consumerIDs []string)
}
Config holds configuration for the queue-based queue manager.
type Deliverer ¶
type Deliverer interface {
Deliver(ctx context.Context, clientID string, msg *storage.Message) error
}
Deliverer is the output boundary for queue message delivery. Protocol brokers implement this interface so the delivery engine can push messages to connected clients without knowing protocol details.
type DeliveryEngine ¶
type DeliveryEngine struct {
// contains filtered or unexported fields
}
DeliveryEngine claims messages from queues and routes them to local or remote consumers. It owns the scheduling loop and delivery state; the Manager delegates all delivery work here.
func NewDeliveryEngine ¶
func NewDeliveryEngine( queueStore storage.QueueStore, groupStore storage.ConsumerGroupStore, consumerMgr *consumer.Manager, local Deliverer, remote RemoteRouter, localNodeID string, distributionMode DistributionMode, batchSize int, logger *slog.Logger, ) *DeliveryEngine
NewDeliveryEngine creates a delivery engine. remote may be nil for single-node deployments.
func (*DeliveryEngine) DeliverAll ¶
func (e *DeliveryEngine) DeliverAll(ctx context.Context)
DeliverAll delivers messages for every queue (full sweep). Intended for tests and benchmarks that need synchronous delivery without the loop.
func (*DeliveryEngine) DeliverQueue ¶
func (e *DeliveryEngine) DeliverQueue(ctx context.Context, queueName string) bool
DeliverQueue delivers messages for a single queue by name. Returns true if any messages were delivered.
func (*DeliveryEngine) Schedule ¶
func (e *DeliveryEngine) Schedule(queueName string)
Schedule enqueues a queue name for delivery. Duplicate schedules for the same queue are coalesced until the queue is delivered.
func (*DeliveryEngine) ScheduleAll ¶
func (e *DeliveryEngine) ScheduleAll(ctx context.Context)
ScheduleAll lists all queues and schedules each for delivery.
func (*DeliveryEngine) Start ¶
func (e *DeliveryEngine) Start(ctx context.Context)
Start launches the delivery loop goroutine.
func (*DeliveryEngine) Stop ¶
func (e *DeliveryEngine) Stop()
Stop signals the delivery loop to exit and waits for it to finish.
func (*DeliveryEngine) Unschedule ¶
func (e *DeliveryEngine) Unschedule(queueName string)
Unschedule removes a queue from the dedup set. Called when a queue is deleted.
type DeliveryMessage ¶
type DeliveryMessage struct {
ID string
Payload []byte
Topic string
Properties map[string]string
GroupID string
Offset uint64
DeliveredAt time.Time
AckTopic string
NackTopic string
RejectTopic string
}
DeliveryMessage is the internal message format for queue delivery tracking.
type DeliveryTargetFunc ¶
DeliveryTargetFunc adapts a plain function to the DeliveryTarget interface.
type DistributionMode ¶
type DistributionMode string
DistributionMode controls how queue messages reach consumers across nodes.
const ( DistributionForward DistributionMode = "forward" // Forward publishes to nodes with consumers DistributionReplicate DistributionMode = "replicate" // Rely on Raft to replicate queue logs )
type GroupOpForwarder ¶
type GroupOpForwarder interface {
ForwardGroupOp(ctx context.Context, nodeID, queueName string, opData []byte) error
}
GroupOpForwarder forwards consumer group operations to a remote node.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is the queue-based queue manager. It uses append-only logs with cursor-based consumer groups, NATS JetQueue-style.
func NewManager ¶
func NewManager(queueStore storage.QueueStore, groupStore storage.ConsumerGroupStore, dt Deliverer, config Config, logger *slog.Logger, cl cluster.Cluster) *Manager
NewManager creates a new queue-based queue manager. The cluster parameter is optional (nil for single-node mode).
func (*Manager) CommitOffset ¶
CommitOffset explicitly commits an offset for a stream consumer group. Use when AutoCommit is disabled for manual commit control.
func (*Manager) CreateQueue ¶
CreateQueue creates a new queue.
func (*Manager) DeleteQueue ¶
DeleteQueue deletes a queue.
func (*Manager) DeliverQueueMessage ¶
func (m *Manager) DeliverQueueMessage(ctx context.Context, clientID string, msg *cluster.QueueMessage) error
DeliverQueueMessage implements cluster.QueueHandler.DeliverQueueMessage.
func (*Manager) Enqueue ¶
func (m *Manager) Enqueue(ctx context.Context, topic string, payload []byte, properties map[string]string) error
Enqueue is an alias for Publish for backward compatibility.
func (*Manager) EnqueueLocal ¶
func (m *Manager) EnqueueLocal(ctx context.Context, topic string, payload []byte, properties map[string]string) (string, error)
EnqueueLocal implements cluster.QueueHandler.EnqueueLocal.
func (*Manager) GetMetrics ¶
GetMetrics returns the current metrics snapshot.
func (*Manager) GetOrCreateQueue ¶
func (m *Manager) GetOrCreateQueue(ctx context.Context, queueName string, topics ...string) (*types.QueueConfig, error)
GetOrCreateQueue gets or creates a queue with default configuration.
func (*Manager) GetRaftManager ¶
GetRaftManager returns the Raft replication manager.
func (*Manager) GroupStore ¶
func (m *Manager) GroupStore() storage.ConsumerGroupStore
GroupStore returns the consumer group store used by the manager.
func (*Manager) HandleForwardedGroupOp ¶
func (m *Manager) HandleForwardedGroupOp(ctx context.Context, queueName string, opData []byte) error
HandleForwardedGroupOp implements cluster.QueueHandler.HandleForwardedGroupOp. It decodes a raft.Operation and applies it through the local coordinator.
func (*Manager) HandleQueuePublish ¶
func (m *Manager) HandleQueuePublish(ctx context.Context, publish types.PublishRequest, mode types.PublishMode) error
HandleQueuePublish implements cluster.QueueHandler.HandleQueuePublish.
func (*Manager) ListQueues ¶
ListQueues returns all queue configurations.
func (*Manager) NarrowProtectedQueueContracts ¶ added in v0.50.0
func (m *Manager) NarrowProtectedQueueContracts(contracts []types.QueueConfig) error
NarrowProtectedQueueContracts replaces the registry with an exact subset of the already-installed contracts without reading queue storage. It is used to remove stale contracts after another subsystem has atomically committed its new authorization snapshot; unlike ReplaceProtectedQueueContracts, this finalization step cannot fail because of storage I/O.
func (*Manager) ProtectedQueueContracts ¶ added in v0.50.0
func (m *Manager) ProtectedQueueContracts() []types.QueueConfig
ProtectedQueueContracts returns a snapshot of the currently registered immutable queue contracts.
func (*Manager) Publish ¶
Publish adds a message to all queues whose topic patterns match the topic. This is the NATS JetQueue-style "multi-queue" routing. The delivery engine routes appended records to remote consumers when needed.
func (*Manager) PublishToDurableStream ¶ added in v0.50.0
func (m *Manager) PublishToDurableStream(ctx context.Context, queueName string, publish types.PublishRequest) error
PublishToDurableStream appends to exactly queueName and establishes a per-queue durability barrier before returning success. The target must be a reserved, durable, non-replicated stream. This method never performs topic fanout and never auto-creates a queue.
The contract snapshot is copied out of the registry before any storage work starts. Holding protectedQueuesMu across the append would let one fsync block every contract reload, and a reload waiting for the write lock would in turn stall every subsequent publish.
func (*Manager) PublishToMatchingQueues ¶ added in v0.51.0
PublishToMatchingQueues captures an ordinary pub/sub publish in existing queues whose configured topic patterns match it. Unlike Publish, it never auto-creates a queue when no pattern matches.
It resolves the matching queues on the caller's goroutine — that is an in-memory index lookup — and then hands the storage work to the capture dispatcher. Enqueueing never blocks, so a queue whose store stalls can no longer delay the subscribers of a matching topic or the publisher's acknowledgement.
The returned error therefore reports only what is known before the append is attempted: that the matching queues could not be resolved. An append that fails or is dropped afterwards is reported through queues.capture_failures and queues.capture_dropped, which is the only signal capture has.
func (*Manager) QueueStore ¶
func (m *Manager) QueueStore() storage.QueueStore
QueueStore returns the queue store used by the manager.
func (*Manager) ReplaceProtectedQueueContracts ¶ added in v0.50.0
func (m *Manager) ReplaceProtectedQueueContracts(ctx context.Context, contracts []types.QueueConfig) error
ReplaceProtectedQueueContracts validates and atomically replaces the immutable queue-contract registry. Queue mutations and exact publishes are blocked for the duration, so no operation can enter between persisted-state validation and the registry swap.
func (*Manager) SetRaftCoordinator ¶
func (m *Manager) SetRaftCoordinator(rc raft.QueueCoordinator)
SetRaftCoordinator sets queue-aware Raft coordinator.
func (*Manager) SetRaftManager ¶
SetRaftManager sets the Raft replication manager.
func (*Manager) ShutdownComplete ¶ added in v0.51.0
ShutdownComplete reports whether Stop finished with every capture worker out of the queue store.
It gates releasing anything the manager shares with those workers, the queue store above all. An append already in flight cannot be cancelled — the store takes no context — so Stop bounds its wait rather than hanging, and a worker may outlive it. Closing the store then would be a use-after-close on a segment that worker still holds. Callers that own such a resource must consult this and leak the handle instead; the process is exiting either way.
func (*Manager) Stop ¶
Stop stops the manager and all workers. Stop shuts the manager down and reports whether that completed cleanly.
Capture drains first. Its workers append through the queue store, schedule delivery, and on replicated queues call the Raft coordinator, so those have to outlive the drain rather than the other way round.
A returned ErrCaptureStillRunning means a capture worker is still inside the queue store and could not be interrupted. Everything it touches — the store above all — must then be left alone: closing it underneath an in-flight append is a use-after-close, and leaking the handle into process exit is the cheaper outcome.
func (*Manager) Subscribe ¶
func (m *Manager) Subscribe(ctx context.Context, queueName, pattern string, clientID, groupID, proxyNodeID string) error
Subscribe adds a consumer to a stream with optional pattern matching.
func (*Manager) SubscribeExisting ¶ added in v0.50.0
func (m *Manager) SubscribeExisting(ctx context.Context, queueName, pattern string, clientID, groupID, proxyNodeID string) error
SubscribeExisting adds a consumer to an existing queue without creating it.
func (*Manager) SubscribeExistingWithCursor ¶ added in v0.50.0
func (m *Manager) SubscribeExistingWithCursor(ctx context.Context, queueName, pattern string, clientID, groupID, proxyNodeID string, cursor *types.CursorOption) error
SubscribeExistingWithCursor adds a consumer to an existing queue without creating the queue or changing its configured type.
func (*Manager) SubscribeWithCursor ¶
func (m *Manager) SubscribeWithCursor(ctx context.Context, queueName, pattern string, clientID, groupID, proxyNodeID string, cursor *types.CursorOption) error
SubscribeWithCursor adds a consumer with explicit cursor positioning.
func (*Manager) Unsubscribe ¶
func (m *Manager) Unsubscribe(ctx context.Context, queueName, pattern string, clientID, groupID string) error
Unsubscribe removes a consumer from a stream.
func (*Manager) UpdateConsumerHeartbeat ¶
func (m *Manager) UpdateConsumerHeartbeat(ctx context.Context, queueName, groupID, consumerID string) error
UpdateConsumerHeartbeat updates heartbeat for a specific consumer membership.
func (*Manager) UpdateHeartbeat ¶
UpdateHeartbeat updates the heartbeat for a consumer.
func (*Manager) UpdateQueue ¶
UpdateQueue updates an existing queue.
type MetricsProvider ¶
type MetricsProvider interface {
GetMetrics() consumer.Metrics
GetLag(ctx context.Context, queueName, groupID string) (uint64, error)
}
MetricsProvider exposes read-only queue delivery metrics.
type RemoteBatchRouter ¶
type RemoteRouter ¶
type RemoteRouter interface {
ListQueueConsumers(ctx context.Context, queueName string) ([]*cluster.QueueConsumerInfo, error)
RouteQueueMessage(ctx context.Context, nodeID, clientID, queueName string, msg *cluster.QueueMessage) error
UnregisterQueueConsumer(ctx context.Context, queueName, groupID, consumerID string) error
}
RemoteRouter is the subset of cluster.Cluster needed by the delivery engine for cross-node message routing.
type StreamCommitter ¶
type StreamCommitter interface {
CommitOffset(ctx context.Context, queueName, groupID string, offset uint64) error
}
StreamCommitter exposes explicit commit control for stream consumer groups.
type WritePolicy ¶
type WritePolicy string
WritePolicy controls how non-leader nodes handle queue writes when Raft is enabled.
const ( WritePolicyLocal WritePolicy = "local" // Append locally (no Raft redirect) WritePolicyReject WritePolicy = "reject" // Reject writes on non-leaders WritePolicyForward WritePolicy = "forward" // Forward writes to the Raft leader )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package consumer provides consumer group management with routing key filtering and work stealing support for the log-based queue model.
|
Package consumer provides consumer group management with routing key filtering and work stealing support for the log-based queue model. |
|
memory/log
Package log provides an in-memory implementation of the queue-based storage.
|
Package log provides an in-memory implementation of the queue-based storage. |