Files

46 lines
1.7 KiB
Go

package durability
import "errors"
// TerminalClassifier is implemented by errors that know whether they are permanent.
// RestateDurableCtx checks this interface: errors marked terminal are wrapped with
// restate.TerminalError so Restate stops retrying immediately.
type TerminalClassifier interface {
IsTerminal() bool
}
// PermanentError marks an error as terminal for durable execution.
// Use this to wrap errors that should never be retried (e.g., resource not found,
// invalid configuration) without importing Restate.
type PermanentError struct{ Err error }
func (e *PermanentError) Error() string { return e.Err.Error() }
func (e *PermanentError) Unwrap() error { return e.Err }
func (e *PermanentError) IsTerminal() bool { return true }
// RetryableError marks an error as retryable for durable execution.
// By default all errors are terminal (no retry). Wrap with this to allow
// Restate to retry (e.g., transient network errors, rate limits).
type RetryableError struct{ Err error }
func (e *RetryableError) Error() string { return e.Err.Error() }
func (e *RetryableError) Unwrap() error { return e.Err }
func (e *RetryableError) IsTerminal() bool { return false }
// IsTerminalError checks whether err should be treated as terminal.
// Returns true unless the error (or any in its chain) is explicitly marked
// retryable via RetryableError.
func IsTerminalError(err error) bool {
var tc TerminalClassifier
if errors.As(err, &tc) {
return tc.IsTerminal()
}
return true
}
// IsRetryableError checks whether err is explicitly marked as retryable.
func IsRetryableError(err error) bool {
var tc TerminalClassifier
return errors.As(err, &tc) && !tc.IsTerminal()
}