diff --git a/solutions/day1/part-5.1-end/temporalpractice/bakery/CookieWorkflowTest.java b/solutions/day1/part-5.1-end/temporalpractice/bakery/CookieWorkflowTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5de07e2230bdaaadcdf0e4aa26d72076ded11bca
--- /dev/null
+++ b/solutions/day1/part-5.1-end/temporalpractice/bakery/CookieWorkflowTest.java
@@ -0,0 +1,74 @@
+package io.takima.temporalpractice.bakery.cookie;
+
+import io.takima.temporalpractice.bakery.bake.BakeServiceImpl;
+import io.takima.temporalpractice.bakery.batter.BatterServiceImpl;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflowImpl;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.client.WorkflowClient;
+import io.temporal.testing.TestWorkflowEnvironment;
+import io.temporal.testing.TestWorkflowExtension;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import java.time.Duration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CookieWorkflowTest {
+
+    @RegisterExtension
+    public static final TestWorkflowExtension testWorkflowExtension =
+            TestWorkflowExtension.newBuilder()
+                    .registerWorkflowImplementationTypes(KitchenWorkflowImpl.class)
+                    .setDoNotStart(true)
+                    .build();
+
+    @BeforeEach
+    void init(TestWorkflowEnvironment testEnv){
+        testEnv.newWorker(TemporalQueues.BAKE)
+                .registerActivitiesImplementations(new BakeServiceImpl());
+        testEnv.newWorker(TemporalQueues.BATTER)
+                .registerActivitiesImplementations(new BatterServiceImpl());
+        testEnv.start();
+    }
+
+    @Test
+    public void shouldMakeCookies(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        // get the env starting time
+        var startTime = testEnv.currentTimeMillis();
+
+        // Start the workflow asynchronously
+        var request = KitchenDtos.CookieOrderRequest.random();
+        WorkflowClient.start(workflow::makeCookies, request);
+
+        var status = workflow.getStatus();
+        assertThat(status.ovenReady()).isFalse();
+        assertThat(status.request()).isEqualTo(request);
+
+        workflow.ovenReady();
+        status = workflow.getStatus();
+        assertThat(status.ovenReady()).isTrue();
+
+        // Get the workflow result
+        var result = workflow.makeCookies(request);
+
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies())
+                .hasSize(request.quantity())
+                .allSatisfy(cookie -> {
+                    assertThat(cookie.bakingPreference()).isEqualTo(request.bakingPreference());
+                    assertThat(cookie.topping()).isEqualTo(request.topping());
+                });
+
+        var duration = Duration.ofMillis(testEnv.currentTimeMillis() - startTime);
+        assertThat(duration).isGreaterThan(Duration.ofSeconds(30));
+    }
+}
diff --git a/solutions/day1/part-5.2-end/temporalpractice/bakery/CookieWorkflowTest.java b/solutions/day1/part-5.2-end/temporalpractice/bakery/CookieWorkflowTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d37dd41ee2d9ef0d672b8adca22310fd99604d7
--- /dev/null
+++ b/solutions/day1/part-5.2-end/temporalpractice/bakery/CookieWorkflowTest.java
@@ -0,0 +1,100 @@
+package io.takima.temporalpractice.bakery.cookie;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflowImpl;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.client.WorkflowClient;
+import io.temporal.testing.TestWorkflowEnvironment;
+import io.temporal.testing.TestWorkflowExtension;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.time.Duration;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class CookieWorkflowTest {
+
+    @Mock(withoutAnnotations = true)
+    private BakeService bakeService;
+
+    @Mock(withoutAnnotations = true)
+    private BatterService batterService;
+
+
+    @RegisterExtension
+    public static final TestWorkflowExtension testWorkflowExtension =
+            TestWorkflowExtension.newBuilder()
+                    .registerWorkflowImplementationTypes(KitchenWorkflowImpl.class)
+                    .setDoNotStart(true)
+                    .build();
+
+    @BeforeEach
+    void init(TestWorkflowEnvironment testEnv) {
+        testEnv.newWorker(TemporalQueues.BAKE)
+                .registerActivitiesImplementations(bakeService);
+        testEnv.newWorker(TemporalQueues.BATTER)
+                .registerActivitiesImplementations(batterService);
+        testEnv.start();
+    }
+
+    KitchenDtos.CookieOrderRequest request = KitchenDtos.CookieOrderRequest.random();
+    BatterCreationRequest batterCreationRequest = new BatterCreationRequest(request.orderId(), request.topping(), request.quantity());
+    BatterCreationResult batterCreationResult = new BatterCreationResult(new Batter(request.topping(), 30 * request.quantity(), request.quantity()));
+    BakeRequest bakeRequest = new BakeRequest(request.orderId(), batterCreationResult.batter(), request.bakingPreference());
+    BakeResult bakeResult = new BakeResult(List.of(new KitchenDtos.Cookie(request.bakingPreference(), request.topping())));
+
+    @Test
+    public void shouldMakeCookies(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        // get the env starting time
+        var startTime = testEnv.currentTimeMillis();
+
+        // Start the workflow asynchronously
+        WorkflowClient.start(workflow::makeCookies, request);
+        when(batterService.prepareBatter(batterCreationRequest))
+                .thenReturn(batterCreationResult);
+        // Make sure we dont bake before the oven is ready
+        verifyNoInteractions(bakeService);
+
+        var status = workflow.getStatus();
+        assertThat(status.ovenReady()).isFalse();
+        assertThat(status.request()).isEqualTo(request);
+
+        workflow.ovenReady();
+        status = workflow.getStatus();
+        assertThat(status.ovenReady()).isTrue();
+        when(bakeService.bake(bakeRequest)).thenReturn(bakeResult);
+
+        // Get the workflow result
+        var result = workflow.makeCookies(request);
+
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies())
+                .isEqualTo(bakeResult.cookies());
+
+        var duration = Duration.ofMillis(testEnv.currentTimeMillis() - startTime);
+        assertThat(duration).isGreaterThan(Duration.ofSeconds(30));
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ff2b24826e205b1abc28eb86c4dbcc695ee210b
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java
@@ -0,0 +1,25 @@
+package io.takima.temporalpractice.bakery;
+
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.serviceclient.WorkflowServiceStubs;
+
+public class OrderCookiesApp {
+    public static void main(String[] args) {
+        // This app simulates an order of cookies
+        // It should call the workflow which makes cookies
+        var orderRequest = CookieOrderRequest.random();
+
+        KitchenWorkflow workflow = TemporalUtils.newWorkflowStub(
+                KitchenWorkflow.class,
+                TemporalQueues.KITCHEN,
+                "kitchen-" + orderRequest.orderId()
+        );
+
+        workflow.makeCookies(orderRequest); // Start the Workflow Execution
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderManyCookies.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderManyCookies.java
new file mode 100644
index 0000000000000000000000000000000000000000..6421088ad913c656bd3133c5d715d182328f5959
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/OrderManyCookies.java
@@ -0,0 +1,70 @@
+package io.takima.temporalpractice.bakery;
+
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.api.enums.v1.ParentClosePolicy;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.workflow.*;
+import org.slf4j.Logger;
+
+import java.time.Duration;
+
+public class OrderManyCookies {
+    public static void main(String[] args) {
+        var queue = "manycookies";
+
+        TemporalUtils.newWorker(queue)
+                .registerWorkflowImplementationTypes(ManyCookiesImpl.class);
+
+        TemporalUtils.startWorkerFactory();
+
+        try {
+            ManyCookies manyCookies = TemporalUtils.CLIENT.newWorkflowStub(
+                    ManyCookies.class,
+                    WorkflowOptions.newBuilder().setWorkflowId("cookie-orderer").setTaskQueue(queue).build()
+            );
+            WorkflowClient.start(manyCookies::continuousOrders);
+        } catch (Exception e) {
+            System.out.println("Many cookies already running, skipping...");
+        }
+    }
+
+    public static class ManyCookiesImpl implements ManyCookies {
+
+        private static final Logger logger = Workflow.getLogger(ManyCookiesImpl.class);
+
+        @Override
+        public void continuousOrders() {
+
+            var options = ChildWorkflowOptions.newBuilder()
+                    .setWorkflowId("order-" + Workflow.randomUUID())
+                    .setTaskQueue(TemporalQueues.KITCHEN)
+                    .setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON)
+                    .build();
+            var kitchenWorkflow = Workflow.newChildWorkflowStub(KitchenWorkflow.class, options);
+
+            var quantity = Workflow.newRandom().nextInt(1, 5);
+            var baking = KitchenDtos.BakingPreference.values()[Workflow.newRandom().nextInt(KitchenDtos.BakingPreference.values().length)];
+            var topping = KitchenDtos.Topping.values()[Workflow.newRandom().nextInt(KitchenDtos.Topping.values().length)];
+
+            var cookiesPreferences = new KitchenDtos.CookieOrderRequest(Workflow.randomUUID().toString(), quantity, baking, topping);
+
+            logger.info("Ordering cookies\n{}", cookiesPreferences);
+            Async.function(kitchenWorkflow::makeCookies, cookiesPreferences);
+
+            Workflow.sleep(Duration.ofSeconds(10));
+            kitchenWorkflow.ovenReady();
+
+            Workflow.continueAsNew();
+        }
+    }
+
+    @WorkflowInterface
+    public interface ManyCookies {
+        @WorkflowMethod
+        void continuousOrders();
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeApp.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d1cdb1f4cbfb9d2d79510e53c2e3534ff4eafc7
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeApp.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+
+public class BakeApp {
+    public static void main(String[] args) {
+        var worker = TemporalUtils.newWorker(TemporalQueues.BAKE);
+        worker.registerActivitiesImplementations(new BakeServiceImpl());
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeService.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeService.java
new file mode 100644
index 0000000000000000000000000000000000000000..36c0d02dba3dde7a8b166e68a8e3ff9c471870d6
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeService.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface BakeService {
+    @ActivityMethod
+    BakeResult bake(BakeRequest request);
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeServiceImpl.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..22509b663a08745f19b2bb4b3fb78915c9fe50c9
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/BakeServiceImpl.java
@@ -0,0 +1,22 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Cookie;
+
+import java.util.ArrayList;
+
+public class BakeServiceImpl implements BakeService {
+  @Override
+  public BakeResult bake(BakeRequest request) {
+    System.out.println("Will bake those cookies " + request.bakingPreference());
+    var cookies = new ArrayList<Cookie>();
+    for (int i = 0; i < request.batter().targetCookieCount(); i++) {
+      // Making cookies out of batter
+      var cookie = new Cookie(request.bakingPreference(), request.batter().topping());
+      // Add it to the cookies after it is baked
+      cookies.add(cookie);
+    }
+    return new BakeResult(cookies);
+  }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeRequest.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..42701fec06fef7cac59011057af8dce46f4eba33
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeRequest.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake.dtos;
+
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.BakingPreference;
+
+public record BakeRequest(
+        String orderId,
+        Batter batter,
+        BakingPreference bakingPreference
+) {
+}
+
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeResult.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9afcf709a517afd86c44140f17877a9c061aac8
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/bake/dtos/BakeResult.java
@@ -0,0 +1,8 @@
+package io.takima.temporalpractice.bakery.bake.dtos;
+
+import java.util.List;
+
+import static io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Cookie;
+
+public record BakeResult(List<Cookie> cookies) {
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterApp.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b4bdb903208cebcca21d9fe8a357a4795f82431
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterApp.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+
+public class BatterApp {
+    public static void main(String[] args) {
+        var worker = TemporalUtils.newWorker(TemporalQueues.BATTER);
+        worker.registerActivitiesImplementations(new BatterServiceImpl());
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterService.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1353c54503494eed2c87e03165f287ca980677c0
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterService.java
@@ -0,0 +1,17 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface BatterService {
+
+    @ActivityMethod
+    BatterCreationResult prepareBatter(BatterCreationRequest request);
+
+    @ActivityMethod
+    void cleanupBatterIfNeeded(BatterCleanupRequest request);
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterServiceImpl.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..17a2e83dccc8a4bd5b1093474b2e6dae84e1bd0b
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/BatterServiceImpl.java
@@ -0,0 +1,27 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+
+public class BatterServiceImpl implements BatterService {
+
+    static final int BATTER_QTY_PER_COOKIE_IN_GRAMS = 30; // in grams
+
+    @Override
+    public BatterCreationResult prepareBatter(BatterCreationRequest request) {
+        System.out.println("Mixing flour, sugar, and love for " + request.targetCookieCount() + " cookies with topping " + request.targetTopping());
+        return new BatterCreationResult(
+                new Batter(
+                        request.targetTopping(),
+                        BATTER_QTY_PER_COOKIE_IN_GRAMS * request.targetCookieCount(),
+                        request.targetCookieCount()
+                ));
+    }
+
+    @Override
+    public void cleanupBatterIfNeeded(BatterCleanupRequest request) {
+        System.out.println("Cleaning up batter of order " + request.orderId());
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/Batter.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/Batter.java
new file mode 100644
index 0000000000000000000000000000000000000000..8608c0e5eac1ddbee9e4d7c20da2549cc9ebfb21
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/Batter.java
@@ -0,0 +1,10 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Topping;
+
+public record Batter(
+        Topping topping,
+        int quantityInGrams,
+        int targetCookieCount
+) {
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCleanupRequest.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCleanupRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..26a9ea7d09c2cacbd61c2052cbc7d87164863653
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCleanupRequest.java
@@ -0,0 +1,4 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+public record BatterCleanupRequest(String orderId) {
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationRequest.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..38cc0c1cd6279c7bee0d6662202b4bd378b31084
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationRequest.java
@@ -0,0 +1,11 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Topping;
+
+public record BatterCreationRequest(
+        String orderId,
+        Topping targetTopping,
+        int targetCookieCount
+) {
+
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationResult.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75e6ab838e3fb45fb53ab2e0870d3a33a5ad975
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/batter/dtos/BatterCreationResult.java
@@ -0,0 +1,5 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+public record BatterCreationResult(Batter batter) {
+
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenApp.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c5736750e2d894e4cb66b8c39bfb94817d61c2c
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenApp.java
@@ -0,0 +1,13 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.worker.Worker;
+
+public class KitchenApp {
+    public static void main(String[] args) {
+        Worker worker = TemporalUtils.newWorker(TemporalQueues.KITCHEN);
+        worker.registerWorkflowImplementationTypes(KitchenWorkflowImpl.class);
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflow.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflow.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca266350468651eaee9fd8a2800d14ec2dfa8632
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflow.java
@@ -0,0 +1,21 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.temporal.workflow.QueryMethod;
+import io.temporal.workflow.SignalMethod;
+import io.temporal.workflow.WorkflowInterface;
+import io.temporal.workflow.WorkflowMethod;
+
+@WorkflowInterface
+public interface KitchenWorkflow {
+    @WorkflowMethod
+    CookieOrderResult makeCookies(CookieOrderRequest request);
+
+    @SignalMethod
+    void ovenReady();
+
+    @QueryMethod
+    CookieOrderStatus getStatus();
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef842cf6404c64e9591dfdc9e136112e0e09f69f
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java
@@ -0,0 +1,72 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.takima.temporalpractice.bakery.temporal.TemporalActivityFactory;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.failure.ActivityFailure;
+import io.temporal.workflow.Saga;
+import io.temporal.workflow.Workflow;
+import org.slf4j.Logger;
+
+import java.time.Duration;
+import java.util.List;
+
+public class KitchenWorkflowImpl implements KitchenWorkflow {
+    private final BatterService batterService;
+    private final BakeService bakeService;
+    private boolean ovenReady = false;
+    private CookieOrderRequest cookieOrder;
+
+    private final Logger logger = Workflow.getLogger(KitchenWorkflowImpl.class);
+
+    private final Saga saga = new Saga(new Saga.Options.Builder().build());
+
+    public KitchenWorkflowImpl() {
+        this.batterService = TemporalActivityFactory.newActivityStub(BatterService.class, TemporalQueues.BATTER);
+        this.bakeService = TemporalActivityFactory.newActivityStub(BakeService.class, TemporalQueues.BAKE);
+    }
+
+
+    @Override
+    public CookieOrderResult makeCookies(CookieOrderRequest request) {
+        this.cookieOrder = request;
+        var timer = Workflow.newTimer(Duration.ofSeconds(30));
+
+        try {
+            saga.addCompensation(batterService::cleanupBatterIfNeeded, new BatterCleanupRequest(request.orderId()));
+
+            logger.info("Order {}: Starting to prepare {} cookies with topping {} and baking preference {}", request.orderId(), request.quantity(), request.topping(), request.bakingPreference());
+            var batterCreationResult = batterService.prepareBatter(new BatterCreationRequest(request.orderId(), request.topping(), request.quantity()));
+            var batter = batterCreationResult.batter();
+
+            Workflow.await(() -> ovenReady);
+
+            var bakeResult = bakeService.bake(new BakeRequest(request.orderId(), batter, request.bakingPreference()));
+
+            logger.info("Order {}: Your {} cookies are ready!", request.orderId(), bakeResult.cookies().size());
+
+            timer.get();
+            return new CookieOrderResult(request.orderId(), bakeResult.cookies());
+        } catch (ActivityFailure failures) {
+            saga.compensate();
+            return new CookieOrderResult(request.orderId(), List.of());
+        }
+    }
+
+    @Override
+    public void ovenReady() {
+        this.ovenReady = true;
+    }
+
+    @Override
+    public CookieOrderStatus getStatus() {
+        return new CookieOrderStatus(ovenReady, cookieOrder);
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/dtos/KitchenDtos.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/dtos/KitchenDtos.java
new file mode 100644
index 0000000000000000000000000000000000000000..f82ef2e5c2ec62f10fb03b9b817cbdb4b39962a1
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/kitchen/dtos/KitchenDtos.java
@@ -0,0 +1,62 @@
+package io.takima.temporalpractice.bakery.kitchen.dtos;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface KitchenDtos {
+    enum BakingPreference {
+        RAW,
+        SOFT,
+        COOKED,
+        BURNT;
+
+        public static BakingPreference random() {
+            return values()[(int) (Math.random() * values().length)];
+        }
+    }
+
+    enum Topping {
+        CHOCOLATE,
+        NUTS,
+        NONE;
+
+        public static Topping random() {
+            return values()[(int) (Math.random() * values().length)];
+        }
+    }
+
+    record Cookie(
+            BakingPreference bakingPreference,
+            Topping topping
+    ) {
+    }
+
+    record CookieOrderRequest(
+            String orderId,
+            int quantity,
+            BakingPreference bakingPreference,
+            Topping topping
+    ) {
+
+        public static CookieOrderRequest random() {
+            return new CookieOrderRequest(
+                    UUID.randomUUID().toString(),
+                    (int) (Math.random() * 10) + 1,
+                    BakingPreference.random(),
+                    Topping.random()
+            );
+        }
+    }
+
+    record CookieOrderResult(
+            String orderId,
+            List<Cookie> cookies
+    ) {
+    }
+
+    record CookieOrderStatus(
+            boolean ovenReady,
+            CookieOrderRequest request
+    ) {
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalActivityFactory.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalActivityFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec51a0efbc4d17dff652a241ef7d40fa16ffa92f
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalActivityFactory.java
@@ -0,0 +1,20 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+import java.time.Duration;
+
+public class TemporalActivityFactory {
+    public static <T> T newActivityStub(Class<T> workflowInterface, String queue) {
+        return Workflow.newActivityStub(
+                workflowInterface,
+                ActivityOptions.newBuilder()
+                        .setTaskQueue(queue)
+                        .setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(2).build())
+                        .setStartToCloseTimeout(Duration.ofSeconds(5))
+                        .build()
+        );
+    }
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalQueues.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalQueues.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c99053e91384d67bce35b927bd47b3ce58444b3
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalQueues.java
@@ -0,0 +1,7 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+public class TemporalQueues {
+  public static final String KITCHEN = "kitchen";
+  public static final String BATTER = "batter";
+  public static final String BAKE = "bake";
+}
diff --git a/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalUtils.java b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..101f7e67044053b8cd545983db756f27b1c5d0e8
--- /dev/null
+++ b/solutions/day2/part-1.3/main/java/io/takima/temporalpractice/bakery/temporal/TemporalUtils.java
@@ -0,0 +1,36 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.serviceclient.WorkflowServiceStubs;
+import io.temporal.worker.Worker;
+import io.temporal.worker.WorkerFactory;
+
+public class TemporalUtils {
+
+    // Represents the connection to your local cluster. For now, lets keep it simple
+    private static final WorkflowServiceStubs SERVICE_STUBS = WorkflowServiceStubs.newLocalServiceStubs();
+
+    // Your key for interacting with the Temporal world.
+    public static final WorkflowClient CLIENT = WorkflowClient.newInstance(SERVICE_STUBS);
+
+    private static final WorkerFactory FACTORY = WorkerFactory.newInstance(CLIENT);
+
+    public static Worker newWorker(String queue) {
+        return FACTORY.newWorker(queue);
+    }
+
+    public static void startWorkerFactory() {
+        FACTORY.start();
+    }
+
+    public static <T> T newWorkflowStub(Class<T> workflowInterface, String queue, String workflowId) {
+        return CLIENT.newWorkflowStub(
+                workflowInterface,
+                WorkflowOptions.newBuilder()
+                        .setTaskQueue(queue)
+                        .setWorkflowId(workflowId)
+                        .build()
+        );
+    }
+}
diff --git a/solutions/day2/part-1.3/main/resources/application.yml b/solutions/day2/part-1.3/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..13906e51785fac4557bbe7048c5c7addbc6c3fa8
--- /dev/null
+++ b/solutions/day2/part-1.3/main/resources/application.yml
@@ -0,0 +1,3 @@
+spring:
+  application:
+    name: Temporal Practice
diff --git a/solutions/day2/part-1.3/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java b/solutions/day2/part-1.3/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..748902fb2f503d578aa8992c0cc8be91c755d0ce
--- /dev/null
+++ b/solutions/day2/part-1.3/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java
@@ -0,0 +1,122 @@
+package io.takima.temporalpractice.bakery.cookie;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflowImpl;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.client.WorkflowClient;
+import io.temporal.testing.TestWorkflowEnvironment;
+import io.temporal.testing.TestWorkflowExtension;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.time.Duration;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+public class CookieWorkflowTest {
+
+    @Mock(withoutAnnotations = true)
+    private BakeService bakeService;
+
+    @Mock(withoutAnnotations = true)
+    private BatterService batterService;
+
+
+    @RegisterExtension
+    public static final TestWorkflowExtension testWorkflowExtension =
+            TestWorkflowExtension.newBuilder()
+                    .registerWorkflowImplementationTypes(KitchenWorkflowImpl.class)
+                    .setDoNotStart(true)
+                    .build();
+
+    @BeforeEach
+    void init(TestWorkflowEnvironment testEnv) {
+        testEnv.newWorker(TemporalQueues.BAKE)
+                .registerActivitiesImplementations(bakeService);
+        testEnv.newWorker(TemporalQueues.BATTER)
+                .registerActivitiesImplementations(batterService);
+        testEnv.start();
+    }
+
+    KitchenDtos.CookieOrderRequest request = KitchenDtos.CookieOrderRequest.random();
+    BatterCreationRequest batterCreationRequest = new BatterCreationRequest(request.orderId(), request.topping(), request.quantity());
+    BatterCreationResult batterCreationResult = new BatterCreationResult(new Batter(request.topping(), 30 * request.quantity(), request.quantity()));
+    BakeRequest bakeRequest = new BakeRequest(request.orderId(), batterCreationResult.batter(), request.bakingPreference());
+    BakeResult bakeResult = new BakeResult(List.of(new KitchenDtos.Cookie(request.bakingPreference(), request.topping())));
+
+    @Test
+    public void shouldCleanupBatter(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        WorkflowClient.start(workflow::makeCookies, request);
+
+        when(batterService.prepareBatter(batterCreationRequest))
+                .thenReturn(batterCreationResult);
+        workflow.ovenReady();
+        when(bakeService.bake(bakeRequest))
+                .thenThrow(new RuntimeException("I will always fail"));
+
+        var result = workflow.makeCookies(request);
+
+        verify(batterService).cleanupBatterIfNeeded(new BatterCleanupRequest(request.orderId()));
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies()).isEmpty();
+    }
+
+    @Test
+    public void shouldMakeCookies(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        // get the env starting time
+        var startTime = testEnv.currentTimeMillis();
+
+        // Start the workflow asynchronously
+        WorkflowClient.start(workflow::makeCookies, request);
+        when(batterService.prepareBatter(batterCreationRequest))
+                .thenThrow(new RuntimeException("I failed on first try"))
+                .thenReturn(batterCreationResult);
+        // Make sure we dont bake before the oven is ready
+        verifyNoInteractions(bakeService);
+
+        var status = workflow.getStatus();
+        assertThat(status.ovenReady()).isFalse();
+        assertThat(status.request()).isEqualTo(request);
+
+        workflow.ovenReady();
+        status = workflow.getStatus();
+        assertThat(status.ovenReady()).isTrue();
+        when(bakeService.bake(bakeRequest)).thenReturn(bakeResult);
+
+        // Get the workflow result
+        var result = workflow.makeCookies(request);
+
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies())
+                .isEqualTo(bakeResult.cookies());
+
+        var duration = Duration.ofMillis(testEnv.currentTimeMillis() - startTime);
+        assertThat(duration).isGreaterThan(Duration.ofSeconds(30));
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/OrderCookiesApp.java b/solutions/day2/part-2.1/bakery/OrderCookiesApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ff2b24826e205b1abc28eb86c4dbcc695ee210b
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/OrderCookiesApp.java
@@ -0,0 +1,25 @@
+package io.takima.temporalpractice.bakery;
+
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.serviceclient.WorkflowServiceStubs;
+
+public class OrderCookiesApp {
+    public static void main(String[] args) {
+        // This app simulates an order of cookies
+        // It should call the workflow which makes cookies
+        var orderRequest = CookieOrderRequest.random();
+
+        KitchenWorkflow workflow = TemporalUtils.newWorkflowStub(
+                KitchenWorkflow.class,
+                TemporalQueues.KITCHEN,
+                "kitchen-" + orderRequest.orderId()
+        );
+
+        workflow.makeCookies(orderRequest); // Start the Workflow Execution
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/OrderManyCookies.java b/solutions/day2/part-2.1/bakery/OrderManyCookies.java
new file mode 100644
index 0000000000000000000000000000000000000000..6421088ad913c656bd3133c5d715d182328f5959
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/OrderManyCookies.java
@@ -0,0 +1,70 @@
+package io.takima.temporalpractice.bakery;
+
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.api.enums.v1.ParentClosePolicy;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.workflow.*;
+import org.slf4j.Logger;
+
+import java.time.Duration;
+
+public class OrderManyCookies {
+    public static void main(String[] args) {
+        var queue = "manycookies";
+
+        TemporalUtils.newWorker(queue)
+                .registerWorkflowImplementationTypes(ManyCookiesImpl.class);
+
+        TemporalUtils.startWorkerFactory();
+
+        try {
+            ManyCookies manyCookies = TemporalUtils.CLIENT.newWorkflowStub(
+                    ManyCookies.class,
+                    WorkflowOptions.newBuilder().setWorkflowId("cookie-orderer").setTaskQueue(queue).build()
+            );
+            WorkflowClient.start(manyCookies::continuousOrders);
+        } catch (Exception e) {
+            System.out.println("Many cookies already running, skipping...");
+        }
+    }
+
+    public static class ManyCookiesImpl implements ManyCookies {
+
+        private static final Logger logger = Workflow.getLogger(ManyCookiesImpl.class);
+
+        @Override
+        public void continuousOrders() {
+
+            var options = ChildWorkflowOptions.newBuilder()
+                    .setWorkflowId("order-" + Workflow.randomUUID())
+                    .setTaskQueue(TemporalQueues.KITCHEN)
+                    .setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON)
+                    .build();
+            var kitchenWorkflow = Workflow.newChildWorkflowStub(KitchenWorkflow.class, options);
+
+            var quantity = Workflow.newRandom().nextInt(1, 5);
+            var baking = KitchenDtos.BakingPreference.values()[Workflow.newRandom().nextInt(KitchenDtos.BakingPreference.values().length)];
+            var topping = KitchenDtos.Topping.values()[Workflow.newRandom().nextInt(KitchenDtos.Topping.values().length)];
+
+            var cookiesPreferences = new KitchenDtos.CookieOrderRequest(Workflow.randomUUID().toString(), quantity, baking, topping);
+
+            logger.info("Ordering cookies\n{}", cookiesPreferences);
+            Async.function(kitchenWorkflow::makeCookies, cookiesPreferences);
+
+            Workflow.sleep(Duration.ofSeconds(10));
+            kitchenWorkflow.ovenReady();
+
+            Workflow.continueAsNew();
+        }
+    }
+
+    @WorkflowInterface
+    public interface ManyCookies {
+        @WorkflowMethod
+        void continuousOrders();
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/bake/BakeApp.java b/solutions/day2/part-2.1/bakery/bake/BakeApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d1cdb1f4cbfb9d2d79510e53c2e3534ff4eafc7
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/bake/BakeApp.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+
+public class BakeApp {
+    public static void main(String[] args) {
+        var worker = TemporalUtils.newWorker(TemporalQueues.BAKE);
+        worker.registerActivitiesImplementations(new BakeServiceImpl());
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/bake/BakeService.java b/solutions/day2/part-2.1/bakery/bake/BakeService.java
new file mode 100644
index 0000000000000000000000000000000000000000..36c0d02dba3dde7a8b166e68a8e3ff9c471870d6
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/bake/BakeService.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface BakeService {
+    @ActivityMethod
+    BakeResult bake(BakeRequest request);
+}
diff --git a/solutions/day2/part-2.1/bakery/bake/BakeServiceImpl.java b/solutions/day2/part-2.1/bakery/bake/BakeServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..22509b663a08745f19b2bb4b3fb78915c9fe50c9
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/bake/BakeServiceImpl.java
@@ -0,0 +1,22 @@
+package io.takima.temporalpractice.bakery.bake;
+
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Cookie;
+
+import java.util.ArrayList;
+
+public class BakeServiceImpl implements BakeService {
+  @Override
+  public BakeResult bake(BakeRequest request) {
+    System.out.println("Will bake those cookies " + request.bakingPreference());
+    var cookies = new ArrayList<Cookie>();
+    for (int i = 0; i < request.batter().targetCookieCount(); i++) {
+      // Making cookies out of batter
+      var cookie = new Cookie(request.bakingPreference(), request.batter().topping());
+      // Add it to the cookies after it is baked
+      cookies.add(cookie);
+    }
+    return new BakeResult(cookies);
+  }
+}
diff --git a/solutions/day2/part-2.1/bakery/bake/dtos/BakeRequest.java b/solutions/day2/part-2.1/bakery/bake/dtos/BakeRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..42701fec06fef7cac59011057af8dce46f4eba33
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/bake/dtos/BakeRequest.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.bake.dtos;
+
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.BakingPreference;
+
+public record BakeRequest(
+        String orderId,
+        Batter batter,
+        BakingPreference bakingPreference
+) {
+}
+
diff --git a/solutions/day2/part-2.1/bakery/bake/dtos/BakeResult.java b/solutions/day2/part-2.1/bakery/bake/dtos/BakeResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9afcf709a517afd86c44140f17877a9c061aac8
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/bake/dtos/BakeResult.java
@@ -0,0 +1,8 @@
+package io.takima.temporalpractice.bakery.bake.dtos;
+
+import java.util.List;
+
+import static io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Cookie;
+
+public record BakeResult(List<Cookie> cookies) {
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/BatterApp.java b/solutions/day2/part-2.1/bakery/batter/BatterApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b4bdb903208cebcca21d9fe8a357a4795f82431
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/BatterApp.java
@@ -0,0 +1,12 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+
+public class BatterApp {
+    public static void main(String[] args) {
+        var worker = TemporalUtils.newWorker(TemporalQueues.BATTER);
+        worker.registerActivitiesImplementations(new BatterServiceImpl());
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/BatterService.java b/solutions/day2/part-2.1/bakery/batter/BatterService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1353c54503494eed2c87e03165f287ca980677c0
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/BatterService.java
@@ -0,0 +1,17 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface BatterService {
+
+    @ActivityMethod
+    BatterCreationResult prepareBatter(BatterCreationRequest request);
+
+    @ActivityMethod
+    void cleanupBatterIfNeeded(BatterCleanupRequest request);
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/BatterServiceImpl.java b/solutions/day2/part-2.1/bakery/batter/BatterServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..17a2e83dccc8a4bd5b1093474b2e6dae84e1bd0b
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/BatterServiceImpl.java
@@ -0,0 +1,27 @@
+package io.takima.temporalpractice.bakery.batter;
+
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+
+public class BatterServiceImpl implements BatterService {
+
+    static final int BATTER_QTY_PER_COOKIE_IN_GRAMS = 30; // in grams
+
+    @Override
+    public BatterCreationResult prepareBatter(BatterCreationRequest request) {
+        System.out.println("Mixing flour, sugar, and love for " + request.targetCookieCount() + " cookies with topping " + request.targetTopping());
+        return new BatterCreationResult(
+                new Batter(
+                        request.targetTopping(),
+                        BATTER_QTY_PER_COOKIE_IN_GRAMS * request.targetCookieCount(),
+                        request.targetCookieCount()
+                ));
+    }
+
+    @Override
+    public void cleanupBatterIfNeeded(BatterCleanupRequest request) {
+        System.out.println("Cleaning up batter of order " + request.orderId());
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/dtos/Batter.java b/solutions/day2/part-2.1/bakery/batter/dtos/Batter.java
new file mode 100644
index 0000000000000000000000000000000000000000..8608c0e5eac1ddbee9e4d7c20da2549cc9ebfb21
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/dtos/Batter.java
@@ -0,0 +1,10 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Topping;
+
+public record Batter(
+        Topping topping,
+        int quantityInGrams,
+        int targetCookieCount
+) {
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/dtos/BatterCleanupRequest.java b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCleanupRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..26a9ea7d09c2cacbd61c2052cbc7d87164863653
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCleanupRequest.java
@@ -0,0 +1,4 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+public record BatterCleanupRequest(String orderId) {
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationRequest.java b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..38cc0c1cd6279c7bee0d6662202b4bd378b31084
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationRequest.java
@@ -0,0 +1,11 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.Topping;
+
+public record BatterCreationRequest(
+        String orderId,
+        Topping targetTopping,
+        int targetCookieCount
+) {
+
+}
diff --git a/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationResult.java b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75e6ab838e3fb45fb53ab2e0870d3a33a5ad975
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/batter/dtos/BatterCreationResult.java
@@ -0,0 +1,5 @@
+package io.takima.temporalpractice.bakery.batter.dtos;
+
+public record BatterCreationResult(Batter batter) {
+
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/KitchenApp.java b/solutions/day2/part-2.1/bakery/kitchen/KitchenApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..52854d18944702325a16ce304a84acfd55c03d35
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/KitchenApp.java
@@ -0,0 +1,14 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.takima.temporalpractice.bakery.temporal.TemporalUtils;
+import io.temporal.worker.Worker;
+
+public class KitchenApp {
+    public static void main(String[] args) {
+        Worker worker = TemporalUtils.newWorker(TemporalQueues.KITCHEN);
+        worker.registerWorkflowImplementationTypes(KitchenWorkflowImpl.class);
+        worker.registerWorkflowImplementationTypes(KitchenWorkflowImplLegacy.class);
+        TemporalUtils.startWorkerFactory();
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflow.java b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflow.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a48a8eb8c55b4faf718b57f9c989c524a196a4b
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflow.java
@@ -0,0 +1,23 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.temporal.workflow.QueryMethod;
+import io.temporal.workflow.SignalMethod;
+import io.temporal.workflow.WorkflowInterface;
+import io.temporal.workflow.WorkflowMethod;
+
+@WorkflowInterface
+public interface KitchenWorkflow {
+    String Type = "CookieOrderWorkflowV2";
+
+    @WorkflowMethod(name = Type)
+    CookieOrderResult makeCookies(CookieOrderRequest request);
+
+    @SignalMethod
+    void ovenReady();
+
+    @QueryMethod
+    CookieOrderStatus getStatus();
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImpl.java b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef842cf6404c64e9591dfdc9e136112e0e09f69f
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImpl.java
@@ -0,0 +1,72 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.takima.temporalpractice.bakery.temporal.TemporalActivityFactory;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.failure.ActivityFailure;
+import io.temporal.workflow.Saga;
+import io.temporal.workflow.Workflow;
+import org.slf4j.Logger;
+
+import java.time.Duration;
+import java.util.List;
+
+public class KitchenWorkflowImpl implements KitchenWorkflow {
+    private final BatterService batterService;
+    private final BakeService bakeService;
+    private boolean ovenReady = false;
+    private CookieOrderRequest cookieOrder;
+
+    private final Logger logger = Workflow.getLogger(KitchenWorkflowImpl.class);
+
+    private final Saga saga = new Saga(new Saga.Options.Builder().build());
+
+    public KitchenWorkflowImpl() {
+        this.batterService = TemporalActivityFactory.newActivityStub(BatterService.class, TemporalQueues.BATTER);
+        this.bakeService = TemporalActivityFactory.newActivityStub(BakeService.class, TemporalQueues.BAKE);
+    }
+
+
+    @Override
+    public CookieOrderResult makeCookies(CookieOrderRequest request) {
+        this.cookieOrder = request;
+        var timer = Workflow.newTimer(Duration.ofSeconds(30));
+
+        try {
+            saga.addCompensation(batterService::cleanupBatterIfNeeded, new BatterCleanupRequest(request.orderId()));
+
+            logger.info("Order {}: Starting to prepare {} cookies with topping {} and baking preference {}", request.orderId(), request.quantity(), request.topping(), request.bakingPreference());
+            var batterCreationResult = batterService.prepareBatter(new BatterCreationRequest(request.orderId(), request.topping(), request.quantity()));
+            var batter = batterCreationResult.batter();
+
+            Workflow.await(() -> ovenReady);
+
+            var bakeResult = bakeService.bake(new BakeRequest(request.orderId(), batter, request.bakingPreference()));
+
+            logger.info("Order {}: Your {} cookies are ready!", request.orderId(), bakeResult.cookies().size());
+
+            timer.get();
+            return new CookieOrderResult(request.orderId(), bakeResult.cookies());
+        } catch (ActivityFailure failures) {
+            saga.compensate();
+            return new CookieOrderResult(request.orderId(), List.of());
+        }
+    }
+
+    @Override
+    public void ovenReady() {
+        this.ovenReady = true;
+    }
+
+    @Override
+    public CookieOrderStatus getStatus() {
+        return new CookieOrderStatus(ovenReady, cookieOrder);
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImplLegacy.java b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImplLegacy.java
new file mode 100644
index 0000000000000000000000000000000000000000..e58630f9c93fe23e0b3ca6281d7ec5e599d75864
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowImplLegacy.java
@@ -0,0 +1,73 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.takima.temporalpractice.bakery.temporal.TemporalActivityFactory;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.failure.ActivityFailure;
+import io.temporal.workflow.Saga;
+import io.temporal.workflow.Workflow;
+import org.slf4j.Logger;
+
+import java.time.Duration;
+import java.util.List;
+
+@Deprecated
+public class KitchenWorkflowImplLegacy implements KitchenWorkflowLegacy {
+    private final BatterService batterService;
+    private final BakeService bakeService;
+    private boolean ovenReady = false;
+    private CookieOrderRequest cookieOrder;
+
+    private final Logger logger = Workflow.getLogger(KitchenWorkflowImplLegacy.class);
+
+    private final Saga saga = new Saga(new Saga.Options.Builder().build());
+
+    public KitchenWorkflowImplLegacy() {
+        this.batterService = TemporalActivityFactory.newActivityStub(BatterService.class, TemporalQueues.BATTER);
+        this.bakeService = TemporalActivityFactory.newActivityStub(BakeService.class, TemporalQueues.BAKE);
+    }
+
+
+    @Override
+    public CookieOrderResult makeCookies(CookieOrderRequest request) {
+        this.cookieOrder = request;
+        var timer = Workflow.newTimer(Duration.ofSeconds(30));
+
+        try {
+            saga.addCompensation(batterService::cleanupBatterIfNeeded, new BatterCleanupRequest(request.orderId()));
+
+            logger.info("Order {}: Starting to prepare {} cookies with topping {} and baking preference {}", request.orderId(), request.quantity(), request.topping(), request.bakingPreference());
+            var batterCreationResult = batterService.prepareBatter(new BatterCreationRequest(request.orderId(), request.topping(), request.quantity()));
+            var batter = batterCreationResult.batter();
+
+            Workflow.await(() -> ovenReady);
+
+            var bakeResult = bakeService.bake(new BakeRequest(request.orderId(), batter, request.bakingPreference()));
+
+            logger.info("Order {}: Your {} cookies are ready!", request.orderId(), bakeResult.cookies().size());
+
+            timer.get();
+            return new CookieOrderResult(request.orderId(), bakeResult.cookies());
+        } catch (ActivityFailure failures) {
+            saga.compensate();
+            return new CookieOrderResult(request.orderId(), List.of());
+        }
+    }
+
+    @Override
+    public void ovenReady() {
+        this.ovenReady = true;
+    }
+
+    @Override
+    public CookieOrderStatus getStatus() {
+        return new CookieOrderStatus(ovenReady, cookieOrder);
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowLegacy.java b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowLegacy.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6c3f98c95ed0a24dd352b7c9023d2987197d33a
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/KitchenWorkflowLegacy.java
@@ -0,0 +1,24 @@
+package io.takima.temporalpractice.bakery.kitchen;
+
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderRequest;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderResult;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos.CookieOrderStatus;
+import io.temporal.workflow.QueryMethod;
+import io.temporal.workflow.SignalMethod;
+import io.temporal.workflow.WorkflowInterface;
+import io.temporal.workflow.WorkflowMethod;
+
+@Deprecated
+@WorkflowInterface
+public interface KitchenWorkflowLegacy {
+    String Type = "CookieOrderWorkflow";
+
+    @WorkflowMethod(name = Type)
+    CookieOrderResult makeCookies(CookieOrderRequest request);
+
+    @SignalMethod
+    void ovenReady();
+
+    @QueryMethod
+    CookieOrderStatus getStatus();
+}
diff --git a/solutions/day2/part-2.1/bakery/kitchen/dtos/KitchenDtos.java b/solutions/day2/part-2.1/bakery/kitchen/dtos/KitchenDtos.java
new file mode 100644
index 0000000000000000000000000000000000000000..f82ef2e5c2ec62f10fb03b9b817cbdb4b39962a1
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/kitchen/dtos/KitchenDtos.java
@@ -0,0 +1,62 @@
+package io.takima.temporalpractice.bakery.kitchen.dtos;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface KitchenDtos {
+    enum BakingPreference {
+        RAW,
+        SOFT,
+        COOKED,
+        BURNT;
+
+        public static BakingPreference random() {
+            return values()[(int) (Math.random() * values().length)];
+        }
+    }
+
+    enum Topping {
+        CHOCOLATE,
+        NUTS,
+        NONE;
+
+        public static Topping random() {
+            return values()[(int) (Math.random() * values().length)];
+        }
+    }
+
+    record Cookie(
+            BakingPreference bakingPreference,
+            Topping topping
+    ) {
+    }
+
+    record CookieOrderRequest(
+            String orderId,
+            int quantity,
+            BakingPreference bakingPreference,
+            Topping topping
+    ) {
+
+        public static CookieOrderRequest random() {
+            return new CookieOrderRequest(
+                    UUID.randomUUID().toString(),
+                    (int) (Math.random() * 10) + 1,
+                    BakingPreference.random(),
+                    Topping.random()
+            );
+        }
+    }
+
+    record CookieOrderResult(
+            String orderId,
+            List<Cookie> cookies
+    ) {
+    }
+
+    record CookieOrderStatus(
+            boolean ovenReady,
+            CookieOrderRequest request
+    ) {
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/temporal/TemporalActivityFactory.java b/solutions/day2/part-2.1/bakery/temporal/TemporalActivityFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec51a0efbc4d17dff652a241ef7d40fa16ffa92f
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/temporal/TemporalActivityFactory.java
@@ -0,0 +1,20 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+import java.time.Duration;
+
+public class TemporalActivityFactory {
+    public static <T> T newActivityStub(Class<T> workflowInterface, String queue) {
+        return Workflow.newActivityStub(
+                workflowInterface,
+                ActivityOptions.newBuilder()
+                        .setTaskQueue(queue)
+                        .setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(2).build())
+                        .setStartToCloseTimeout(Duration.ofSeconds(5))
+                        .build()
+        );
+    }
+}
diff --git a/solutions/day2/part-2.1/bakery/temporal/TemporalQueues.java b/solutions/day2/part-2.1/bakery/temporal/TemporalQueues.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c99053e91384d67bce35b927bd47b3ce58444b3
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/temporal/TemporalQueues.java
@@ -0,0 +1,7 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+public class TemporalQueues {
+  public static final String KITCHEN = "kitchen";
+  public static final String BATTER = "batter";
+  public static final String BAKE = "bake";
+}
diff --git a/solutions/day2/part-2.1/bakery/temporal/TemporalUtils.java b/solutions/day2/part-2.1/bakery/temporal/TemporalUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..101f7e67044053b8cd545983db756f27b1c5d0e8
--- /dev/null
+++ b/solutions/day2/part-2.1/bakery/temporal/TemporalUtils.java
@@ -0,0 +1,36 @@
+package io.takima.temporalpractice.bakery.temporal;
+
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+import io.temporal.serviceclient.WorkflowServiceStubs;
+import io.temporal.worker.Worker;
+import io.temporal.worker.WorkerFactory;
+
+public class TemporalUtils {
+
+    // Represents the connection to your local cluster. For now, lets keep it simple
+    private static final WorkflowServiceStubs SERVICE_STUBS = WorkflowServiceStubs.newLocalServiceStubs();
+
+    // Your key for interacting with the Temporal world.
+    public static final WorkflowClient CLIENT = WorkflowClient.newInstance(SERVICE_STUBS);
+
+    private static final WorkerFactory FACTORY = WorkerFactory.newInstance(CLIENT);
+
+    public static Worker newWorker(String queue) {
+        return FACTORY.newWorker(queue);
+    }
+
+    public static void startWorkerFactory() {
+        FACTORY.start();
+    }
+
+    public static <T> T newWorkflowStub(Class<T> workflowInterface, String queue, String workflowId) {
+        return CLIENT.newWorkflowStub(
+                workflowInterface,
+                WorkflowOptions.newBuilder()
+                        .setTaskQueue(queue)
+                        .setWorkflowId(workflowId)
+                        .build()
+        );
+    }
+}
diff --git a/solutions/day2/part-2.2/test/java/io/takima/temporalpractice/.gitkeep b/solutions/day2/part-2.2/test/java/io/takima/temporalpractice/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/solutions/day2/part-2.2/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java b/solutions/day2/part-2.2/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..aed1a852b966faa4bcee58db5dbe7d6c2c4d3136
--- /dev/null
+++ b/solutions/day2/part-2.2/test/java/io/takima/temporalpractice/bakery/cookie/CookieWorkflowTest.java
@@ -0,0 +1,130 @@
+package io.takima.temporalpractice.bakery.cookie;
+
+import io.takima.temporalpractice.bakery.bake.BakeService;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeRequest;
+import io.takima.temporalpractice.bakery.bake.dtos.BakeResult;
+import io.takima.temporalpractice.bakery.batter.BatterService;
+import io.takima.temporalpractice.bakery.batter.dtos.Batter;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCleanupRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationRequest;
+import io.takima.temporalpractice.bakery.batter.dtos.BatterCreationResult;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow;
+import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflowImpl;
+import io.takima.temporalpractice.bakery.kitchen.dtos.KitchenDtos;
+import io.takima.temporalpractice.bakery.temporal.TemporalQueues;
+import io.temporal.client.WorkflowClient;
+import io.temporal.testing.TestWorkflowEnvironment;
+import io.temporal.testing.TestWorkflowExtension;
+import io.temporal.testing.WorkflowReplayer;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.File;
+import java.time.Duration;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+public class CookieWorkflowTest {
+
+    @Mock(withoutAnnotations = true)
+    private BakeService bakeService;
+
+    @Mock(withoutAnnotations = true)
+    private BatterService batterService;
+
+
+    @RegisterExtension
+    public static final TestWorkflowExtension testWorkflowExtension =
+            TestWorkflowExtension.newBuilder()
+                    .registerWorkflowImplementationTypes(KitchenWorkflowImpl.class)
+                    .setDoNotStart(true)
+                    .build();
+
+    @BeforeEach
+    void init(TestWorkflowEnvironment testEnv) {
+        testEnv.newWorker(TemporalQueues.BAKE)
+                .registerActivitiesImplementations(bakeService);
+        testEnv.newWorker(TemporalQueues.BATTER)
+                .registerActivitiesImplementations(batterService);
+        testEnv.start();
+    }
+
+    KitchenDtos.CookieOrderRequest request = KitchenDtos.CookieOrderRequest.random();
+    BatterCreationRequest batterCreationRequest = new BatterCreationRequest(request.orderId(), request.topping(), request.quantity());
+    BatterCreationResult batterCreationResult = new BatterCreationResult(new Batter(request.topping(), 30 * request.quantity(), request.quantity()));
+    BakeRequest bakeRequest = new BakeRequest(request.orderId(), batterCreationResult.batter(), request.bakingPreference());
+    BakeResult bakeResult = new BakeResult(List.of(new KitchenDtos.Cookie(request.bakingPreference(), request.topping())));
+
+    @Test
+    public void shouldCleanupBatter(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        WorkflowClient.start(workflow::makeCookies, request);
+
+        when(batterService.prepareBatter(batterCreationRequest))
+                .thenReturn(batterCreationResult);
+        workflow.ovenReady();
+        when(bakeService.bake(bakeRequest))
+                .thenThrow(new RuntimeException("I will always fail"));
+
+        var result = workflow.makeCookies(request);
+
+        verify(batterService).cleanupBatterIfNeeded(new BatterCleanupRequest(request.orderId()));
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies()).isEmpty();
+    }
+
+    @Test
+    public void shouldMakeCookies(
+            // Test environment for configuration
+            TestWorkflowEnvironment testEnv,
+            // Auto-created Workflow stub
+            KitchenWorkflow workflow
+    ) {
+        // get the env starting time
+        var startTime = testEnv.currentTimeMillis();
+
+        // Start the workflow asynchronously
+        WorkflowClient.start(workflow::makeCookies, request);
+        when(batterService.prepareBatter(batterCreationRequest))
+                .thenThrow(new RuntimeException("I failed on first try"))
+                .thenReturn(batterCreationResult);
+        // Make sure we dont bake before the oven is ready
+        verifyNoInteractions(bakeService);
+
+        var status = workflow.getStatus();
+        assertThat(status.ovenReady()).isFalse();
+        assertThat(status.request()).isEqualTo(request);
+
+        workflow.ovenReady();
+        status = workflow.getStatus();
+        assertThat(status.ovenReady()).isTrue();
+        when(bakeService.bake(bakeRequest)).thenReturn(bakeResult);
+
+        // Get the workflow result
+        var result = workflow.makeCookies(request);
+
+        assertThat(result.orderId()).isEqualTo(request.orderId());
+        assertThat(result.cookies())
+                .isEqualTo(bakeResult.cookies());
+
+        var duration = Duration.ofMillis(testEnv.currentTimeMillis() - startTime);
+        assertThat(duration).isGreaterThan(Duration.ofSeconds(30));
+    }
+
+    @Test
+    void shouldNotBreakDeterminism() throws Exception {
+        var historyFile = new File("src/test/resources/history.json");
+        WorkflowReplayer.replayWorkflowExecution(historyFile, KitchenWorkflowImpl.class);
+    }
+}
diff --git a/solutions/day2/part-2.2/test/resources/history.json b/solutions/day2/part-2.2/test/resources/history.json
new file mode 100644
index 0000000000000000000000000000000000000000..5e73fd1e48775588ab7f510cb8bb613c08379f84
--- /dev/null
+++ b/solutions/day2/part-2.2/test/resources/history.json
@@ -0,0 +1,437 @@
+{
+  "events": [
+    {
+      "eventId": "1",
+      "eventTime": "2025-05-20T09:21:02.200461472Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED",
+      "taskId": "3148028",
+      "workflowExecutionStartedEventAttributes": {
+        "workflowType": {
+          "name": "CookieOrderWorkflowV2"
+        },
+        "taskQueue": {
+          "name": "kitchen",
+          "kind": "TASK_QUEUE_KIND_NORMAL"
+        },
+        "input": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJvcmRlcklkIjoiNzAyY2E1NDEtMzdiYi00YzI4LTg0NGMtZDc1OWY0ZDIyNTZjIiwicXVhbnRpdHkiOjEsImJha2luZ1ByZWZlcmVuY2UiOiJTT0ZUIiwidG9wcGluZyI6IkNIT0NPTEFURSJ9"
+            }
+          ]
+        },
+        "workflowExecutionTimeout": "0s",
+        "workflowRunTimeout": "0s",
+        "workflowTaskTimeout": "10s",
+        "originalExecutionRunId": "0196ecff-14f8-7705-af1f-58e18b61f61d",
+        "identity": "36905@MacBookPro.takima.home",
+        "firstExecutionRunId": "0196ecff-14f8-7705-af1f-58e18b61f61d",
+        "attempt": 1,
+        "firstWorkflowTaskBackoff": "0s",
+        "header": {},
+        "workflowId": "kitchen-702ca541-37bb-4c28-844c-d759f4d2256c"
+      }
+    },
+    {
+      "eventId": "2",
+      "eventTime": "2025-05-20T09:21:02.200563764Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
+      "taskId": "3148029",
+      "workflowTaskScheduledEventAttributes": {
+        "taskQueue": {
+          "name": "kitchen",
+          "kind": "TASK_QUEUE_KIND_NORMAL"
+        },
+        "startToCloseTimeout": "10s",
+        "attempt": 1
+      }
+    },
+    {
+      "eventId": "3",
+      "eventTime": "2025-05-20T09:21:02.209216055Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
+      "taskId": "3148034",
+      "workflowTaskStartedEventAttributes": {
+        "scheduledEventId": "2",
+        "identity": "36902@MacBookPro.takima.home",
+        "requestId": "e9bb9cdd-4427-4645-9cf4-07a8a2560054",
+        "historySizeBytes": "425"
+      }
+    },
+    {
+      "eventId": "4",
+      "eventTime": "2025-05-20T09:21:02.388671041Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
+      "taskId": "3148038",
+      "workflowTaskCompletedEventAttributes": {
+        "scheduledEventId": "2",
+        "startedEventId": "3",
+        "identity": "36902@MacBookPro.takima.home",
+        "workerVersion": {},
+        "sdkMetadata": {
+          "langUsedFlags": [
+            1
+          ]
+        },
+        "meteringMetadata": {}
+      }
+    },
+    {
+      "eventId": "5",
+      "eventTime": "2025-05-20T09:21:02.388723958Z",
+      "eventType": "EVENT_TYPE_TIMER_STARTED",
+      "taskId": "3148039",
+      "timerStartedEventAttributes": {
+        "timerId": "98d73a02-7edb-39dd-a643-79005e644b64",
+        "startToFireTimeout": "30s",
+        "workflowTaskCompletedEventId": "4"
+      }
+    },
+    {
+      "eventId": "6",
+      "eventTime": "2025-05-20T09:21:02.388758875Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED",
+      "taskId": "3148040",
+      "activityTaskScheduledEventAttributes": {
+        "activityId": "92159483-48ab-3725-862f-7bf8a043d767",
+        "activityType": {
+          "name": "PrepareBatter"
+        },
+        "taskQueue": {
+          "name": "batter",
+          "kind": "TASK_QUEUE_KIND_NORMAL"
+        },
+        "header": {},
+        "input": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJvcmRlcklkIjoiNzAyY2E1NDEtMzdiYi00YzI4LTg0NGMtZDc1OWY0ZDIyNTZjIiwidGFyZ2V0VG9wcGluZyI6IkNIT0NPTEFURSIsInRhcmdldENvb2tpZUNvdW50IjoxfQ=="
+            }
+          ]
+        },
+        "scheduleToCloseTimeout": "0s",
+        "scheduleToStartTimeout": "0s",
+        "startToCloseTimeout": "5s",
+        "heartbeatTimeout": "0s",
+        "workflowTaskCompletedEventId": "4",
+        "retryPolicy": {
+          "initialInterval": "1s",
+          "backoffCoefficient": 2,
+          "maximumInterval": "100s",
+          "maximumAttempts": 2
+        }
+      }
+    },
+    {
+      "eventId": "7",
+      "eventTime": "2025-05-20T09:21:02.394468666Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED",
+      "taskId": "3148047",
+      "activityTaskStartedEventAttributes": {
+        "scheduledEventId": "6",
+        "identity": "36781@MacBookPro.takima.home",
+        "requestId": "732e3649-f870-499a-84ef-cde1ed52afc2",
+        "attempt": 1,
+        "workerVersion": {}
+      }
+    },
+    {
+      "eventId": "8",
+      "eventTime": "2025-05-20T09:21:02.400925625Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED",
+      "taskId": "3148048",
+      "activityTaskCompletedEventAttributes": {
+        "result": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJiYXR0ZXIiOnsidG9wcGluZyI6IkNIT0NPTEFURSIsInF1YW50aXR5SW5HcmFtcyI6MzAsInRhcmdldENvb2tpZUNvdW50IjoxfX0="
+            }
+          ]
+        },
+        "scheduledEventId": "6",
+        "startedEventId": "7",
+        "identity": "36781@MacBookPro.takima.home"
+      }
+    },
+    {
+      "eventId": "9",
+      "eventTime": "2025-05-20T09:21:02.400931125Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
+      "taskId": "3148049",
+      "workflowTaskScheduledEventAttributes": {
+        "taskQueue": {
+          "name": "36902@MacBookPro.takima.home:27069735-1e75-4a62-9677-69417d0e5b39",
+          "kind": "TASK_QUEUE_KIND_STICKY",
+          "normalName": "kitchen"
+        },
+        "startToCloseTimeout": "10s",
+        "attempt": 1
+      }
+    },
+    {
+      "eventId": "10",
+      "eventTime": "2025-05-20T09:21:02.404223166Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
+      "taskId": "3148053",
+      "workflowTaskStartedEventAttributes": {
+        "scheduledEventId": "9",
+        "identity": "36902@MacBookPro.takima.home",
+        "requestId": "a1fb1d18-2dfe-4ec1-b812-3135bdf6229b",
+        "historySizeBytes": "1314"
+      }
+    },
+    {
+      "eventId": "11",
+      "eventTime": "2025-05-20T09:21:02.418556Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
+      "taskId": "3148057",
+      "workflowTaskCompletedEventAttributes": {
+        "scheduledEventId": "9",
+        "startedEventId": "10",
+        "identity": "36902@MacBookPro.takima.home",
+        "workerVersion": {},
+        "meteringMetadata": {}
+      }
+    },
+    {
+      "eventId": "12",
+      "eventTime": "2025-05-20T09:21:32.393183416Z",
+      "eventType": "EVENT_TYPE_TIMER_FIRED",
+      "taskId": "3148060",
+      "timerFiredEventAttributes": {
+        "timerId": "98d73a02-7edb-39dd-a643-79005e644b64",
+        "startedEventId": "5"
+      }
+    },
+    {
+      "eventId": "13",
+      "eventTime": "2025-05-20T09:21:32.393217500Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
+      "taskId": "3148061",
+      "workflowTaskScheduledEventAttributes": {
+        "taskQueue": {
+          "name": "36902@MacBookPro.takima.home:27069735-1e75-4a62-9677-69417d0e5b39",
+          "kind": "TASK_QUEUE_KIND_STICKY",
+          "normalName": "kitchen"
+        },
+        "startToCloseTimeout": "10s",
+        "attempt": 1
+      }
+    },
+    {
+      "eventId": "14",
+      "eventTime": "2025-05-20T09:21:32.404506541Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
+      "taskId": "3148065",
+      "workflowTaskStartedEventAttributes": {
+        "scheduledEventId": "13",
+        "identity": "36902@MacBookPro.takima.home",
+        "requestId": "8a083d1c-0ba7-4ca9-ae54-03e303b4d1df",
+        "historySizeBytes": "1660"
+      }
+    },
+    {
+      "eventId": "15",
+      "eventTime": "2025-05-20T09:21:32.421678958Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
+      "taskId": "3148069",
+      "workflowTaskCompletedEventAttributes": {
+        "scheduledEventId": "13",
+        "startedEventId": "14",
+        "identity": "36902@MacBookPro.takima.home",
+        "workerVersion": {},
+        "meteringMetadata": {}
+      }
+    },
+    {
+      "eventId": "16",
+      "eventTime": "2025-05-20T09:31:25.471000502Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED",
+      "taskId": "3148071",
+      "workflowExecutionSignaledEventAttributes": {
+        "signalName": "ovenReady",
+        "input": {}
+      }
+    },
+    {
+      "eventId": "17",
+      "eventTime": "2025-05-20T09:31:25.471008835Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
+      "taskId": "3148072",
+      "workflowTaskScheduledEventAttributes": {
+        "taskQueue": {
+          "name": "36902@MacBookPro.takima.home:27069735-1e75-4a62-9677-69417d0e5b39",
+          "kind": "TASK_QUEUE_KIND_STICKY",
+          "normalName": "kitchen"
+        },
+        "startToCloseTimeout": "10s",
+        "attempt": 1
+      }
+    },
+    {
+      "eventId": "18",
+      "eventTime": "2025-05-20T09:31:25.478133502Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
+      "taskId": "3148076",
+      "workflowTaskStartedEventAttributes": {
+        "scheduledEventId": "17",
+        "identity": "36902@MacBookPro.takima.home",
+        "requestId": "14720a8e-9b34-419c-a8a9-559b40c19f8c",
+        "historySizeBytes": "1979"
+      }
+    },
+    {
+      "eventId": "19",
+      "eventTime": "2025-05-20T09:31:25.494807919Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
+      "taskId": "3148080",
+      "workflowTaskCompletedEventAttributes": {
+        "scheduledEventId": "17",
+        "startedEventId": "18",
+        "identity": "36902@MacBookPro.takima.home",
+        "workerVersion": {},
+        "meteringMetadata": {}
+      }
+    },
+    {
+      "eventId": "20",
+      "eventTime": "2025-05-20T09:31:25.494843794Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED",
+      "taskId": "3148081",
+      "activityTaskScheduledEventAttributes": {
+        "activityId": "23d7c2c4-cb8c-3dee-b3d2-e8300ca29511",
+        "activityType": {
+          "name": "Bake"
+        },
+        "taskQueue": {
+          "name": "bake",
+          "kind": "TASK_QUEUE_KIND_NORMAL"
+        },
+        "header": {},
+        "input": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJvcmRlcklkIjoiNzAyY2E1NDEtMzdiYi00YzI4LTg0NGMtZDc1OWY0ZDIyNTZjIiwiYmF0dGVyIjp7InRvcHBpbmciOiJDSE9DT0xBVEUiLCJxdWFudGl0eUluR3JhbXMiOjMwLCJ0YXJnZXRDb29raWVDb3VudCI6MX0sImJha2luZ1ByZWZlcmVuY2UiOiJTT0ZUIn0="
+            }
+          ]
+        },
+        "scheduleToCloseTimeout": "0s",
+        "scheduleToStartTimeout": "0s",
+        "startToCloseTimeout": "5s",
+        "heartbeatTimeout": "0s",
+        "workflowTaskCompletedEventId": "19",
+        "retryPolicy": {
+          "initialInterval": "1s",
+          "backoffCoefficient": 2,
+          "maximumInterval": "100s",
+          "maximumAttempts": 2
+        }
+      }
+    },
+    {
+      "eventId": "21",
+      "eventTime": "2025-05-20T09:31:25.498424877Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED",
+      "taskId": "3148086",
+      "activityTaskStartedEventAttributes": {
+        "scheduledEventId": "20",
+        "identity": "36783@MacBookPro.takima.home",
+        "requestId": "31445516-84c7-4cb3-8d81-95c62fba17a3",
+        "attempt": 1,
+        "workerVersion": {}
+      }
+    },
+    {
+      "eventId": "22",
+      "eventTime": "2025-05-20T09:31:25.582749377Z",
+      "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED",
+      "taskId": "3148087",
+      "activityTaskCompletedEventAttributes": {
+        "result": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJjb29raWVzIjpbeyJiYWtpbmdQcmVmZXJlbmNlIjoiU09GVCIsInRvcHBpbmciOiJDSE9DT0xBVEUifV19"
+            }
+          ]
+        },
+        "scheduledEventId": "20",
+        "startedEventId": "21",
+        "identity": "36783@MacBookPro.takima.home"
+      }
+    },
+    {
+      "eventId": "23",
+      "eventTime": "2025-05-20T09:31:25.582760710Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
+      "taskId": "3148088",
+      "workflowTaskScheduledEventAttributes": {
+        "taskQueue": {
+          "name": "36902@MacBookPro.takima.home:27069735-1e75-4a62-9677-69417d0e5b39",
+          "kind": "TASK_QUEUE_KIND_STICKY",
+          "normalName": "kitchen"
+        },
+        "startToCloseTimeout": "10s",
+        "attempt": 1
+      }
+    },
+    {
+      "eventId": "24",
+      "eventTime": "2025-05-20T09:31:25.589439919Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
+      "taskId": "3148092",
+      "workflowTaskStartedEventAttributes": {
+        "scheduledEventId": "23",
+        "identity": "36902@MacBookPro.takima.home",
+        "requestId": "e6cd5cd1-4f48-4d44-86b3-de2543e020c3",
+        "historySizeBytes": "2820"
+      }
+    },
+    {
+      "eventId": "25",
+      "eventTime": "2025-05-20T09:31:25.603636960Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
+      "taskId": "3148096",
+      "workflowTaskCompletedEventAttributes": {
+        "scheduledEventId": "23",
+        "startedEventId": "24",
+        "identity": "36902@MacBookPro.takima.home",
+        "workerVersion": {},
+        "meteringMetadata": {}
+      }
+    },
+    {
+      "eventId": "26",
+      "eventTime": "2025-05-20T09:31:25.603693210Z",
+      "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED",
+      "taskId": "3148097",
+      "workflowExecutionCompletedEventAttributes": {
+        "result": {
+          "payloads": [
+            {
+              "metadata": {
+                "encoding": "anNvbi9wbGFpbg=="
+              },
+              "data": "eyJvcmRlcklkIjoiNzAyY2E1NDEtMzdiYi00YzI4LTg0NGMtZDc1OWY0ZDIyNTZjIiwiY29va2llcyI6W3siYmFraW5nUHJlZmVyZW5jZSI6IlNPRlQiLCJ0b3BwaW5nIjoiQ0hPQ09MQVRFIn1dfQ=="
+            }
+          ]
+        },
+        "workflowTaskCompletedEventId": "25"
+      }
+    }
+  ]
+}
\ No newline at end of file