From 3e17c8e674da741bc2fce690673260ada7a99246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Ortola?= <contact@loicortola.com> Date: Fri, 16 May 2025 16:21:23 +0200 Subject: [PATCH] feat: improved boilerplate and added solution for part-1 --- .../bakery/MakeCookiesApp.java | 8 ++++ .../bakery/OrderCookiesApp.java | 21 +++++++++++ .../bakery/kitchen/KitchenWorker.java | 29 +++++++++++++++ .../bakery/kitchen/KitchenWorkflow.java | 10 +++++ .../bakery/kitchen/KitchenWorkflowImpl.java | 9 +++++ .../bakery/kitchen/bake/BakeService.java | 5 +++ .../bakery/kitchen/batter/BatterService.java | 5 +++ .../signals/ConsumeSignal.java | 4 ++ .../signals/InventoryActivity.java | 7 ++++ .../signals/InventoryActivityImpl.java | 26 +++++++++++++ .../signals/InventoryWorkflow.java | 10 +++++ .../temporalpractice/signals/MSMain.java | 37 +++++++++++++++++++ .../bakery/MakeCookiesApp.java | 1 + .../bakery/OrderCookiesApp.java | 2 + 14 files changed, 174 insertions(+) create mode 100644 solutions/day1/part-1/temporalpractice/bakery/MakeCookiesApp.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/OrderCookiesApp.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflow.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/kitchen/bake/BakeService.java create mode 100644 solutions/day1/part-1/temporalpractice/bakery/kitchen/batter/BatterService.java create mode 100644 solutions/day1/part-1/temporalpractice/signals/ConsumeSignal.java create mode 100644 solutions/day1/part-1/temporalpractice/signals/InventoryActivity.java create mode 100644 solutions/day1/part-1/temporalpractice/signals/InventoryActivityImpl.java create mode 100644 solutions/day1/part-1/temporalpractice/signals/InventoryWorkflow.java create mode 100644 solutions/day1/part-1/temporalpractice/signals/MSMain.java diff --git a/solutions/day1/part-1/temporalpractice/bakery/MakeCookiesApp.java b/solutions/day1/part-1/temporalpractice/bakery/MakeCookiesApp.java new file mode 100644 index 0000000..d0c3871 --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/MakeCookiesApp.java @@ -0,0 +1,8 @@ +package io.takima.temporalpractice.bakery; + +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-1/temporalpractice/bakery/OrderCookiesApp.java b/solutions/day1/part-1/temporalpractice/bakery/OrderCookiesApp.java new file mode 100644 index 0000000..ccb16fb --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/OrderCookiesApp.java @@ -0,0 +1,21 @@ +package io.takima.temporalpractice.bakery; + +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-1/temporalpractice/bakery/kitchen/KitchenWorker.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java new file mode 100644 index 0000000..b61e118 --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorker.java @@ -0,0 +1,29 @@ +package io.takima.temporalpractice.bakery.kitchen; + +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); + + WorkflowOptions options = WorkflowOptions.newBuilder() + .setTaskQueue("TheOneAndOnlyQueue") + .setWorkflowId("best-cookie") + .build(); + + WorkerFactory factory = WorkerFactory.newInstance(client); + + Worker worker = factory.newWorker("TheOneAndOnlyQueue"); + + worker.registerWorkflowImplementationTypes(KitchenWorkflowImpl.class); + + factory.start(); + } +} diff --git a/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflow.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflow.java new file mode 100644 index 0000000..bec377d --- /dev/null +++ b/solutions/day1/part-1/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-1/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java new file mode 100644 index 0000000..445fb39 --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/kitchen/KitchenWorkflowImpl.java @@ -0,0 +1,9 @@ +package io.takima.temporalpractice.bakery.kitchen; + +public class KitchenWorkflowImpl implements KitchenWorkflow { + @Override + public void makeCookies() { + System.out.println("I'm making cookies"); + System.out.println("Cookies are done!"); + } +} diff --git a/solutions/day1/part-1/temporalpractice/bakery/kitchen/bake/BakeService.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/bake/BakeService.java new file mode 100644 index 0000000..50b3b72 --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/kitchen/bake/BakeService.java @@ -0,0 +1,5 @@ +package io.takima.temporalpractice.bakery.kitchen.bake; + +public interface BakeService { + void bake(); +} diff --git a/solutions/day1/part-1/temporalpractice/bakery/kitchen/batter/BatterService.java b/solutions/day1/part-1/temporalpractice/bakery/kitchen/batter/BatterService.java new file mode 100644 index 0000000..ce25b12 --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/bakery/kitchen/batter/BatterService.java @@ -0,0 +1,5 @@ +package io.takima.temporalpractice.bakery.kitchen.batter; + +public interface BatterService { + void prepareBatter(); +} diff --git a/solutions/day1/part-1/temporalpractice/signals/ConsumeSignal.java b/solutions/day1/part-1/temporalpractice/signals/ConsumeSignal.java new file mode 100644 index 0000000..ea74daf --- /dev/null +++ b/solutions/day1/part-1/temporalpractice/signals/ConsumeSignal.java @@ -0,0 +1,4 @@ +package io.takima.temporalpractice.signals; + +public record ConsumeSignal(int amount) { +} diff --git a/solutions/day1/part-1/temporalpractice/signals/InventoryActivity.java b/solutions/day1/part-1/temporalpractice/signals/InventoryActivity.java new file mode 100644 index 0000000..1645c76 --- /dev/null +++ b/solutions/day1/part-1/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-1/temporalpractice/signals/InventoryActivityImpl.java b/solutions/day1/part-1/temporalpractice/signals/InventoryActivityImpl.java new file mode 100644 index 0000000..db1105d --- /dev/null +++ b/solutions/day1/part-1/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-1/temporalpractice/signals/InventoryWorkflow.java b/solutions/day1/part-1/temporalpractice/signals/InventoryWorkflow.java new file mode 100644 index 0000000..f7cfebd --- /dev/null +++ b/solutions/day1/part-1/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-1/temporalpractice/signals/MSMain.java b/solutions/day1/part-1/temporalpractice/signals/MSMain.java new file mode 100644 index 0000000..61cdb4a --- /dev/null +++ b/solutions/day1/part-1/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)); + }); + } + } + } +} diff --git a/src/main/java/io/takima/temporalpractice/bakery/MakeCookiesApp.java b/src/main/java/io/takima/temporalpractice/bakery/MakeCookiesApp.java index e7c4d63..059f9d6 100644 --- a/src/main/java/io/takima/temporalpractice/bakery/MakeCookiesApp.java +++ b/src/main/java/io/takima/temporalpractice/bakery/MakeCookiesApp.java @@ -2,5 +2,6 @@ package io.takima.temporalpractice.bakery; public class MakeCookiesApp { public static void main(String[] args) { + // This app should execute the making of all cookies ordered } } diff --git a/src/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java b/src/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java index 9fb1fc1..c7bf115 100644 --- a/src/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java +++ b/src/main/java/io/takima/temporalpractice/bakery/OrderCookiesApp.java @@ -2,5 +2,7 @@ package io.takima.temporalpractice.bakery; public class OrderCookiesApp { public static void main(String[] args) { + // This app simulates an order of cookies + // It should call the workflow which makes cookies } } -- GitLab