Skip to content

v2.8.0

Compare
Choose a tag to compare
@roxblnfk roxblnfk released this 07 Mar 18:56
· 337 commits to master since this release
v2.8.0
41c9c3b

What's Changed

  • Expose Workflow Updates by @roxblnfk in #398
    Sample
  • Add Carbon v3 and remove unnecessary packages by @devvitalii in #404
    Now SDK is compatible with Symfony 7
  • A few life quality improvements by @roxblnfk in #405
    • Make exception messages shorter and more elegant: hide internal stack trace and deduplicate the error reason
    • Throw an exception with clear message if Client is used without gRPC extension; add ext-grpc into suggested packages

Warning

RoadRunner >=2023.3.12 is required

How to develop with Updates

An Update is an operation that can mutate the state of a Workflow Execution and return a response.

Note

To enable the Workflow Update feature, you have to set the frontend.enableUpdateWorkflowExecution Temporal option to true.

How to define Updates

An Update handler has a name, arguments, response, and an optional validator.

  • The name, also called an Update type, is a string.
  • The arguments and response must be serializable.

The #[UpdateMethod] attribute indicates that the method is used to handle and respond to update requests.

#[UpdateMethod]
public function myUpdate(string $signalName);

How to handle Updates in a Workflow

Workflows listen for Update by the update's name.

The handler method can accept multiple serializable input parameters, but it's recommended using only a single parameter.
The function can return a serializable value or void.

#[WorkflowInterface]
interface FileProcessingWorkflow {
    #[WorkflowMethod]
    public function processFile(Arguments $args);

    #[UpdateMethod]
    public function pauseProcessing(): void;
}

Update handlers, unlike Query handlers, can change Workflow state.

The Updates type defaults to the name of the method. To overwrite this default naming and assign a custom Update type, use the #[UpdateMethod] attribute with the name parameter.

#[WorkflowInterface]
interface FileProcessingWorkflow {
    #[WorkflowMethod]
    public function processFile(Arguments $args);

    #[UpdateMethod(name: "pause")]
    public function pauseProcessing();
}

How to validate an Update in a Workflow

Validate certain aspects of the data sent to the Workflow using an Update Validator method. For instance, a counter Workflow might never want to accept a non-positive number. Use the #[UpdateValidatorMethod] attribute and set name to the name of your Update handler. Your Update Validator should accept the same input parameters as your Update Handler and return void.

#[WorkflowInterface]
interface GreetingWorkflow {
    #[WorkflowMethod]
    public function getGreetings(): array;

    #[UpdateMethod]
    public function addGreeting(string $name): int;

    #[UpdateValidatorMethod(forUpdate: "addGreeting")]
    public function addGreetingValidator(string $name): void;
}

How to send an Update from a Client

To send an Update to a Workflow Execution from a Client, call the Update method, annotated with #[UpdateMethod] in the Workflow interface, from the Client code.

In the following Client code example, start the Workflow getGreetings and call the Update method addGreeting that is handled in the Workflow.

/** @var \Temporal\Client\WorkflowClientInterface $client */

// Create a typed Workflow stub for GreetingsWorkflow
$workflow = $client->newWorkflowStub(GreetingWorkflow::class, $workflowOptions);

// Start the Workflow
$run = $client->start($workflow);

// Send an update to the Workflow. addGreeting returns
// the number of greetings our workflow has received.
$workflow->addGreeting("World");

Async accept

Note

To enable the async Workflow Update feature, you have to set the frontend.enableUpdateWorkflowExecutionAsyncAccepted Temporal option to true.

In Workflow Update methods, all Workflow features are available, such as executing Activities and child Workflows, and waiting on timers/conditions.
In cases where it's known that the update will take a long time to execute, or you are not interested in the outcome of its execution, you can use the stub method startUpdate and move on immediately after receiving the validation result.

/** @var \Temporal\Client\WorkflowClientInterface $client */
use Ramsey\Uuid\UuidInterface;
use Temporal\Client\Update\UpdateOptions;
use Temporal\Client\Update\WaitPolicy;
use Temporal\Client\Update\LifecycleStage;

// Create a typed Workflow stub for GreetingsWorkflow
$stub = $client->newUntypedWorkflowStub('GreetingWorkflow', $workflowOptions);

// Start the Workflow
$run = $client->start($stub);

// Send an update to the Workflow. UpdateHandle returns
$handle = $stub->startUpdate('addGreeting', 'World');

// Use the UpdateHandle to get the update result with timeout 2.5 seconds
$result = $handle->getResult(timeout: 2.5);

// You can get more control using UpdateOptions
$resultUuid = $stub->startUpdate(
    UpdateOptions::new('storeGreetings')
        ->withWaitPolicy(WaitPolicy::new()->withLifecycleStage(LifecycleStage::StageCompleted))
        ->withResultType(UuidInterface::class)
 )->getResult();

New Contributors

Full Changelog: v2.7.6...v2.8.0