Timeouts and retries
A Retry Policy works in cooperation with the timeouts to provide fine controls to optimize the execution experience.
In Temporal, you could define retry policies for both Activity execution and Workflow execution.
Refer to Temporal documentation for more details regarding retries.
Activity retriesβ
Let's start with some basic imports that will be required for the whole demonstration:
import zio._
import zio.temporal._
import zio.temporal.worker._
import zio.temporal.workflow._
import zio.temporal.activity._
import java.util.UUID
Consider following simple activity and workflow definitions:
@activityInterface
trait BookingActivity {
def bookFlight(name: String, surname: String, flightNumber: String): UUID /*Booking ID*/
def purchaseFlight(bookingId: UUID, cardId: UUID): UUID /*Booking ID*/
}
@workflowInterface
trait BookingWorkflow {
@workflowMethod
def bookFlight(name: String, surname: String, flightNumber: String, cardId: UUID): UUID /*Booking ID*/
}
When declaring activities inside the workflow implementation, it's possible to provide custom timeouts and retry policies.
They are provided using ZRetryOptions
:
val retryOptions = ZRetryOptions.default
.withMaximumAttempts(3)
.withInitialInterval(300.millis)
.withMaximumAttempts(5)
.withBackoffCoefficient(1.2)
.withDoNotRetry(nameOf[IllegalArgumentException])
// retryOptions: ZRetryOptions = ZRetryOptions(
// maximumAttempts = Some(value = 5),
// initialInterval = Some(value = PT0.3S),
// backoffCoefficient = Some(value = 1.2),
// maximumInterval = None,
// doNotRetry = ArraySeq("java.lang.IllegalArgumentException"),
// javaOptionsCustomization = zio.temporal.ZRetryOptions$$$Lambda$9180/0x00007fea09ad2d08@28193ff3
// )
Important notes:
withStartToCloseTimeout
allows to specify the maximum duration of a single Activity Task ExecutionwithRetryOptions
allows to specify the retry policy for an activity executionwithMaximumAttempts
limits the number of retrieswithInitialInterval
,withMaximumAttempts
andwithBackoffCoefficient
adds a backoffwithDoNotRetry
allows to specify what errors must not be retries. A helpernameOf
method is used to get the full type name of the provided Exception
You can then specify retry options into ZActivityOptions
when creating the Activity Stub:
class BookingWorkflowImpl extends BookingWorkflow {
private val bookingActivity: ZActivityStub.Of[BookingActivity] =
ZWorkflow.newActivityStub[BookingActivity](
ZActivityOptions
.withStartToCloseTimeout(10.seconds)
.withRetryOptions(retryOptions)
)
override def bookFlight(name: String, surname: String, flightNumber: String, cardId: UUID): UUID =
???
}
Workflow retriesβ
Adding retry policies for workflows is pretty the same as for activities:
ZIO.serviceWithZIO[ZWorkflowClient] { workflowClient =>
workflowClient.newWorkflowStub[BookingWorkflow](
ZWorkflowOptions
.withWorkflowId("<ANY ID>")
.withTaskQueue("booking")
.withWorkflowExecutionTimeout(5.minutes)
.withWorkflowRunTimeout(10.seconds)
.withRetryOptions(
ZRetryOptions.default.withMaximumAttempts(5)
)
)
}
Important notes:
withWorkflowExecutionTimeout
allows to specify the maximum time that a Workflow Execution could be in progress, including retries andContinue as New
(more details here)withWorkflowRunTimeout
allows to specify the maximum run time of a single Workflow runwithRetryOptions
allows to specify the retry policy in the same way as for activities