temporal

package
v1.42.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package temporal provides native Hanzo Tasks workflow primitives (retry policy, error model, failure serialisation) with zero dependency on any go.temporal.io/* package.

This package is consumed directly by user code (workflows, activities) and indirectly by the rest of the SDK (pkg/sdk/workflow, pkg/sdk/activity, pkg/sdk/client, pkg/sdk/worker). It is deliberately tiny and has no imports outside the Go standard library.

Index

Constants

View Source
const (
	// CodeApplication is the default code for an error produced by
	// user workflow/activity code via NewError. It carries the
	// user-supplied type tag in Error.Code; this constant is used
	// only when the caller did not supply one.
	CodeApplication = "ApplicationError"

	// CodeCanceled marks an error arising from a workflow / activity
	// cancellation. Non-retryable by construction.
	CodeCanceled = "CanceledError"

	// CodeTimeout marks an error arising from schedule-to-close,
	// start-to-close, or heartbeat timeouts. Non-retryable.
	CodeTimeout = "TimeoutError"

	// CodeDecode marks an error produced by the failure decoder
	// when given bytes it cannot parse. Non-retryable.
	CodeDecode = "DecodeError"
)

Sentinel Code values carried on the wire in Error.Code. They are matched by IsCanceledError / IsTimeoutError and can be listed in RetryPolicy.NonRetryableErrorTypes.

Variables

View Source
var (

	// Canceled is the sentinel used with errors.Is to detect a
	// canceled-class error anywhere in the chain.
	Canceled error = canceledSentinel

	// Timeout is the sentinel used with errors.Is to detect a
	// timeout-class error anywhere in the chain.
	Timeout error = timeoutSentinel
)

canceledSentinel / timeoutSentinel back the Canceled / Timeout package-level values used with errors.Is. They carry only the Code field so the Is() comparison is code-only.

Functions

func Encode

func Encode(err error) ([]byte, error)

Encode serialises err into the bytes that live in the `failure` field of RespondActivityTaskFailedRequest (schema/tasks.zap).

If err is not already an *Error it is wrapped as an ApplicationError with the original message preserved. Non-JSON-serialisable details are replaced by their error string so Encode never fails on input (workers must not get stuck unable to report a failure).

func IsApplicationError

func IsApplicationError(err error) bool

IsApplicationError reports whether err (or anything it wraps) is an *Error with an application-class Code — i.e. it was produced by user code via NewError, not a canceled or timeout sentinel.

func IsCanceledError

func IsCanceledError(err error) bool

IsCanceledError reports whether err (or anything it wraps) is a canceled-class *Error.

func IsTimeoutError

func IsTimeoutError(err error) bool

IsTimeoutError reports whether err (or anything it wraps) is a timeout-class *Error.

Types

type Error

type Error struct {
	// Message is the human-readable error text. Safe to log.
	Message string

	// Code is a stable, machine-readable tag. Callers compare
	// against this to decide whether to retry, branch, etc. It is
	// the field listed in RetryPolicy.NonRetryableErrorTypes.
	//
	// Reserved values: CodeApplication, CodeCanceled, CodeTimeout,
	// CodeDecode. Anything else is user-defined.
	Code string

	// NonRetryable short-circuits retry regardless of MaximumAttempts.
	// Canceled and Timeout errors are always non-retryable.
	NonRetryable bool

	// Details carries arbitrary user payloads attached at the
	// failure site. Must be JSON-serialisable. Decoders surface
	// them as []any.
	Details []any

	// Cause wraps the underlying Go error, if any. errors.Unwrap
	// exposes it so errors.Is / errors.As chains work.
	Cause error
}

Error is the one and only error type this SDK emits for workflow/activity failures. Having a single concrete type keeps classification trivial (type assertion + Code check) and serialisation obvious.

The zero value is a usable but uninformative error. Prefer the constructors below.

func AsError

func AsError(err error) (*Error, bool)

AsError is a typed wrapper around errors.As for *Error. Returns the embedded *Error and true on hit, nil and false otherwise.

func Decode

func Decode(b []byte) *Error

Decode parses bytes produced by Encode back into an *Error.

Fail-secure: any parsing problem returns a non-retryable DecodeError whose message identifies the failure class, never a nil pointer and never a panic. Callers can feed hostile bytes.

func NewCanceledError

func NewCanceledError(details ...any) *Error

NewCanceledError constructs a canceled error. Canceled errors are always non-retryable.

func NewError

func NewError(msg, code string, nonRetryable bool, details ...any) *Error

NewError constructs an Error. msg is the human-readable message, code is the machine-readable type tag (empty => CodeApplication), nonRetryable forces retry short-circuit, and details is an arbitrary JSON-serialisable payload attached to the failure.

This is the one, canonical constructor. Previous upstream callers that used NewApplicationError(msg, code, details...) map to NewError(msg, code, false, details...).

func NewErrorWithCause

func NewErrorWithCause(msg, code string, cause error, nonRetryable bool, details ...any) *Error

NewErrorWithCause is NewError with a wrapped underlying error. Equivalent to NewError + manual .Cause assignment; kept for call sites that previously used NewApplicationErrorWithCause.

func NewTimeoutError

func NewTimeoutError(msg string, details ...any) *Error

NewTimeoutError constructs a timeout error. Timeout errors are always non-retryable.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) Is

func (e *Error) Is(target error) bool

Is lets callers match via errors.Is(err, Canceled) etc., using the sentinel values declared below.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap allows errors.Is / errors.As to reach the underlying cause.

type RetryPolicy

type RetryPolicy struct {
	// InitialInterval is the delay before the first retry.
	// Zero means "use DefaultRetryPolicy().InitialInterval".
	InitialInterval time.Duration

	// BackoffCoefficient multiplies the interval on each retry.
	// Must be >= 1.0. Zero means "use default (2.0)".
	BackoffCoefficient float64

	// MaximumInterval caps the exponential backoff. Zero means
	// "100 * InitialInterval" (matches upstream default).
	MaximumInterval time.Duration

	// MaximumAttempts bounds the total retry count including the
	// first execution. 0 = unlimited, 1 = no retries.
	MaximumAttempts int32

	// NonRetryableErrorTypes lists error Code values that skip
	// retry regardless of MaximumAttempts. See errors.go.
	NonRetryableErrorTypes []string
}

RetryPolicy controls how the engine retries a workflow or activity that returns an error. Semantics mirror the classic Temporal retry model so existing hanzoai/base and hanzoai/commerce call sites work unchanged after the import swap.

Wire form (schema/tasks.zap:RetryPolicy) uses int64 milliseconds; Go callers work with time.Duration. Conversion happens in serde.go.

func DefaultRetryPolicy

func DefaultRetryPolicy() *RetryPolicy

DefaultRetryPolicy returns the retry policy used when a workflow/activity has not configured one explicitly.

func (*RetryPolicy) NextInterval

func (p *RetryPolicy) NextInterval(attempt int32) time.Duration

NextInterval returns the delay before retry number `attempt` (1-based — attempt=1 is the delay before the first retry, which happens after the initial execution failed).

func (*RetryPolicy) Normalize

func (p *RetryPolicy) Normalize() *RetryPolicy

Normalize returns a copy of p with zero fields filled in from DefaultRetryPolicy. The input is not mutated. Callers who want to know the effective policy (for dispatch, for logging) use this. Callers who want to honour user-supplied zeros pass the policy through untouched.

func (*RetryPolicy) ShouldRetry

func (p *RetryPolicy) ShouldRetry(err error, attempt int32) bool

ShouldRetry reports whether an error produced at attempt n (1-based) under policy p should be retried. It is a pure function: it does not sleep, log, or call the network. Callers schedule the retry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL