Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrBackendNotFound = errors.New("backend not found") ErrInvalidConfig = errors.New("invalid backend configuration") )
var ErrUnhealthy = errors.New("backend unhealthy")
ErrUnhealthy is a sentinel used to signal that the backend is unhealthy/unavailable.
Functions ¶
func IsHealthError ¶ added in v0.0.9
IsHealthError reports whether err indicates backend is unhealthy. This function checks for both the ErrUnhealthy sentinel and any wrapped HealthError. It returns true for:
- ErrUnhealthy sentinel errors
- HealthError instances (direct or wrapped)
- Any error that wraps a HealthError via error chaining
It returns false for regular operational errors that should not trigger failover.
func MaybeConnError ¶ added in v0.0.9
MaybeConnError checks if the error is a connectivity issue using the provided patterns.
The op parameter should describe the operation being performed (e.g., "redis:Get", "postgres:Ping"). patterns contains lowercase string patterns to match against error messages. If patterns is nil, no pattern matching is performed.
Returns a HealthError if the error matches any pattern or is a context error, otherwise returns the original error.
Examples:
err := MaybeConnError("myBackend:Connect", connErr, []string{"connection refused", "timeout"})
// Returns HealthError if error matches patterns
err := MaybeConnError("myBackend:Get", ioErr, nil)
// Returns HealthError if context error, otherwise returns original error
func NewHealthError ¶ added in v0.0.9
NewHealthError wraps a cause as a health error with context. The op parameter should describe the logical operation being performed (e.g., "redis:Ping", "postgres:Get"). If cause is nil, the sentinel ErrUnhealthy is returned. The returned error implements both errors.Is(ErrUnhealthy) and errors.As(*HealthError) for type checking.
func Register ¶ added in v0.0.3
func Register(name string, factory BackendFactory)
Register registers a backend factory function
Types ¶
type Backend ¶
type Backend interface {
// Get retrieves a value from storage
Get(ctx context.Context, key string) (string, error)
// Set stores a value with expiration
Set(ctx context.Context, key string, value string, expiration time.Duration) error
// CheckAndSet atomically sets key to newValue only if current value matches oldValue.
// This operation provides compare-and-swap (CAS) semantics for implementing optimistic locking.
//
// Parameters:
// - ctx: Context for cancellation and timeouts
// - key: The storage key to operate on
// - oldValue: Expected current value. Use empty string "" for "set if not exists" semantics
// - newValue: New value to set if the current value matches oldValue
// - expiration: Time-to-live for the key. Use 0 for no expiration
//
// Returns:
// - bool: true if the CAS succeeded (value was set), false if the compare failed and no write occurred
// - error: Any storage-related error (not including a compare mismatch)
//
// Behavior:
// - If oldValue is "", the operation succeeds only if the key does not exist (or is expired)
// - If oldValue matches the current value, the key is updated to newValue
// - Expired keys are treated as non-existent for comparison purposes
// - All values are stored and compared as strings
//
// Caller contract:
// - A (false, nil) return indicates the compare condition did not match (e.g., another writer won the race
// or the key already exists when using "set if not exists"). This is not an error. Callers may safely
// reload state and retry with backoff according to their contention policy.
// - A non-nil error indicates a storage/backend failure and should not be retried blindly.
CheckAndSet(ctx context.Context, key string, oldValue, newValue string, expiration time.Duration) (bool, error)
// Delete removes a key from storage
Delete(ctx context.Context, key string) error
// Close releases resources used by the storage backend
Close() error
}
Backend defines the storage interface for atomic operations
type BackendFactory ¶ added in v0.0.3
BackendFactory creates a backend instance with optional configuration
type HealthError ¶ added in v0.0.9
type HealthError struct {
Op string // logical operation context, e.g. "redis:ScriptLoad", "postgres:Ping", "get"
Cause error // underlying error returned by driver/client
}
HealthError wraps an underlying cause with operation context. Use for connectivity/auth/TLS/unavailability issues.
func (*HealthError) Error ¶ added in v0.0.9
func (e *HealthError) Error() string
Error returns a formatted error message that includes the operation context and underlying cause. For a HealthError with Op="redis:Ping" and Cause="connection refused", this returns: "backend unhealthy: redis:Ping: connection refused" If Op is empty, it returns: "backend unhealthy: connection refused" If the receiver is nil, it returns the sentinel error message.
func (*HealthError) Is ¶ added in v0.0.9
func (e *HealthError) Is(target error) bool
Is implements errors.Is to allow matching against ErrUnhealthy sentinel. This enables using errors.Is(err, ErrUnhealthy) to detect health errors.
func (*HealthError) Unwrap ¶ added in v0.0.9
func (e *HealthError) Unwrap() error
Unwrap returns the underlying cause error, enabling error chaining with errors.Unwrap.