From 3f9d724eea8f51f7b1299d7abe5ad3b77a5ed133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Ortola?= <contact@loicortola.com> Date: Sat, 17 May 2025 11:24:36 +0200 Subject: [PATCH] feat: added step-2 --- .../bakery/kitchen/KitchenWorker.java | 5 --- .../bakery/MakeCookiesApp.java | 10 +++++ .../bakery/OrderCookiesApp.java | 22 +++++++++++ .../bakery/kitchen/KitchenWorker.java | 30 +++++++++++++++ .../bakery/kitchen/KitchenWorkflow.java | 10 +++++ .../bakery/kitchen/KitchenWorkflowImpl.java | 34 +++++++++++++++++ .../bakery/kitchen/bake/BakeService.java | 10 +++++ .../bakery/kitchen/bake/BakeServiceImpl.java | 8 ++++ .../bakery/kitchen/batter/BatterService.java | 10 +++++ .../kitchen/batter/BatterServiceImpl.java | 8 ++++ .../signals/ConsumeSignal.java | 4 ++ .../signals/InventoryActivity.java | 7 ++++ .../signals/InventoryActivityImpl.java | 26 +++++++++++++ .../signals/InventoryWorkflow.java | 10 +++++ .../temporalpractice/signals/MSMain.java | 37 +++++++++++++++++++ 15 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 solutions/day1/part-2/temporalpractice/bakery/MakeCookiesApp.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/OrderCookiesApp.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorker.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflow.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeService.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeServiceImpl.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterService.java create mode 100644 solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterServiceImpl.java create mode 100644 solutions/day1/part-2/temporalpractice/signals/ConsumeSignal.java create mode 100644 solutions/day1/part-2/temporalpractice/signals/InventoryActivity.java create mode 100644 solutions/day1/part-2/temporalpractice/signals/InventoryActivityImpl.java create mode 100644 solutions/day1/part-2/temporalpractice/signals/InventoryWorkflow.java create mode 100644 solutions/day1/part-2/temporalpractice/signals/MSMain.java diff --git a/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java index b61e118..0f982df 100644 --- a/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java +++ b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java @@ -13,11 +13,6 @@ public class KitchenWorker { // Your key for interacting with the Temporal world. WorkflowClient client = WorkflowClient.newInstance(serviceStub); - WorkflowOptions options = WorkflowOptions.newBuilder() - .setTaskQueue("TheOneAndOnlyQueue") - .setWorkflowId("best-cookie") - .build(); - WorkerFactory factory = WorkerFactory.newInstance(client); Worker worker = factory.newWorker("TheOneAndOnlyQueue"); diff --git a/solutions/day1/part-2/temporalpractice/bakery/MakeCookiesApp.java b/solutions/day1/part-2/temporalpractice/bakery/MakeCookiesApp.java new file mode 100644 index 0000000..2ea7f9b --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/MakeCookiesApp.java @@ -0,0 +1,10 @@ +package io.takima.temporalpractice.bakery; + +import io.takima.temporalpractice.bakery.kitchen.KitchenWorker; + +public class MakeCookiesApp { + public static void main(String[] args) { + // This app should execute the making of all cookies ordered + new KitchenWorker().start(); + } +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/OrderCookiesApp.java b/solutions/day1/part-2/temporalpractice/bakery/OrderCookiesApp.java new file mode 100644 index 0000000..0639213 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/OrderCookiesApp.java @@ -0,0 +1,22 @@ +package io.takima.temporalpractice.bakery; + +import io.takima.temporalpractice.bakery.kitchen.KitchenWorkflow; +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 + WorkflowClient client = WorkflowClient.newInstance(WorkflowServiceStubs.newLocalServiceStubs()); + WorkflowOptions options = WorkflowOptions.newBuilder() + .setTaskQueue("TheOneAndOnlyQueue") + .setWorkflowId("best-cookie") + .build(); + + KitchenWorkflow workflow = client.newWorkflowStub(KitchenWorkflow.class, options); + + workflow.makeCookies(); // Start the Workflow Execution + } +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorker.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorker.java new file mode 100644 index 0000000..b92e5a6 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorker.java @@ -0,0 +1,30 @@ +package io.takima.temporalpractice.bakery.kitchen; + +import io.takima.temporalpractice.bakery.kitchen.bake.BakeServiceImpl; +import io.takima.temporalpractice.bakery.kitchen.batter.BatterServiceImpl; +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 KitchenWorker { + public void start() { + // Represents the connection to your local cluster. For now, lets keep it simple + WorkflowServiceStubs serviceStub = WorkflowServiceStubs.newLocalServiceStubs(); + // Your key for interacting with the Temporal world. + WorkflowClient client = WorkflowClient.newInstance(serviceStub); + + WorkerFactory factory = WorkerFactory.newInstance(client); + + Worker worker = factory.newWorker("TheOneAndOnlyQueue"); + + // Register workflows + worker.registerWorkflowImplementationTypes(KitchenWorkflowImpl.class); + // Register activities + worker.registerActivitiesImplementations(new BakeServiceImpl()); + worker.registerActivitiesImplementations(new BatterServiceImpl()); + + factory.start(); + } +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflow.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflow.java new file mode 100644 index 0000000..bec377d --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflow.java @@ -0,0 +1,10 @@ +package io.takima.temporalpractice.bakery.kitchen; + +import io.temporal.workflow.WorkflowInterface; +import io.temporal.workflow.WorkflowMethod; + +@WorkflowInterface +public interface KitchenWorkflow { + @WorkflowMethod + void makeCookies(); +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java new file mode 100644 index 0000000..529793a --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java @@ -0,0 +1,34 @@ +package io.takima.temporalpractice.bakery.kitchen; + +import io.takima.temporalpractice.bakery.kitchen.bake.BakeService; +import io.takima.temporalpractice.bakery.kitchen.batter.BatterService; +import io.temporal.activity.ActivityOptions; +import io.temporal.workflow.Workflow; + +import java.time.Duration; + +public class KitchenWorkflowImpl implements KitchenWorkflow { + private final BatterService batterService; + private final BakeService bakeService; + + public KitchenWorkflowImpl() { + ActivityOptions options = ActivityOptions.newBuilder() + .setTaskQueue("TheOneAndOnlyQueue") + .setStartToCloseTimeout(Duration.ofSeconds(10)) + .build(); + + this.batterService = Workflow.newActivityStub(BatterService.class, options); + this.bakeService = Workflow.newActivityStub(BakeService.class, options); + } + + + @Override + public void makeCookies() { + // Note: System.out.println is used here for simplicity + // In real applications, you should use proper Workflow-aware logging (we'll cover this in Day 2) + System.out.println("Starting to prepare your cookie!"); + batterService.prepareBatter(); + bakeService.bake(); + System.out.println("Your cookie is ready!"); + } +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeService.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeService.java new file mode 100644 index 0000000..5b6ed8d --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeService.java @@ -0,0 +1,10 @@ +package io.takima.temporalpractice.bakery.kitchen.bake; + +import io.temporal.activity.ActivityInterface; +import io.temporal.activity.ActivityMethod; + +@ActivityInterface +public interface BakeService { + @ActivityMethod + void bake(); +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeServiceImpl.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeServiceImpl.java new file mode 100644 index 0000000..6f4a582 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/bake/BakeServiceImpl.java @@ -0,0 +1,8 @@ +package io.takima.temporalpractice.bakery.kitchen.bake; + +public class BakeServiceImpl implements BakeService { + @Override + public void bake() { + System.out.println("Now baking those cookies."); + } +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterService.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterService.java new file mode 100644 index 0000000..e366a46 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterService.java @@ -0,0 +1,10 @@ +package io.takima.temporalpractice.bakery.kitchen.batter; + +import io.temporal.activity.ActivityInterface; +import io.temporal.activity.ActivityMethod; + +@ActivityInterface +public interface BatterService { + @ActivityMethod + void prepareBatter(); +} diff --git a/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterServiceImpl.java b/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterServiceImpl.java new file mode 100644 index 0000000..4a428a0 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/bakery/kitchen/batter/BatterServiceImpl.java @@ -0,0 +1,8 @@ +package io.takima.temporalpractice.bakery.kitchen.batter; + +public class BatterServiceImpl implements BatterService { + @Override + public void prepareBatter() { + System.out.println("Mixing flour, sugar, and love..."); + } +} diff --git a/solutions/day1/part-2/temporalpractice/signals/ConsumeSignal.java b/solutions/day1/part-2/temporalpractice/signals/ConsumeSignal.java new file mode 100644 index 0000000..ea74daf --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/signals/ConsumeSignal.java @@ -0,0 +1,4 @@ +package io.takima.temporalpractice.signals; + +public record ConsumeSignal(int amount) { +} diff --git a/solutions/day1/part-2/temporalpractice/signals/InventoryActivity.java b/solutions/day1/part-2/temporalpractice/signals/InventoryActivity.java new file mode 100644 index 0000000..1645c76 --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/signals/InventoryActivity.java @@ -0,0 +1,7 @@ +package io.takima.temporalpractice.signals; +// TODO : remove comments when starting the mastering signals exercise on day 2 +//@ActivityInterface +public interface InventoryActivity { + void reserve(ConsumeSignal input); + +} diff --git a/solutions/day1/part-2/temporalpractice/signals/InventoryActivityImpl.java b/solutions/day1/part-2/temporalpractice/signals/InventoryActivityImpl.java new file mode 100644 index 0000000..db1105d --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/signals/InventoryActivityImpl.java @@ -0,0 +1,26 @@ +package io.takima.temporalpractice.signals; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InventoryActivityImpl implements InventoryActivity { + private static final Logger logger = LoggerFactory.getLogger(InventoryActivityImpl.class); + int counter; + + public InventoryActivityImpl(int inventorySize){ + this.counter = inventorySize; + } + + @Override + public void reserve(ConsumeSignal input) { + int currentValue = counter; + + try { + //Simulate async work + Thread.sleep(10); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + counter = currentValue - 1; + logger.info("counter: " + counter); + } +} diff --git a/solutions/day1/part-2/temporalpractice/signals/InventoryWorkflow.java b/solutions/day1/part-2/temporalpractice/signals/InventoryWorkflow.java new file mode 100644 index 0000000..f7cfebd --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/signals/InventoryWorkflow.java @@ -0,0 +1,10 @@ +package io.takima.temporalpractice.signals; +// TODO : remove comments when starting the mastering signals exercise on day 2 +//@WorkflowInterface +public interface InventoryWorkflow { +// @WorkflowMethod + void run(); +// @SignalMethod + void reserve(ConsumeSignal input); + +} diff --git a/solutions/day1/part-2/temporalpractice/signals/MSMain.java b/solutions/day1/part-2/temporalpractice/signals/MSMain.java new file mode 100644 index 0000000..61cdb4a --- /dev/null +++ b/solutions/day1/part-2/temporalpractice/signals/MSMain.java @@ -0,0 +1,37 @@ +package io.takima.temporalpractice.signals; +// TODO : remove comments when starting the mastering signals exercise on day 2 +//import io.temporal.client.WorkflowClient; +//import io.temporal.client.WorkflowOptions; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +//import static io.takima.temporalpractice.temporal.TemporalUtils.*; +//import static io.takima.temporalpractice.temporal.TemporalQueues.*; +public class MSMain { + + // Our inventory will contain 100 elements and we will send 100 signals, lets see how it goes + static int inventoryToDecrement = 100; + + public static void main(String[] args) { +// var worker = FACTORY.newWorker(MASTERING_SIGNALS); +// worker.registerActivitiesImplementations(new InventoryActivityImpl(inventoryToDecrement)); +// worker.registerWorkflowImplementationTypes(InventoryWorkflowImpl.class); + +// FACTORY.start(); + +// var workflow = CLIENT.newWorkflowStub( +// InventoryWorkflow.class, +// WorkflowOptions.newBuilder().setTaskQueue(MASTERING_SIGNALS).setWorkflowId("inventory").build() +// ); +// WorkflowClient.start(workflow::run); + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + // Submit 100 tasks + for (int i = 1; i < inventoryToDecrement; i++) { + executor.submit(() -> { +// workflow.reserve(new ConsumeSignal(1)); + }); + } + } + } +} -- GitLab