Documentation
¶
Overview ¶
Package middleware provides composable middleware for Grove KV operations.
Each middleware implements hook.PreQueryHook and/or hook.PostQueryHook and is registered via kv.WithHook() during store creation.
Index ¶
- Variables
- type CacheHook
- func (h *CacheHook) AfterQuery(_ context.Context, qc *hook.QueryContext, result any) error
- func (h *CacheHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
- func (h *CacheHook) Evict(keys ...string)
- func (h *CacheHook) Flush()
- func (h *CacheHook) Put(key string, value []byte, ttl time.Duration)
- func (h *CacheHook) Size() int
- type CircuitBreakerHook
- type CircuitState
- type CompressHook
- func (h *CompressHook) AfterQuery(_ context.Context, qc *hook.QueryContext, result any) error
- func (h *CompressHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
- func (h *CompressHook) Compress(data []byte) ([]byte, error)
- func (h *CompressHook) Decompress(data []byte) ([]byte, error)
- type CompressionAlgorithm
- type EncryptHook
- type LoggingHook
- type NamespaceHook
- type RetryHook
- type RetryOption
- type StampedeHook
Constants ¶
This section is empty.
Variables ¶
var ErrCircuitOpen = errors.New("kv: circuit breaker is open")
ErrCircuitOpen is returned when the circuit breaker is open.
Functions ¶
This section is empty.
Types ¶
type CacheHook ¶
type CacheHook struct {
// contains filtered or unexported fields
}
CacheHook provides a local in-memory L1 cache in front of the remote store. It supports read-through (check local first, then remote) and write-through (write to both local and remote on Set).
func NewCache ¶
NewCache creates a new L1 cache middleware. maxEntries limits cache size; defaultTTL sets TTL for cached entries.
func (*CacheHook) AfterQuery ¶
func (*CacheHook) BeforeQuery ¶
func (h *CacheHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
type CircuitBreakerHook ¶
type CircuitBreakerHook struct {
// contains filtered or unexported fields
}
CircuitBreakerHook protects against cascading failures when the backing store is unavailable.
func NewCircuitBreaker ¶
func NewCircuitBreaker(threshold int, timeout time.Duration) *CircuitBreakerHook
NewCircuitBreaker creates a new circuit breaker middleware.
threshold is the number of consecutive failures before opening the circuit. timeout is the duration the circuit stays open before transitioning to half-open.
func (*CircuitBreakerHook) BeforeQuery ¶
func (h *CircuitBreakerHook) BeforeQuery(_ context.Context, _ *hook.QueryContext) (*hook.HookResult, error)
func (*CircuitBreakerHook) RecordFailure ¶
func (h *CircuitBreakerHook) RecordFailure()
RecordFailure records a failed operation, potentially opening the circuit.
func (*CircuitBreakerHook) RecordSuccess ¶
func (h *CircuitBreakerHook) RecordSuccess()
RecordSuccess records a successful operation, potentially closing the circuit.
func (*CircuitBreakerHook) State ¶
func (h *CircuitBreakerHook) State() CircuitState
State returns the current circuit breaker state.
type CircuitState ¶
type CircuitState int
CircuitState represents the state of the circuit breaker.
const ( // StateClosed means the circuit is healthy — requests flow normally. StateClosed CircuitState = iota // StateOpen means the circuit has tripped — requests are rejected immediately. StateOpen // StateHalfOpen means the circuit is testing — a limited number of requests are allowed. StateHalfOpen )
type CompressHook ¶
type CompressHook struct {
// contains filtered or unexported fields
}
CompressHook provides transparent value compression/decompression.
func NewCompress ¶
func NewCompress(algo CompressionAlgorithm, threshold ...int) *CompressHook
NewCompress creates a new compression middleware. The threshold is the minimum value size in bytes before compression is applied. A threshold of 0 compresses all values.
func (*CompressHook) AfterQuery ¶
func (h *CompressHook) AfterQuery(_ context.Context, qc *hook.QueryContext, result any) error
func (*CompressHook) BeforeQuery ¶
func (h *CompressHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
func (*CompressHook) Compress ¶
func (h *CompressHook) Compress(data []byte) ([]byte, error)
Compress compresses data using the configured algorithm.
func (*CompressHook) Decompress ¶
func (h *CompressHook) Decompress(data []byte) ([]byte, error)
Decompress decompresses data if it was compressed.
type CompressionAlgorithm ¶
type CompressionAlgorithm int
CompressionAlgorithm identifies a compression algorithm.
const ( // Gzip uses gzip compression (widely supported, good compression ratio). Gzip CompressionAlgorithm = iota )
type EncryptHook ¶
type EncryptHook struct {
// contains filtered or unexported fields
}
EncryptHook provides transparent AES-GCM encryption for values at rest.
func NewEncrypt ¶
func NewEncrypt(key []byte) (*EncryptHook, error)
NewEncrypt creates a new encryption middleware with the given AES key. The key must be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256.
type LoggingHook ¶
type LoggingHook struct {
// contains filtered or unexported fields
}
LoggingHook logs every KV operation with structured fields.
func NewLogging ¶
func NewLogging(logger log.Logger) *LoggingHook
NewLogging creates a new logging middleware.
func (*LoggingHook) AfterQuery ¶
func (h *LoggingHook) AfterQuery(ctx context.Context, qc *hook.QueryContext, result any) error
func (*LoggingHook) BeforeQuery ¶
func (h *LoggingHook) BeforeQuery(ctx context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
type NamespaceHook ¶
type NamespaceHook struct {
// contains filtered or unexported fields
}
NamespaceHook automatically prepends a prefix to all keys. This is useful for multi-tenant isolation at the key level.
func NewNamespace ¶
func NewNamespace(prefix string, separator ...string) *NamespaceHook
NewNamespace creates a namespace middleware that prepends the given prefix to all keys (e.g., "tenant:acme" → "tenant:acme:user:123").
func (*NamespaceHook) BeforeQuery ¶
func (h *NamespaceHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
type RetryHook ¶
type RetryHook struct {
// contains filtered or unexported fields
}
RetryHook provides automatic retry with configurable backoff for transient failures.
func NewRetry ¶
func NewRetry(maxAttempts int, opts ...RetryOption) *RetryHook
NewRetry creates a retry middleware with the given maximum attempts.
func (*RetryHook) AfterQuery ¶
func (*RetryHook) BackoffDuration ¶
BackoffDuration calculates the backoff duration for the given attempt (0-indexed).
func (*RetryHook) MaxAttempts ¶
MaxAttempts returns the configured maximum number of retry attempts.
type RetryOption ¶
type RetryOption func(*RetryHook)
RetryOption configures the retry middleware.
func WithInitialWait ¶
func WithInitialWait(d time.Duration) RetryOption
WithInitialWait sets the initial wait duration before the first retry.
func WithJitter ¶
func WithJitter(enabled bool) RetryOption
WithJitter enables or disables random jitter on retry delays.
func WithMaxWait ¶
func WithMaxWait(d time.Duration) RetryOption
WithMaxWait sets the maximum wait duration between retries.
type StampedeHook ¶
type StampedeHook struct {
// contains filtered or unexported fields
}
StampedeHook provides singleflight-based cache stampede protection. When multiple goroutines request the same key concurrently, only one performs the actual fetch; others wait and share the result.
func NewStampede ¶
func NewStampede() *StampedeHook
NewStampede creates a new stampede protection middleware.
func (*StampedeHook) BeforeQuery ¶
func (h *StampedeHook) BeforeQuery(_ context.Context, qc *hook.QueryContext) (*hook.HookResult, error)
func (*StampedeHook) Complete ¶
func (h *StampedeHook) Complete(key string)
Complete signals that the GET for this key is done. This should be called after the operation completes.