An Activity is a manifestation of a particular task in the business logic.
Activities are defined as methods of a plain PHP interface annotated with
#[ActivityInterface] (you can use PHP 8 attributes
in PHP7 as well).
Each method defines a single Activity type. A single Workflow can use more than one Activity interface and call more that one Activity method from the same interface.
The only requirement is that Activity method arguments and return values are serializable to a byte array using the provided DataConverter interface. The default implementation uses a JSON serializer, but an alternative implementation can be easily configured.
Following is an example of an interface that defines four Activities:
We recommend to use a single value type argument for Activity methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change.
#[ActivityMethod] annotation can be used to override a default Activity name.
ActivityInterface annotation will allow you to define your own prefix for all activity names (by
default it's empty).
Activity implementation is an implementation of an Activity interface. A single instance of the Activities implementation is shared across multiple simultaneous Activity invocations. Therefore, the Activity implementation code must be stateless.
The values passed to Activities through invocation parameters or returned through a result value are recorded in the execution history. The entire execution history is transferred from the Temporal service to Workflow workers when a Workflow state needs to recover. A large execution history can thus adversely impact the performance of your Workflow. Therefore, be mindful of the amount of data you transfer via Activity invocation parameters or return values.
Otherwise, no additional limitations exist on Activity implementations.
The Activity class provides static getters to access information about the Workflow that invoked it. Note that this information is stored in a thread local variable. Therefore, calls to Activity accessors succeed only in the process that invoked the Activity function.
Some Activities are long-running.
To react to a crash quickly, use the Heartbeat mechanism,
Activity::heartbeat(), which lets the Temporal Server know that the Activity is still alive.
This acts as a periodic checkpoint mechanism for the progress of an Activity.
You can piggyback
details on an Activity Heartbeat.
If an Activity times out, the last value of
details is included in the
TimeoutFailure delivered to a Workflow.
Then the Workflow can pass the details to the next Activity invocation.
Additionally, you can access the details from within an Activity via
When an Activity is retried after a failure
getHeartbeatDetails enables you to get the value from the last successful Heartbeat.
Workflow::newActivityStub returns a client-side stub an implements an Activity interface.
The client-side stub can be used within the Workflow code.
It takes the Activity's type and
ActivityOptions as arguments.
yield) a method on this interface invokes an Activity that implements this method.
An Activity invocation synchronously blocks until the Activity completes, fails, or times out.
Even if Activity execution takes a few months, the Workflow code still sees it as a single synchronous invocation.
It doesn't matter what happens to the processes that host the Workflow.
The business logic code just sees a single method call.
If different Activities need different options, like timeouts or a task queue, multiple client-side stubs can be created with different options.
Sometimes Workflows need to perform certain operations in parallel.
Invoking activity stub without the use of
yield will return the activity result promise which can be resolved at later moment.
yield on promise blocks until a result is available.
Activity promise also exposes
thenmethod to construct promise chains. Read more about Promises here.
Alternatively you can explicitly wrap your code (including
yield constucts) using
Workflow::async which will execute nested code in parallel with main workflow code.
yeild on Promise returned by
Workflow::async to merge execution result back to primary workflow method.
There are certain scenarios when moving on from an Activity upon completion of its function is not possible or desirable. For example, you might have an application that requires user input in order to complete the Activity. You could implement the Activity with a polling mechanism, but a simpler and less resource-intensive implementation is to asynchronously complete a Temporal Activity.
There are two parts to implementing an asynchronously completed Activity:
- The Activity provides the information necessary for completion from an external system and notifies the Temporal service that it is waiting for that outside callback.
- The external service calls the Temporal service to complete the Activity.
The following example demonstrates the first part:
The following code demonstrates how to complete the Activity successfully using
To fail the Activity, you would do the following: