storage

package
v2.4.1 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PrefixKey = "__host"
)

Variables

View Source
var (
	// ErrQueueClosed is returned by operations on a closed Queue.
	ErrQueueClosed = errors.New("storage: queue closed")

	// ErrTopicAlreadySubscribed reports a second handler for one topic.
	// Registration is rejected rather than silently replacing the first, which
	// is what the previous Register did.
	ErrTopicAlreadySubscribed = errors.New("storage: topic already subscribed")

	// ErrNoHandler reports a message published to a topic nobody consumes.
	ErrNoHandler = errors.New("storage: no handler for topic")

	// ErrNilHandler reports a subscription with nothing to deliver to.
	ErrNilHandler = errors.New("storage: nil handler")

	// ErrQueueAlreadyStarted reports a second call to Start, or a Subscribe
	// that arrived too late to take effect.
	ErrQueueAlreadyStarted = errors.New("storage: queue already started")
)
View Source
var ErrCacheClosed = errors.New("storage: cache closed")

ErrCacheClosed is returned by operations on a closed Cache.

View Source
var ErrCacheMiss = errors.New("storage: cache miss")

ErrCacheMiss reports that a key is absent.

A key that never existed and a key that has expired are the same fact and return the same error. Callers must test with errors.Is; treating any non-nil error as "no data" turns a backend outage into a full cache bypass and stampedes the database.

Functions

This section is empty.

Types

type AdapterCache deprecated

type AdapterCache interface {
	String() string
	Get(key string) (string, error)
	Set(key string, val interface{}, expire int) error
	Del(key string) error
	HashGet(hk, key string) (string, error)
	HashDel(hk, key string) error
	Increase(key string) error
	Decrease(key string) error
	Expire(key string, dur time.Duration) error
}

AdapterCache is the original cache contract.

Deprecated: use Cache. This interface cannot report a miss (Get returns an empty string and a nil error for both an absent key and a stored empty string), carries no context, has no Close, and its Hash family shares one flat key space with ordinary keys. Wrap a Cache with LegacyAdapter to keep existing call sites working. To be removed in v2.0.0.

func LegacyAdapter

func LegacyAdapter(c Cache) AdapterCache

LegacyAdapter exposes a Cache through the older AdapterCache interface, so a new backend can be adopted without touching the call sites that still take AdapterCache — captcha.NewCacheStore and Runtime.SetCacheAdapter among them.

It cannot repair the older contract, only preserve it:

  • Get reports a miss as ("", nil), which is indistinguishable from a stored empty string. Callers that need to tell them apart must move to Cache.
  • HashGet and HashDel concatenate their arguments, matching the previous in-memory behaviour. That shares one flat key space with ordinary keys, so HashGet("a", "bc") and Set("abc", …) collide. The Hash family is not carried over to Cache for this reason.

type AdapterQueue

type AdapterQueue interface {
	String() string
	Append(message Messager) error
	Register(name string, f ConsumerFunc)
	Run()
	Shutdown()
}

func LegacyQueueAdapter

func LegacyQueueAdapter(q Queue) AdapterQueue

LegacyQueueAdapter exposes a Queue through the older AdapterQueue interface, so a backend can be selected by configuration without changing the call sites that still take AdapterQueue.

It cannot repair the older contract, only preserve it:

  • Register returns nothing, so a rejected topic or an unreachable backend can only be logged. Subscribe reports both; use it where that matters.
  • ConsumerFunc takes no context, so a cancelled Start does not reach a handler that is already running.
  • Messager counts errors while Message counts deliveries. GetErrorCount is therefore Attempts minus one, since the first delivery has not failed.

type Cache

