Skip to content

Replay Events

Regunath B edited this page Dec 21, 2021 · 1 revision

Feature Overview

This feature provides the capability to re-execute a specific completed state in the workflow without having to restart the workflow all-over again by initiating a new workflow instance.

To be able to re-execute it’s completed state, it is possible to attach execution-version to the states and events wherein each execution of a state occurs with a new execution-version, such that execution-version keeps track/audit of multiple executions of a state in a workflow.

On similar lines of ExternalEvent, a ReplayEvent type instance may be used by the user to trigger re-execution along-with all the states in its traversal path. This is initiated using the Flux client library, typically within the end user application that uses Flux.

Flux replay example

Consider a workflow shown in figure above, the use-case in this workflow can be that if a state “Add” is getting errored/sidelined then user may want to re-execute workflow from any intermediate previously completed state (“Subtract” in this case) whereas the initial state is “Random” in this case. Though to Flux-runtime, it doesn’t matter what triggered the replay-event, whether it’s one or more errored/sidelined state(s) in the workflow or something else.

Every time you send a request to re-execute a workflow instead of creating a new instance of the workflow(with the subset of tasks) the ‘executionVersion’ is used to track the tasks that are being executed again. In this example the tasks Subtract, Modulus, Left Shift, Right Shift and Add gets re-executed. By default the first execution of workflow is assigned the execution version 0(zero). And every time you re-execute the version number is incremented.

Usage

During the workflow creation the user may mark a task as replayable by setting the flag isReplayable in @Task annotation. This task listens to the events identified by the annotation @ReplayEvent as shown in the example below. The replay event is treated as an optional event (means State execution doesn’t waits for ReplayEvent to trigger) during the dependency evaluation for the task execution. So, when @ReplayEvent is explicitly triggered via postReplayEvent API, user can choose to read ReplayEvent Data in their @Task code.

Recommendation : In order to use @ReplayEvent data in the @Task code, add a NULL value check for it’s trigger in @Task method. Otherwise, use @ReplayEvent only as a trigger hook to re-execute workflows from that Replayable State.

Flux replay event parameters

API payload for replaying events

POST: http://<FluxEndpoint>/api/machines/<StateMachineId>/context/replayevent

Payload Sample:
{
"name" : <AsUsedInDeclaration>, 
"type" : "<FQNOfEventClass>",
"data" : "{\"value\":\"5\"}",
"eventSource" : "<EventSource>" 
}

Recommended Do's & Don'ts

  • The task which is replayable has to be in completed state in order to re-execute
  • It is not possible to have more than 1 task dependent on the same replay event.
  • It is not possible to have more than 1 replay event on the same task.
  • Replay events may be sent multiple times as identified by the flag replayRetries in the task declaration. (finite limit of 5). Attempting to send the event more than the identified number of times will result in Flux rejecting the event and return an error.
  • Flux supports doing a reset of the retry count using the reset api (shown below). In this case Flux will delete all the previous entries and start from zero again.
PUT : http://<FluxEndpoint>/api/machines/<stateMachineId>/<stateId>/resetreplayretries

Flux also supports updating the existing internal event data being used by the replayable state. To update the data, at least one of the dependent states that are dependent on this event should be replayable. API is as follows:

POST: http://<FluxEndpoint>/api/machines/<stateMachineId>/context/internaleventupdate
{
"name" : <AsUsedInDeclaration>, 
"type" : "<FQNOfEventClass>",
"data" : "{\"value\":\"5\"}",
"eventSource" : "<EventSource>" 
}

Clone this wiki locally