Help us shape the future of Go! Take the 2026 Go Developer Survey

redisstream

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: BSD-2-Clause Imports: 11 Imported by: 0

Documentation

Overview

Package redisstream implements the internal/coachapi/queue.TaskQueue port (ADR-006, docs/architecture/ADR-006-watermill-queue-abstraction.md) on top of Watermill's Redis Streams pub/sub (github.com/ThreeDotsLabs/watermill-redisstream), for coach's non-AWS / self-hosted deployment target. Enqueue publishes through a Watermill Publisher; Complete and permanent Nack acknowledge through the underlying Watermill message, so ADR-006 rule 5's "successful handler -> Ack, retryable error -> Nack, permanent error -> Ack plus publication to a poison-task destination" holds at the wire level. Redis pending-entry lists, consumer groups, XCLAIM, and Watermill's *message.Message are not exposed: callers only see queue.Task and queue.Claim.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Address is the Redis server address (host:port), e.g. "redis:6379".
	Address string
	// Password is the Redis AUTH password. Empty means no auth.
	Password string
	// DB selects the Redis logical database index.
	DB int

	// Stream is the Redis Stream (and Watermill topic) task attempts are
	// published to and consumed from; ADR-006's "taskQueue" name.
	Stream string
	// ConsumerGroup is the Redis Streams consumer group every Queue
	// instance for Stream shares. It is what makes claims competing: at
	// most one consumer in the group receives a given stream entry.
	ConsumerGroup string
	// Consumer names this Queue instance's Redis Streams consumer within
	// ConsumerGroup. A generated id is used when empty.
	Consumer string

	// ClaimAfter is how long an unresolved claim (neither Complete nor
	// Nack called) may be held before Claim treats it as abandoned and
	// reclaims it for another attempt -- this Queue's equivalent of a
	// visibility timeout. See Queue's doc comment for why this is
	// enforced against the injected Clock rather than Redis server time.
	ClaimAfter time.Duration

	// DialTimeout bounds the initial Redis connection attempt. Defaults
	// to defaultDialTimeout when zero or negative.
	DialTimeout time.Duration
}

Config matches ADR-006's "Provider configuration" Redis Streams shape (address, consumerGroup, claimAfter; docs/architecture/ADR-006-watermill-queue-abstraction.md).

func (Config) Validate

func (c Config) Validate() error

Validate reports a descriptive error naming every required Config field that is missing or out of range, or nil if c is usable by NewQueue.

type Queue

type Queue struct {
	// contains filtered or unexported fields
}

Queue implements internal/coachapi/queue.TaskQueue against Redis Streams. It also exposes PoisonTasks, which is not part of that port but is required by internal/acceptanceharness/queueconformance.Queue (see redisstream_conformance_test.go for the adapter that reconciles the two packages' structurally-identical-but-distinctly-named Task and Claim types).

A single Queue is safe for concurrent use: Claim/Complete/Nack all serialize access to the shared pending-claims map via mu.

func NewQueue

func NewQueue(cfg Config, clock acceptanceharness.Clock) (*Queue, error)

NewQueue connects to Redis and returns a Queue consuming cfg.Stream under cfg.ConsumerGroup. clock defaults to acceptanceharness.RealClock when nil; tests inject acceptanceharness.FakeClock to force reclaims deterministically (see maxWatermillIdleTime's doc comment).

func (*Queue) Claim

func (q *Queue) Claim(ctx context.Context) (queue.Claim, bool, error)

Claim first reclaims any pending claim whose ClaimAfter has elapsed (per the injected Clock), and only if none did, waits up to claimPollWindow for a newly delivered message. ok=false means neither happened before the wait window (or ctx) elapsed.

func (*Queue) Close

func (q *Queue) Close() error

Close stops consuming and releases the underlying Redis connection.

func (*Queue) Complete

func (q *Queue) Complete(ctx context.Context, claim queue.Claim) error

Complete acknowledges claim's task attempt as durably finished. It fails if claim.Token has been invalidated by a reclaim.

func (*Queue) Enqueue

func (q *Queue) Enqueue(ctx context.Context, task queue.Task) error

Enqueue publishes task onto the Redis Stream via the Watermill Publisher (an XADD under the hood).

func (*Queue) Nack

func (q *Queue) Nack(ctx context.Context, claim queue.Claim, permanent bool) error

Nack reports claim's task attempt failed. A retryable failure (permanent=false) makes the task claimable again with Attempt incremented. A permanent failure (permanent=true) acknowledges the underlying message (ADR-006 rule 5) and republishes the task onto the poison-task destination stream; PoisonTasks reads that stream back. Nack fails under the same stale-token condition as Complete.

func (*Queue) PoisonTasks

func (q *Queue) PoisonTasks(ctx context.Context) ([]queue.Task, error)

PoisonTasks returns every task a permanent Nack has routed to the poison-task destination stream, oldest first. It is not part of queue.TaskQueue; internal/acceptanceharness/queueconformance.Queue requires it so both this package's own tests and the shared conformance suite can assert the poison destination actually received a task.

Jump to

Keyboard shortcuts

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