type Cache interface {
	// Get returns the value stored under key, or ErrCacheMiss when the key is
	// absent or expired. An empty string is a legal value and is returned with
	// a nil error.
	Get(ctx context.Context, key string) (string, error)

	// Set stores a value with a time to live. A ttl of zero or less means the
	// entry never expires.
	Set(ctx context.Context, key, val string, ttl time.Duration) error

	// Del removes keys. Removing an absent key is not an error.
	Del(ctx context.Context, keys ...string) error

	// Incr atomically adds delta and returns the resulting value. An absent key
	// starts from zero. delta may be negative. A key created this way has no
	// ttl; call Expire to add one. The read-modify-write must be atomic.
	Incr(ctx context.Context, key string, delta int64) (int64, error)

	// Expire resets the time to live, returning ErrCacheMiss when the key is
	// absent. A ttl of zero or less makes the entry permanent.
	Expire(ctx context.Context, key string, ttl time.Duration) error

	// Close releases the underlying resources. It is idempotent. Afterwards
	// every other method returns ErrCacheClosed, unless ctx is already done,
	// in which case the context error wins.
	io.Closer
}

Cache is the contract for a key/value cache.

Implementations must honour ctx cancellation and deadlines, and must not swallow ctx.Err(). The context is checked first: a cancelled context yields its own error even on a closed Cache, so a caller that gave up is never told something else went wrong.

func WithPrefix

func WithPrefix(c Cache, prefix string) Cache

WithPrefix returns a Cache that prefixes every key, so that several applications can share one backend.

This is a decorator rather than a method on the interface, mirroring the Logger decorators already used in this repository.

type ConsumerFunc

type ConsumerFunc func(Messager) error

type Handler

type Handler func(ctx context.Context, msg Message) error

Handler processes one message. Returning an error marks the delivery as failed; whether that leads to a retry is the implementation's decision, but Attempts must reflect it.

type Message

type Message struct {
	// ID is assigned by the queue on publish. It is ignored on input.
	ID string

	// Topic routes the message to a handler.
	Topic string

	// Values carries the payload.
	//
	// Only string values are guaranteed to arrive unchanged. Everything else is
	// undefined across implementations, because a broker-backed queue has to
	// serialise the map and an in-process one does not: the Redis queue returns
	// a published int as a float64, the memory queue returns the int. Use
	// strings, or encode the payload yourself.
	Values map[string]interface{}

	// Attempts counts deliveries of this message, starting at 1. A handler can
	// use it to give up on a message that keeps failing.
	Attempts int
}

Message is a queued message.

It is a struct, not an interface: the previous Messager was ten getters and setters with a single implementation, so the indirection bought nothing. Values is a map rather than a byte slice to match the field model of Redis streams, which is the intended backend.

type Messager

type Messager interface {
	SetID(string)
	SetStream(string)
	SetValues(map[string]interface{})
	GetID() string
	GetStream() string
	GetValues() map[string]interface{}
	GetPrefix() string
	SetPrefix(string)
	SetErrorCount(count int)
	GetErrorCount() int
}

type Queue

type Queue interface {
	// Publish enqueues a message. The topic must have a subscriber, otherwise
	// ErrNoHandler is returned rather than dropping the message silently.
	Publish(ctx context.Context, msg Message) error

	// Subscribe registers the handler for a topic. It must be called before
	// Start, because an implementation may fix its set of topics there and a
	// late subscription would then let Publish succeed with nothing reading it.
	//
	// Where more than one rule is broken at once, every implementation has to
	// answer alike: a bad argument outranks the queue's state, and among
	// states the terminal one outranks the rest. So ErrNilHandler, then
	// ErrQueueClosed, then ErrQueueAlreadyStarted, then
	// ErrTopicAlreadySubscribed.
	Subscribe(topic string, h Handler) error

	// Start begins consuming and blocks until ctx is done or an unrecoverable
	// error occurs. A context cancellation is not an error.
	Start(ctx context.Context) error

	// Close stops accepting new messages and waits for in-flight deliveries to
	// finish. It is idempotent. Bound the wait with a context of your own if
	// you need to.
	io.Closer
}

Queue is the contract for a message queue.

Directories

Path Synopsis
Package cachetest provides a black-box conformance suite for storage.Cache implementations.
Package cachetest provides a black-box conformance suite for storage.Cache implementations.
Package redis implements storage.Cache and storage.Queue on top of Redis.
Package redis implements storage.Cache and storage.Queue on top of Redis.

Jump to

Keyboard shortcuts

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