mirror of
https://github.com/open-gitagent/langship.sh.git
synced 2026-08-03 07:21:04 +02:00
51 lines
1.8 KiB
Go
51 lines
1.8 KiB
Go
package durability
|
|
|
|
import (
|
|
"context"
|
|
|
|
restate "github.com/restatedev/sdk-go"
|
|
)
|
|
|
|
// RestateDurableCtx wraps a Restate Context to provide durable step execution.
|
|
// Each Run() call is journaled by Restate — on crash/restart, completed steps
|
|
// return cached results without re-execution.
|
|
// Works with any Restate context type (Context, ObjectContext, WorkflowContext).
|
|
type RestateDurableCtx struct {
|
|
Rctx restate.Context
|
|
}
|
|
|
|
func (d *RestateDurableCtx) run(name string, fn func(ctx context.Context) (any, error), opts ...restate.RunOption) (any, error) {
|
|
allOpts := append([]restate.RunOption{restate.WithName(name)}, opts...)
|
|
result, err := restate.Run(d.Rctx, func(rc restate.RunContext) (any, error) {
|
|
result, err := fn(rc)
|
|
if err != nil && !IsRetryableError(err) {
|
|
// Default: all errors are terminal unless explicitly wrapped
|
|
// in RetryableError by the caller.
|
|
return result, restate.TerminalError(err)
|
|
}
|
|
return result, err
|
|
}, allOpts...)
|
|
// On replay, Restate preserves terminal-ness (restate.IsTerminalError) but
|
|
// strips Go error types. Re-wrap as PermanentError so callers can use
|
|
// durability.IsTerminalError without parsing error strings.
|
|
if err != nil && restate.IsTerminalError(err) && !IsTerminalError(err) {
|
|
return result, &PermanentError{Err: err}
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
func (d *RestateDurableCtx) Run(name string, fn func(ctx context.Context) (any, error)) (any, error) {
|
|
return d.run(name, fn)
|
|
}
|
|
|
|
func (d *RestateDurableCtx) RunWithRetry(name string, policy RetryPolicy, fn func(ctx context.Context) (any, error)) (any, error) {
|
|
var opts []restate.RunOption
|
|
if policy.MaxAttempts > 0 {
|
|
opts = append(opts, restate.WithMaxRetryAttempts(uint(policy.MaxAttempts)))
|
|
}
|
|
if policy.InitialInterval > 0 {
|
|
opts = append(opts, restate.WithInitialRetryInterval(policy.InitialInterval))
|
|
}
|
|
return d.run(name, fn, opts...)
|
|
}
|