Skip to content

Latest commit

 

History

History
571 lines (430 loc) · 13.8 KB

File metadata and controls

571 lines (430 loc) · 13.8 KB

Workflow lifecycle

Below we follow a typical sequence of events in the execution of the following very simple workflow pseudocode:

function myWorkflow() {
  result = callActivity(myActivity);
  return result;
}


Note that below, "Initialize history", "Append event to history", or "Persist Mutable State and history tasks", all refer to durable writes to the persistence layer.


  1. The User Application sends a StartWorkflowExecution request
    • Workflow History is initialized with [WorkflowExecutionStarted, WorkflowTaskScheduled]
    • A Workflow Task is added in the Matching service
sequenceDiagram
User Application->>Frontend: StartWorkflowExecution
Frontend->> History: StartWorkflowExecution
History ->> Persistence: CreateWorkflowExecution
note over Persistence: Initialize History:<br>[WorkflowExecutionStarted, WorkflowTaskScheduled]<br>persist MutableState and Transfer Task
Persistence ->> History: Create Succeed
History->>Frontend: Start Succeed
Frontend->>User Application: Start Succeed
loop QueueProcessor
    History->>Persistence: GetHistoryTasks
		History->>History: ProcessTask
		History->>Matching: AddWorkflowTask<br>
end
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Scheduled"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("WorkflowTask")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB
      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



  1. A Worker dequeues and processes the Workflow Task
    • It advances the workflow execution, and becomes blocked on the Activity call.
