Skip to content

Commit 36f10c5

Browse files
Add Kotlin parallelize work example (#249)
* Add kotlin parallelize work example * Add Java run instructions for parallelize work example * Add kotlin parallelize work to readmes * Update kotlin/patterns-use-cases/src/main/kotlin/my/example/parallelizework/stubs.kt Co-authored-by: Francesco Guardiani <[email protected]> * Update kotlin/patterns-use-cases/src/main/kotlin/my/example/parallelizework/FanOutWorker.kt Co-authored-by: Francesco Guardiani <[email protected]> * Add comments --------- Co-authored-by: Francesco Guardiani <[email protected]>
1 parent cbabdab commit 36f10c5

File tree

6 files changed

+201
-2
lines changed

6 files changed

+201
-2
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Or have a look at the general catalog below:
5555
| Example Name | Languages |
5656
|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
5757
| <a id="durable-rpc">Durable RPC, Idempotency & Concurrency</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#durable-rpc-idempotency--concurrency) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#durable-rpc-idempotency--concurrency) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#durable-rpc-idempotency--concurrency) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#durable-rpc-idempotency--concurrency) |
58-
| <a id="message-queue">\(Delayed\) Message Queue</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/patterns-use-cases/README.md#delayed-message-queue) |
58+
| <a id="message-queue">\(Delayed\) Message Queue</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#delayed-message-queue) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/patterns-use-cases/README.md#delayed-message-queue) |
5959
| <a id="webhook-callbacks">Webhook Callbacks</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#webhook-callbacks) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#webhook-callbacks) |
6060
| <a id="database-interaction">Database Interaction Patterns</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#database-interaction-patterns) |
6161
| <a id="sync-to-async">Convert Sync Tasks to Async</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#convert-sync-tasks-to-async) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#convert-sync-tasks-to-async) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#convert-sync-tasks-to-async) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#convert-sync-tasks-to-async) |
@@ -64,7 +64,7 @@ Or have a look at the general catalog below:
6464
| <a id="stateful-actors">Stateful Actors and State Machines</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#stateful-actors-and-state-machines) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#stateful-actors-and-state-machines) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#stateful-actors-and-state-machines) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#stateful-actors-and-state-machines) |
6565
| <a id="payment-state-machines">Payment State Machines \(Advanced\)</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#payment-state-machines) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#payment-state-machines) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#payment-state-machines) |
6666
| <a id="scheduling-tasks">Scheduling Tasks</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#scheduling-tasks) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#scheduling-tasks) |
67-
| <a id="parallelizing-work">Parallelizing Work</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#parallelizing-work) |
67+
| <a id="parallelizing-work">Parallelizing Work</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#parallelizing-work) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/patterns-use-cases/README.md#parallelizing-work) |
6868
| <a id="transactional-event-processing">Transactional Event Processing</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#transactional-event-processing) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#transactional-event-processing) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#transactional-event-processing) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#transactional-event-processing) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/patterns-use-cases/README.md#transactional-event-processing) |
6969
| <a id="event-enrichment">Event Enrichment / Joins</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#event-enrichment--joins) [<img src="https://skillicons.dev/icons?i=go" width="24" height="24">](go/patterns-use-cases/README.md#event-enrichment--joins) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/patterns-use-cases/README.md#event-enrichment--joins) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/patterns-use-cases/README.md#event-enrichment--joins) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/patterns-use-cases/README.md#event-enrichment--joins) |
7070
| <a id="promise-as-a-service">Durable Promises as a Service</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/patterns-use-cases/README.md#durable-promises-as-a-service) |

java/patterns-use-cases/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,48 @@ It then splits the task into subtasks, executes them in parallel, and then gathe
387387
Restate guarantees and manages the execution of all the subtasks across failures.
388388
You can run this on FaaS infrastructure, like AWS Lambda, and it will scale automatically.
389389

390+
<details>
391+
<summary><strong>Running the example</strong></summary>
392+
393+
1. [Start the Restate Server](https://docs.restate.dev/develop/local_dev) in a separate shell: `restate-server`
394+
2. Start the service: `./gradlew -PmainClass=my.example.parallelizework.FanOutWorker run`
395+
3. Register the services (with `--force` to override the endpoint during **development**): `restate -y deployments register --force localhost:9080`
396+
397+
Send a request:
398+
```shell
399+
curl -X POST http://localhost:8080/FanOutWorker/run -H "Content-Type: application/json" -d '{"description": "get out of bed,shower,make coffee,have breakfast"}'
400+
```
401+
402+
Check in the logs how all tasks get spawned in parallel.
403+
404+
<details>
405+
<summary>View logs</summary>
406+
407+
```
408+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1eR9VE9c7xfz4SKB2eCJy86XGFTrGJKWMp] dev.restate.sdk.core.InvocationStateMachine - Start invocation
409+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1eR9VE9c7xfz4SKB2eCJy86XGFTrGJKWMp] my.example.parallelizework.utils.Utils - Started executing subtask: get out of bed
410+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_15hry2WSJRuS45Sunug6olrHpWpHUKs0Mx] dev.restate.sdk.core.InvocationStateMachine - Start invocation
411+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_15hry2WSJRuS45Sunug6olrHpWpHUKs0Mx] my.example.parallelizework.utils.Utils - Started executing subtask: make coffee
412+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1edYMhniRwzc0kU2LZXKqS0yc516iofpfP] dev.restate.sdk.core.InvocationStateMachine - Start invocation
413+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1edYMhniRwzc0kU2LZXKqS0yc516iofpfP] my.example.parallelizework.utils.Utils - Started executing subtask: shower
414+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1beEP283Rozk4vTmbUgorTdxrDaJkCwPkZ] dev.restate.sdk.core.InvocationStateMachine - Start invocation
415+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_1beEP283Rozk4vTmbUgorTdxrDaJkCwPkZ] my.example.parallelizework.utils.Utils - Started executing subtask: have breakfast
416+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_15hry2WSJRuS45Sunug6olrHpWpHUKs0Mx] my.example.parallelizework.utils.Utils - Execution subtask finished: make coffee
417+
2025-03-06 12:53:43 INFO [FanOutWorker/runSubtask][inv_15hry2WSJRuS45Sunug6olrHpWpHUKs0Mx] dev.restate.sdk.core.InvocationStateMachine - End invocation
418+
2025-03-06 12:53:46 INFO [FanOutWorker/runSubtask][inv_1eR9VE9c7xfz4SKB2eCJy86XGFTrGJKWMp] my.example.parallelizework.utils.Utils - Execution subtask finished: get out of bed
419+
2025-03-06 12:53:46 INFO [FanOutWorker/runSubtask][inv_1eR9VE9c7xfz4SKB2eCJy86XGFTrGJKWMp] dev.restate.sdk.core.InvocationStateMachine - End invocation
420+
2025-03-06 12:53:46 INFO [FanOutWorker/runSubtask][inv_1beEP283Rozk4vTmbUgorTdxrDaJkCwPkZ] my.example.parallelizework.utils.Utils - Execution subtask finished: have breakfast
421+
2025-03-06 12:53:46 INFO [FanOutWorker/runSubtask][inv_1beEP283Rozk4vTmbUgorTdxrDaJkCwPkZ] dev.restate.sdk.core.InvocationStateMachine - End invocation
422+
2025-03-06 12:53:52 INFO [FanOutWorker/runSubtask][inv_1edYMhniRwzc0kU2LZXKqS0yc516iofpfP] my.example.parallelizework.utils.Utils - Execution subtask finished: shower
423+
2025-03-06 12:53:52 INFO [FanOutWorker/runSubtask][inv_1edYMhniRwzc0kU2LZXKqS0yc516iofpfP] dev.restate.sdk.core.InvocationStateMachine - End invocation
424+
2025-03-06 12:53:52 INFO [FanOutWorker/run][inv_1eXFJRCIXMwr57UdPLLIRwARZFifnOusTL] my.example.parallelizework.utils.Utils - Aggregated result: get out of bed: DONE, shower: DONE, make coffee: DONE, have breakfast: DONE
425+
2025-03-06 12:53:52 INFO [FanOutWorker/run][inv_1eXFJRCIXMwr57UdPLLIRwARZFifnOusTL] dev.restate.sdk.core.InvocationStateMachine - End invocation
426+
```
427+
428+
</details>
429+
</details>
430+
431+
390432
## Payment Signals
391433
[<img src="https://raw.githubusercontent.com/restatedev/img/refs/heads/main/show-code.svg">](src/main/java/my/example/signalspayments/PaymentService.java)
392434

kotlin/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#### Orchestration patterns
1919
- **[Sagas](patterns-use-cases/README.md#sagas)**: Preserve consistency by tracking undo actions and running them when code fails halfway through. [<img src="https://raw.githubusercontent.com/restatedev/img/refs/heads/main/play-button.svg" width="16" height="16">](patterns-use-cases/src/main/kotlin/my/example/sagas/BookingWorkflow.kt)
2020

21+
#### Scheduling
22+
- **[Parallelizing Work](patterns-use-cases/README.md#parallelizing-work)**: Execute a list of tasks in parallel and then gather their result. [<img src="https://raw.githubusercontent.com/restatedev/img/refs/heads/main/play-button.svg" width="16" height="16">](patterns-use-cases/src/main/kotlin/my/example/parallelizework/FanOutWorker.kt)
23+
2124
#### Event processing
2225
- **[Transactional Event Processing](patterns-use-cases/README.md#transactional-event-processing)**: Processing events (from Kafka) to update various downstream systems in a transactional way. [<img src="https://raw.githubusercontent.com/restatedev/img/refs/heads/main/play-button.svg" width="16" height="16">](patterns-use-cases/src/main/kotlin/my/example/eventtransactions/UserFeed.kt)
2326
- **[Event Enrichment / Joins](patterns-use-cases/README.md#event-enrichment--joins)**: Stateful functions/actors connected to Kafka and callable over RPC. [<img src="https://raw.githubusercontent.com/restatedev/img/refs/heads/main/play-button.svg" width="16" height="16">](patterns-use-cases/src/main/kotlin/my/example/eventenrichment/PackageTracker.kt)

0 commit comments

Comments
 (0)