mirror of
https://github.com/redis/go-redis.git
synced 2025-09-10 07:11:50 +03:00
* feat(hitless): Introduce handlers for hitless upgrades This commit includes all the work on hitless upgrades with the addition of: - Pubsub Pool - Examples - Refactor of push - Refactor of pool (using atomics for most things) - Introducing of hooks in pool --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
106 lines
3.9 KiB
Go
106 lines
3.9 KiB
Go
package hitless
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Configuration errors
|
|
var (
|
|
ErrInvalidRelaxedTimeout = errors.New("hitless: relaxed timeout must be greater than 0")
|
|
ErrInvalidHandoffTimeout = errors.New("hitless: handoff timeout must be greater than 0")
|
|
ErrInvalidHandoffWorkers = errors.New("hitless: MaxWorkers must be greater than or equal to 0")
|
|
ErrInvalidHandoffQueueSize = errors.New("hitless: handoff queue size must be greater than 0")
|
|
ErrInvalidPostHandoffRelaxedDuration = errors.New("hitless: post-handoff relaxed duration must be greater than or equal to 0")
|
|
ErrInvalidLogLevel = errors.New("hitless: log level must be LogLevelError (0), LogLevelWarn (1), LogLevelInfo (2), or LogLevelDebug (3)")
|
|
ErrInvalidEndpointType = errors.New("hitless: invalid endpoint type")
|
|
ErrInvalidMaintNotifications = errors.New("hitless: invalid maintenance notifications setting (must be 'disabled', 'enabled', or 'auto')")
|
|
ErrMaxHandoffRetriesReached = errors.New("hitless: max handoff retries reached")
|
|
|
|
// Configuration validation errors
|
|
ErrInvalidHandoffRetries = errors.New("hitless: MaxHandoffRetries must be between 1 and 10")
|
|
)
|
|
|
|
// Integration errors
|
|
var (
|
|
ErrInvalidClient = errors.New("hitless: invalid client type")
|
|
)
|
|
|
|
// Handoff errors
|
|
var (
|
|
ErrHandoffQueueFull = errors.New("hitless: handoff queue is full, cannot queue new handoff requests - consider increasing HandoffQueueSize or MaxWorkers in configuration")
|
|
)
|
|
|
|
// Notification errors
|
|
var (
|
|
ErrInvalidNotification = errors.New("hitless: invalid notification format")
|
|
)
|
|
|
|
// connection handoff errors
|
|
var (
|
|
// ErrConnectionMarkedForHandoff is returned when a connection is marked for handoff
|
|
// and should not be used until the handoff is complete
|
|
ErrConnectionMarkedForHandoff = errors.New("hitless: connection marked for handoff")
|
|
// ErrConnectionInvalidHandoffState is returned when a connection is in an invalid state for handoff
|
|
ErrConnectionInvalidHandoffState = errors.New("hitless: connection is in invalid state for handoff")
|
|
)
|
|
|
|
// general errors
|
|
var (
|
|
ErrShutdown = errors.New("hitless: shutdown")
|
|
)
|
|
|
|
// circuit breaker errors
|
|
var (
|
|
ErrCircuitBreakerOpen = errors.New("hitless: circuit breaker is open, failing fast")
|
|
)
|
|
|
|
// CircuitBreakerError provides detailed context for circuit breaker failures
|
|
type CircuitBreakerError struct {
|
|
Endpoint string
|
|
State string
|
|
Failures int64
|
|
LastFailure time.Time
|
|
NextAttempt time.Time
|
|
Message string
|
|
}
|
|
|
|
func (e *CircuitBreakerError) Error() string {
|
|
if e.NextAttempt.IsZero() {
|
|
return fmt.Sprintf("hitless: circuit breaker %s for %s (failures: %d, last: %v): %s",
|
|
e.State, e.Endpoint, e.Failures, e.LastFailure, e.Message)
|
|
}
|
|
return fmt.Sprintf("hitless: circuit breaker %s for %s (failures: %d, last: %v, next attempt: %v): %s",
|
|
e.State, e.Endpoint, e.Failures, e.LastFailure, e.NextAttempt, e.Message)
|
|
}
|
|
|
|
// HandoffError provides detailed context for connection handoff failures
|
|
type HandoffError struct {
|
|
ConnectionID uint64
|
|
SourceEndpoint string
|
|
TargetEndpoint string
|
|
Attempt int
|
|
MaxAttempts int
|
|
Duration time.Duration
|
|
FinalError error
|
|
Message string
|
|
}
|
|
|
|
func (e *HandoffError) Error() string {
|
|
return fmt.Sprintf("hitless: handoff failed for conn[%d] %s→%s (attempt %d/%d, duration: %v): %s",
|
|
e.ConnectionID, e.SourceEndpoint, e.TargetEndpoint,
|
|
e.Attempt, e.MaxAttempts, e.Duration, e.Message)
|
|
}
|
|
|
|
func (e *HandoffError) Unwrap() error {
|
|
return e.FinalError
|
|
}
|
|
|
|
// circuit breaker configuration errors
|
|
var (
|
|
ErrInvalidCircuitBreakerFailureThreshold = errors.New("hitless: circuit breaker failure threshold must be >= 1")
|
|
ErrInvalidCircuitBreakerResetTimeout = errors.New("hitless: circuit breaker reset timeout must be >= 0")
|
|
ErrInvalidCircuitBreakerMaxRequests = errors.New("hitless: circuit breaker max requests must be >= 1")
|
|
)
|