sequenceDiagram
Worker->>Frontend: PollWorkflowTask
Frontend->>Matching: PollWorkflowTask
History->>Matching: AddWorkflowTask (step 1 above)
Matching->>History: RecordWorkflowTaskStarted
History->>Persistence: UpdateWorkflowExecution
note over Persistence: append History Event: WorkflowTaskStarted<br>update Mutable State & add Timer Task (workflow task timeout)
Persistence->>History: Update Succeed
History->>Matching: Record Succeed
Matching->>Frontend: WorkflowTask
Frontend->>Persistence: GetHistoryEvents
Persistence->>Frontend: History Events
Frontend->>Worker: WorkflowTask
Worker->>Worker: Advance workflow
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Started"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("&nbsp")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Workflow Task Timeout") ~~~
         timer2("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



  1. The workflow launches an activity, causing the Worker to send a ScheduleActivityTask command back to the Frontend
    • An Activity task is added in the Matching service.
sequenceDiagram
Worker ->> Frontend: RespondWorkflowTaskCompleted<br>[ScheduleActivityTask]
Frontend->> History: RespondWorkflowTaskCompleted<br>[ScheduleActivityTask]
History ->> Persistence: UpdateWorkflowExecution
note over Persistence: append History Events: WorkflowTaskCompleted, ActivityTaskScheduled<br>update MutableState and add Transfer Task
Persistence ->> History: Update Succeed
History->>Frontend: Respond Succeed
Frontend->>Worker: Respond Succeed
loop QueueProcessor
    History->>Persistence: GetHistoryTasks
		History->>History: ProcessTask
		History->>Matching: AddActivityTask
end
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Empty"] ~~~
         ms2["Activity Task: Scheduled"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("Activity Task")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Workflow Task Timeout") ~~~
         timer2("Activity Task Timeout") ~~~
         timer3("Workflow Timeout")
      end

      ms ~~~ transferQ  ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted] ~~~
      e4[WorkflowTaskCompleted] ~~~
      e5[ActivityTaskScheduled]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



4. A Worker dequeues the Activity task and executes the activity

sequenceDiagram
Worker->>Frontend: PollActivityTask
Frontend->>Matching: PollActivityTask
History->>Matching: AddActivityTask (step 3 above)
Matching->>History: RecordActivityStarted
History->>Persistence: UpdateWorkflowExecution
note over Persistence: append History Event: ActivityTaskStarted<br>update Mutable State, add Timer Task (activity task timeout)
Persistence->>History: Update succeed
History->>Matching: Record Succeed
Matching->>Frontend: ActivityTask
Frontend->>Worker: ActivityTask
Worker->>Worker: Execute activity
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Empty"] ~~~
         ms2["Activity Task: Started"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("&nbsp")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Activity Task Timeout") ~~~
         timer2("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      classDef dottedBoxStyle stroke-dasharray: 5 5;
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted] ~~~
      e4[WorkflowTaskCompleted] ~~~
      e5[ActivityTaskScheduled] ~~~
      e6[ActivityTaskStarted]:::dottedBoxStyle
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



  1. Once the activity is completed, the Worker running the Activity sends RespondActivityTaskCompleted, containing the activity result
    • A Workflow Task is added in the Matching service
sequenceDiagram
Worker->>Frontend: RespondActivityTaskCompleted
Frontend->>History: RespondActivityTaskCompleted
History->>Persistence: UpdateWorkflowExecution
note over Persistence: append History Events:<br>ActivityTaskCompleted  (w/ activity result), WorkflowTaskScheduled<br>update Mutable State & add Transfer Task
Persistence->>History: Update Succeed
History->>Frontend: Respond Succeed
Frontend->>Worker: Respond Succeed
loop QueueProcessor
    History->>Persistence: GetHistoryTasks
		History->>History: ProcessTask
		History->>Matching: AddWorkflowTask
end
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Empty"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("Workflow Task")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Workflow Task Timeout") ~~~
         timer2("Activity Task Timeout") ~~~
         timer3("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted] ~~~
      e4[WorkflowTaskCompleted] ~~~
      e5[ActivityTaskScheduled] ~~~
      e6[ActivityTaskStarted] ~~~
      e7[ActivityTaskCompleted] ~~~
      e8[WorkflowTaskScheduled]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



  1. The Worker dequeues the Workflow Task
    • It advances the workflow, and finds that it has reached its end.

<Same sequence diagram as step 2 above>




  1. The Worker sends RespondWorkflowTaskCompleted, containing a CompleteWorkflowExecution command
sequenceDiagram
Worker->>Frontend: RespondWorkflowTaskCompleted<br>[CompleteWorkflowExecution]
Frontend->>History: RespondWorkflowTaskCompleted<br>[CompleteWorkflowExecution]
History->>Persistence: UpdateWorkflowExecution
note over Persistence: append HistoryEvents: WorkflowTaskCompleted, WorkflowExecutionCompleted<br>update Mutable State & add tasks (visibility, tiered storage, retention etc)
Persistence->>History: Update Succeed
History->>Frontend: Respond Succeed
Frontend->>Worker: Respond Succeed
loop QueueProcessor
    History->>Persistence: GetHistoryTasks
		History->>History: ProcessTask (Update visibility, Upload to S3, Delete data etc)
end
Loading
---
config:
  layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Empty"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("&nbsp")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Workflow Task Timeout") ~~~
         timer2("Activity Task Timeout") ~~~
         timer3("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted] ~~~
      e4[WorkflowTaskCompleted] ~~~
      e5[ActivityTaskScheduled] ~~~
      e6[ActivityTaskStarted] ~~~
      e7[ActivityTaskCompleted] ~~~
      e8[WorkflowTaskScheduled] ~~~
      e9[WorkflowTaskStarted] ~~~
      e10[WorkflowTaskCompleted] ~~~
      e11[WorkflowExecutionCompleted]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints



Alternatively, the Activity may fail and be retried:

sequenceDiagram
Worker->>Frontend: RespondActivityFailed
Frontend->>History: RespondActivityFailed
History->>Persistence: UpdateWorkflowExecution
note over Persistence: Append History Events: ActivityTaskFailed, ActivityTaskScheduled<br>update MutableState & add Timer Task (activity timout)
Persistence->>History: Update Succeed
History->>Frontend: Respond Succeed
Frontend->>Worker: Respond Succeed
loop QueueProcessor
    History->>Persistence: GetHistoryTasks
		History->>History: ProcessTask
		History->>Matching: AddActivityTask
end
Loading
---
config:
   layout: elk
---
flowchart LR
   subgraph left["&nbsp"]
      direction TB

      subgraph ms[Mutable State]
         direction TB

         ms1["Workflow Task: Empty"] ~~~
         ms2["Activity Task: Scheduled, Attempt 2"]
      end

      subgraph transferQ[Transfer Queue]
         direction LR

         transfer1("&nbsp")
      end

      subgraph timerQ[Timer Queue]
         direction LR

         timer1("Activity Retry") ~~~
         timer2("Workflow Timeout")
      end

      ms ~~~ transferQ ~~~ timerQ
   end

   subgraph history[Workflow History]
      direction TB

      e1[WorkflowExecutionStarted] ~~~
      e2[WorkflowTaskScheduled] ~~~
      e3[WorkflowTaskStarted] ~~~
      e4[WorkflowTaskCompleted] ~~~
      e5[ActivityTaskScheduled]
   end

   left ~~~ history

   style left fill:transparent,stroke:transparent
Loading
Code entrypoints