DEV Community

fjavierm
fjavierm

Posted on • Originally published at binarycoders.wordpress.com on

Implementing Durable Execution

Reading and writing about topics we are learning is great, but there is nothing better than some hands-on approach, as such, let’s build a couple implementations of the pizza example described in yesterday’s article.

The first implementation is using the Temporal SDK to allow us to get more familiar with the details of Durable Execution, and consolidate a bit better what we are reviewing. In the second example, we will try to implement our incredible tiny very reduced version of the whole thing.

First example: Using the Temporal SDK

The full implementation of this example can be found in GitHub in the repository pizza-durable-execution. The code and the repository have been heavily documented, which what I think should be enough information to understand the example. But some quick overview is:

  • PizzaActivities: Activities are the side-effecting operations in Durable Execution.
  • PizzaActivitiesImpl: Concrete implementation of the activities.
  • PizzaOrderStarter: Starts a new pizza order workflow instance.
  • PizzaOrderWorkflow: The workflow interface defines the durable process contract.
  • PizzaOrderWorkflowImpl: The durable workflow implementation with pure orchestration, zero side effects.
  • PizzaWorker: The Worker process.

Once we run it, we should see something like:

The pizza worker


=================================================
 Pizza Worker started. Polling: pizza-order-queue
 Now run PizzaOrderStarter to place an order.
=================================================
10:50:09.222 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Starting pizza order for: margherita
10:50:09.247 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Taking order for pizza: margherita
10:50:09.247 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Order created → ORDER-MARGHERITA
10:50:09.256 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Order accepted → ORDER-MARGHERITA
10:50:09.259 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Kitchen preparing pizza for order: ORDER-MARGHERITA
10:50:09.260 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Pizza ready → PIZZA-ORDER-MARGHERITA
10:50:09.262 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Pizza prepared → PIZZA-ORDER-MARGHERITA
10:50:09.262 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Waiting 5 seconds for delivery window (durable timer)...
10:50:14.291 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Dispatching delivery for: PIZZA-ORDER-MARGHERITA
10:50:14.292 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Delivery confirmed → DELIVERED-PIZZA-ORDER-MARGHERITA
10:50:14.297 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Pizza delivered → DELIVERED-PIZZA-ORDER-MARGHERITA
10:50:14.301 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Sending receipt for delivery: DELIVERED-PIZZA-ORDER-MARGHERITA
10:50:14.301 [Activity Executor taskQueue="pizza-order-queue", namespace="default": 1] INFO d.b.pizza.PizzaActivitiesImpl - [ACTIVITY] Receipt sent. Workflow complete.
10:50:14.305 [workflow-method-pizza-order-margherita-001-019e3031-78f6-7222-9627-e9f11a3367de] INFO d.b.pizza.PizzaOrderWorkflowImpl - [WORKFLOW] Workflow complete for order: ORDER-MARGHERITA
Enter fullscreen mode Exit fullscreen mode

The pizza order starter


=================================================
 Starting pizza order workflow...
=================================================
=================================================
 Workflow finished. Pizza delivered!
=================================================
Enter fullscreen mode Exit fullscreen mode

We can check the Temporal UI, and see our execution:

All necessary instructions for running it are present in the README of the project.

Second example: Implementing our own

The full implementation of this example can be found in GitHub in the repository mini-durable-execution-platform. The code and the repository have been heavily documented, which what I think should be enough information to understand the example. But some quick overview is:

  • MiniTemporal: Single class containing the whole project.
  • PizzaWorkflow: Durable orchestration of a pizza order.
  • WorkflowContext: The replay engine: the heart of durable execution.

Once we run it, we should see something like:

The pizza worker


worker started
[EXECUTING] prepare-dough
[EXECUTING] add-toppings
[EXECUTING] bake-pizza
[EXECUTING] prepare-dough
[EXECUTING] add-toppings
[EXECUTING] bake-pizza
[EXECUTING] deliver-pizza
Enter fullscreen mode Exit fullscreen mode

The pizza order starter


[WAITING] prepare-dough
[WAITING] add-toppings
[WAITING] bake-pizza

=== JVM CRASH SIMULATED ===

workflowId=d2a8dc13-e428-4bc2-996e-c721d71592f7
...

[WAITING] prepare-dough
[WAITING] add-toppings
[WAITING] bake-pizza
[WAITING] deliver-pizza

===== ORDER COMPLETED =====
dough=dough-ready
toppings=toppings-added
baked=pizza-baked
delivery=pizza-delivered

=== WORKFLOW COMPLETED ===
Enter fullscreen mode Exit fullscreen mode

All necessary instructions for running it are present in the README of the project.

Top comments (0)