Documentation
¶
Overview ¶
pkg/adapter/error/backoff.go
pkg/adapter/error/coordinator.go
pkg/adapter/error/dlq.go
Package error provides resilience patterns: circuit breaker, retry with exponential backoff, dead letter queue (DLQ), and a coordinator that composes all three for robust error handling.
pkg/adapter/error/policy.go
pkg/adapter/error/retry.go
Index ¶
- func IsNonRetryable(err error) bool
- func IsRetryable(err error) bool
- func NewHTTPError(code int, message string) error
- func NewNonRetryableError(err error) error
- func NewRetryableError(err error) error
- type Backoff
- type BackoffConfig
- type Coordinator
- func (c *Coordinator) Execute(ctx context.Context, job *entity.Job, fn func(context.Context) error) error
- func (c *Coordinator) ExecuteWithResult(ctx context.Context, job *entity.Job, fn func(context.Context) (any, error)) (any, error)
- func (c *Coordinator) GetCircuitState() shared.CircuitBreakerState
- func (c *Coordinator) GetDLQCount(ctx context.Context) (int, error)
- func (c *Coordinator) RetryFromDLQ(ctx context.Context, jobID string) (*entity.Job, error)
- type CoordinatorConfig
- type DLQConfig
- type DLQEntry
- type DeadLetterQueue
- func (dlq *DeadLetterQueue) Add(ctx context.Context, job *entity.Job, err error) error
- func (dlq *DeadLetterQueue) Clear(ctx context.Context) error
- func (dlq *DeadLetterQueue) Count(ctx context.Context) (int, error)
- func (dlq *DeadLetterQueue) GetFailed(ctx context.Context, limit int) ([]*DLQEntry, error)
- func (dlq *DeadLetterQueue) GetRetryable(ctx context.Context, limit int) ([]*entity.Job, error)
- func (dlq *DeadLetterQueue) Remove(ctx context.Context, jobID string) error
- func (dlq *DeadLetterQueue) Retry(ctx context.Context, jobID string) (*entity.Job, error)
- type HTTPStatusCodeError
- type NonRetryableError
- type RetryConfig
- type RetryHandler
- type RetryPolicy
- type RetryableError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsNonRetryable ¶
IsNonRetryable checks if the error is non-retriable
func NewHTTPError ¶
NewHTTPError creates a new HTTP status code error
func NewNonRetryableError ¶
NewNonRetryableError wraps an error as non-retriable
func NewRetryableError ¶
NewRetryableError wraps an error as retriable
Types ¶
type Backoff ¶
type Backoff struct {
// contains filtered or unexported fields
}
Backoff calculates backoff durations with exponential strategy
func NewBackoff ¶
func NewBackoff(config BackoffConfig) *Backoff
NewBackoff creates a new backoff calculator
func (*Backoff) NextSequence ¶
NextSequence returns a sequence of backoff durations for visualization/testing
type BackoffConfig ¶
type BackoffConfig struct {
// InitialDelay is the initial backoff duration
InitialDelay time.Duration
// MaxDelay is the maximum backoff duration (cap)
MaxDelay time.Duration
// Multiplier is the backoff multiplier for exponential backoff
Multiplier float64
// JitterEnabled adds randomness to backoff
JitterEnabled bool
}
BackoffConfig holds backoff configuration
type Coordinator ¶
type Coordinator struct {
// contains filtered or unexported fields
}
Coordinator orchestrates error handling strategies (retry, circuit breaker, DLQ)
func NewCoordinator ¶
func NewCoordinator(config CoordinatorConfig, retry *RetryHandler, circuit *shared.CircuitBreaker, dlq *DeadLetterQueue) *Coordinator
NewCoordinator creates a new error handling coordinator
func (*Coordinator) Execute ¶
func (c *Coordinator) Execute(ctx context.Context, job *entity.Job, fn func(context.Context) error) error
Execute runs a function with full error handling (retry, circuit breaker, DLQ)
Execution flow: 1. Check circuit breaker state (fail fast if open) 2. Execute function with retry logic (if enabled) 3. Add to DLQ if all retries exhausted (if enabled) 4. Return error to caller
This respects hexagonal architecture: - Coordinator is an adapter (infrastructure layer) - It coordinates other adapters (retry, circuit, DLQ) - No business logic, pure infrastructure orchestration
func (*Coordinator) ExecuteWithResult ¶
func (c *Coordinator) ExecuteWithResult(ctx context.Context, job *entity.Job, fn func(context.Context) (any, error)) (any, error)
ExecuteWithResult runs a function that returns a result, with full error handling
func (*Coordinator) GetCircuitState ¶
func (c *Coordinator) GetCircuitState() shared.CircuitBreakerState
GetCircuitState returns the current circuit breaker state (for monitoring)
func (*Coordinator) GetDLQCount ¶
func (c *Coordinator) GetDLQCount(ctx context.Context) (int, error)
GetDLQCount returns the number of failed jobs in DLQ (for monitoring)
func (*Coordinator) RetryFromDLQ ¶
RetryFromDLQ attempts to retry a job from the DLQ
type CoordinatorConfig ¶
type CoordinatorConfig struct {
// EnableRetry enables retry logic with exponential backoff
EnableRetry bool
// EnableCircuit enables circuit breaker pattern
EnableCircuit bool
// EnableDLQ enables dead letter queue for failed jobs
EnableDLQ bool
}
CoordinatorConfig holds configuration for error handling orchestration
func DefaultCoordinatorConfig ¶
func DefaultCoordinatorConfig() CoordinatorConfig
DefaultCoordinatorConfig returns sensible defaults
type DLQConfig ¶
type DLQConfig struct {
// Storage is the persistence adapter for failed jobs
Storage port.StoragePort
// RetryAfter is the cooldown period before retry (default: 5 minutes)
RetryAfter time.Duration
// MaxAttempts is max retry attempts for DLQ entries (default: 3)
MaxAttempts int
}
DLQConfig holds DLQ configuration
type DLQEntry ¶
type DLQEntry struct {
JobID string `json:"job_id"`
Priority entity.Priority `json:"priority"`
Payload any `json:"payload"`
Error string `json:"error"`
Timestamp time.Time `json:"timestamp"`
Attempts int `json:"attempts"`
NextRetry *time.Time `json:"next_retry,omitempty"`
}
DLQEntry represents a failed job in the dead letter queue
type DeadLetterQueue ¶
type DeadLetterQueue struct {
// contains filtered or unexported fields
}
DeadLetterQueue manages failed jobs
func NewDeadLetterQueue ¶
func NewDeadLetterQueue(config DLQConfig) (*DeadLetterQueue, error)
NewDeadLetterQueue creates a new dead letter queue
func (*DeadLetterQueue) Clear ¶
func (dlq *DeadLetterQueue) Clear(ctx context.Context) error
Clear removes all entries from the DLQ
func (*DeadLetterQueue) Count ¶
func (dlq *DeadLetterQueue) Count(ctx context.Context) (int, error)
Count returns the number of failed jobs in the DLQ
func (*DeadLetterQueue) GetRetryable ¶
GetRetryable retrieves jobs that are ready for retry
type HTTPStatusCodeError ¶
HTTPStatusCodeError is an error that includes an HTTP status code
func (*HTTPStatusCodeError) Error ¶
func (e *HTTPStatusCodeError) Error() string
func (*HTTPStatusCodeError) StatusCode ¶
func (e *HTTPStatusCodeError) StatusCode() int
type NonRetryableError ¶
type NonRetryableError struct {
Err error
}
NonRetryableError is an error type that should not be retried
func (*NonRetryableError) Error ¶
func (e *NonRetryableError) Error() string
func (*NonRetryableError) Unwrap ¶
func (e *NonRetryableError) Unwrap() error
type RetryConfig ¶
type RetryConfig struct {
// MaxAttempts is the maximum number of retry attempts (including initial attempt)
MaxAttempts int
// InitialDelay is the initial backoff duration
InitialDelay time.Duration
// MaxDelay is the maximum backoff duration (cap)
MaxDelay time.Duration
// Multiplier is the backoff multiplier for exponential backoff
Multiplier float64
// JitterEnabled adds randomness to backoff to prevent thundering herd
JitterEnabled bool
}
RetryConfig holds retry configuration
func DefaultRetryConfig ¶
func DefaultRetryConfig() RetryConfig
DefaultRetryConfig returns a sensible default configuration
type RetryHandler ¶
type RetryHandler struct {
// contains filtered or unexported fields
}
RetryHandler handles retry logic with exponential backoff
func NewRetryHandler ¶
func NewRetryHandler(config RetryConfig) *RetryHandler
NewRetryHandler creates a new retry handler
func (*RetryHandler) Do ¶
func (rh *RetryHandler) Do(ctx context.Context, fn func() error) error
Do executes the function with retry logic
func (*RetryHandler) DoWithResult ¶
DoWithResult executes a function that returns a result and error, with retry logic
func (*RetryHandler) SetPolicy ¶
func (rh *RetryHandler) SetPolicy(policy *RetryPolicy)
SetPolicy sets a custom retry policy
type RetryPolicy ¶
type RetryPolicy struct {
// contains filtered or unexported fields
}
RetryPolicy determines which errors are retriable
func NewRetryPolicy ¶
func NewRetryPolicy() *RetryPolicy
NewRetryPolicy creates a new retry policy with default retriable errors
func (*RetryPolicy) AddRetriableError ¶
func (p *RetryPolicy) AddRetriableError(err error)
AddRetriableError adds an error to the retriable error list
func (*RetryPolicy) ClearCustomCheck ¶
func (p *RetryPolicy) ClearCustomCheck()
ClearCustomCheck clears the custom check function
func (*RetryPolicy) IsRetriable ¶
func (p *RetryPolicy) IsRetriable(err error) bool
IsRetriable checks if an error should be retried
func (*RetryPolicy) RemoveRetriableError ¶
func (p *RetryPolicy) RemoveRetriableError(err error)
RemoveRetriableError removes an error from the retriable error list
func (*RetryPolicy) SetCustomCheck ¶
func (p *RetryPolicy) SetCustomCheck(fn func(error) bool)
SetCustomCheck sets a custom function to determine if an error is retriable
type RetryableError ¶
type RetryableError struct {
Err error
}
RetryableError is an error type that can be retried
func (*RetryableError) Error ¶
func (e *RetryableError) Error() string
func (*RetryableError) Unwrap ¶
func (e *RetryableError) Unwrap() error