My use case is , for different errors received after the execution of activites i want to have different kind of retry policy .
For example if i receive a error as null then i should retry 5 times but if i receive an error as emptyString i should retry 10 times .
how to achieve this in temporal ?
I have searched a lot but is not able to find the solution please help
This is not yet directly supported.
A workaround is to retry one of the errors from the workflow directly.
Thankyou maxim for your quick reply .
Can you please elaborate or give an example to retry one of the errors from the workflow directly.
Hey Nikhil,
Here is a basic example that may give you some ideas. Let me if you have any question.
type ErrorDetails struct {
Code string
}
// The workflow adapt activities' retry behaviour based on the custom error details returned
func Workflow(ctx workflow.Context, name string) (string, error) {
ao := workflow.ActivityOptions{
ScheduleToCloseTimeout: 10 * time.Second,
RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 1},
}
ctx = workflow.WithActivityOptions(ctx, ao)
logger := workflow.GetLogger(ctx)
logger.Info("HelloWorld workflow started", "name", name)
var result string
attempt := 1
maxAttempts := 3
interval := 1 * time.Second
for attempt < maxAttempts {
fmt.Printf("attempt: %d maxAttempts: %d\n", attempt, maxAttempts)
err := workflow.ExecuteActivity(ctx, Activity, name).Get(ctx, &result)
if err != nil {
// Unwrap and get error details
var applicationError *temporal.ApplicationError
var details ErrorDetails
if errors.As(errors.Unwrap(err), &applicationError) {
applicationError.Details(&details)
fmt.Printf("Application Error Details: %+v\n", details)
}
// Sleep according to error code
if details.Code == "10001" {
interval = 5 * time.Second
maxAttempts = 10
}
workflow.Sleep(ctx, interval)
attempt++
} else {
break
}
}
logger.Info("HelloWorld workflow completed.", "result", result)
return result, nil
}
func Activity(ctx context.Context, name string) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("Activity", "name", name)
if len(name) < 10 {
// return ApplicationError with custom details, e.g. error code
return "", temporal.NewApplicationError("Name is invalid", "InvalidName", ErrorDetails{"10001"})
}
return "Hello " + name + "!", nil
}
[quote=“tao, post:4, topic:8335”]
s.As(errors.Unwrap(err), &applicationError) {
applicationError.Details(&details)
fmt.Printf("Application Error Details: %+v
Thank you @taonic for your quick and detailed reply but i think this does not clarify my use case . i want the retry policy to behave similar to AWS step function retry policy , where when a specific kind of error let say error = ERR occurs at 5th retry and then error = ERRRR occurs and after some retries error = ERR occurs again then i want to start from the attempt = 6 .
can i achieve this in temporal , I am trying to figure this out can you help me with this . @maxim
If you implement retries inside the workflow, you have the complete control over them. So you can implement the logic you described.
Would you describe the actual business need for such a retry policy?
@maxim we want to shift from aws step function to temporal .
Basically we want to have this retry policy when a user is placing an order .
Our order system is a little complex and we want to handle multiple errors with multiple retry policies.
I see. Unfortunately, this feature is not yet supported.
is the downside with this approach that you would see an all the retries in the execution history and potentially your history can get flooded?
Yes, the number of retries is limited by the history size. Or, the workflow must periodically call continue as new to keep the history size in check.