Skip to content

Commit 26b4362

Browse files
Merge pull request #73 from temporalio/dev
Release 0.2.0
2 parents 3d4ea71 + 25eb553 commit 26b4362

24 files changed

Lines changed: 2348 additions & 39 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Appropriately adjust the installation directory based on your coding agent.
3636
- [x] Python ✅
3737
- [x] TypeScript ✅
3838
- [x] Go ✅
39-
- [ ] Java 🚧 ([PR](https://github.com/temporalio/skill-temporal-developer/pull/42))
39+
- [x] Java
4040
- [ ] .NET 🚧 ([PR](https://github.com/temporalio/skill-temporal-developer/pull/39))
4141
- [ ] Ruby 🚧 ([PR](https://github.com/temporalio/skill-temporal-developer/pull/41))
4242
- [ ] PHP 🚧 ([PR](https://github.com/temporalio/skill-temporal-developer/pull/40))

SKILL.md

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,29 @@
11
---
22
name: temporal-developer
3-
description: This skill should be used when the user asks to "create a Temporal workflow", "write a Temporal activity", "debug stuck workflow", "fix non-determinism error", "Temporal Python", "Temporal TypeScript", "Temporal Go", "Temporal Golang", "workflow replay", "activity timeout", "signal workflow", "query workflow", "worker not starting", "activity keeps retrying", "Temporal heartbeat", "continue-as-new", "child workflow", "saga pattern", "workflow versioning", "durable execution", "reliable distributed systems", or mentions Temporal SDK development.
4-
version: 0.1.0
3+
description: This skill should be used when the user asks to "create a Temporal workflow", "write a Temporal activity", "debug stuck workflow", "fix non-determinism error", "Temporal Python", "Temporal TypeScript", "Temporal Go", "Temporal Golang", "Temporal Java", "workflow replay", "activity timeout", "signal workflow", "query workflow", "worker not starting", "activity keeps retrying", "Temporal heartbeat", "continue-as-new", "child workflow", "saga pattern", "workflow versioning", "durable execution", "reliable distributed systems", or mentions Temporal SDK development.
4+
version: 0.2.0
55
---
66

77
# Skill: temporal-developer
88

99
## Overview
1010

11-
Temporal is a durable execution platform that makes workflows survive failures automatically. This skill provides guidance for building Temporal applications in Python, TypeScript, and Go.
11+
Temporal is a durable execution platform that makes workflows survive failures automatically. This skill provides guidance for building Temporal applications in Python, TypeScript, Go, and Java.
1212

1313
## Core Architecture
1414

15-
```
16-
┌─────────────────────────────────────────────────────────────────┐
17-
│ Temporal Cluster │
18-
│ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │
19-
│ │ Event History │ │ Task Queues │ │ Visibility │ │
20-
│ │ (Durable Log) │ │ (Work Router) │ │ (Search) │ │
21-
│ └─────────────────┘ └─────────────────┘ └────────────────┘ │
22-
└─────────────────────────────────────────────────────────────────┘
23-
24-
│ Poll / Complete
25-
26-
┌─────────────────────────────────────────────────────────────────┐
27-
│ Worker │
28-
│ ┌─────────────────────────┐ ┌──────────────────────────────┐ │
29-
│ │ Workflow Definitions │ │ Activity Implementations │ │
30-
│ │ (Deterministic) │ │ (Non-deterministic OK) │ │
31-
│ └─────────────────────────┘ └──────────────────────────────┘ │
32-
└─────────────────────────────────────────────────────────────────┘
33-
```
15+
The **Temporal Cluster** is the central orchestration backend. It maintains three key subsystems: the **Event History** (a durable log of all workflow state), **Task Queues** (which route work to the right workers), and a **Visibility** store (for searching and listing workflows). There are three ways to run a Cluster:
16+
17+
- **Temporal CLI dev server** — a local, single-process server started with `temporal server start-dev`. Suitable for development and testing only, not production.
18+
- **Self-hosted** — you deploy and manage the Temporal server and its dependencies (e.g., database) in your own infrastructure for production use.
19+
- **Temporal Cloud** — a fully managed production service operated by Temporal. No cluster infrastructure to manage.
20+
21+
**Workers** are long-running processes that you run and manage. They poll Task Queues for work and execute your code. You might run a single Worker process on one machine during development, or run many Worker processes across a large fleet of machines in production. Each Worker hosts two types of code:
22+
23+
- **Workflow Definitions** — durable, deterministic functions that orchestrate work. These must not have side effects.
24+
- **Activity Implementations** — non-deterministic operations (API calls, file I/O, etc.) that can fail and be retried.
3425

35-
**Components:**
36-
- **Workflows** - Durable, deterministic functions that orchestrate activities
37-
- **Activities** - Non-deterministic operations (API calls, I/O) that can fail and retry
38-
- **Workers** - Long-running processes that poll task queues and execute code
39-
- **Task Queues** - Named queues connecting clients to workers
26+
Workers communicate with the Cluster via a poll/complete loop: they poll a Task Queue for tasks, execute the corresponding Workflow or Activity code, and report results back.
4027

4128
## History Replay: Why Determinism Matters
4229

@@ -92,6 +79,7 @@ Once you've downloaded the file, extract the downloaded archive and add the temp
9279
1. First, read the getting started guide for the language you are working in:
9380
- Python -> read `references/python/python.md`
9481
- TypeScript -> read `references/typescript/typescript.md`
82+
- Java -> read `references/java/java.md`
9583
- Go -> read `references/go/go.md`
9684
2. Second, read appropriate `core` and language-specific references for the task at hand.
9785

references/core/determinism.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ In Temporal, activities are the primary mechanism for making non-deterministic c
7676
For a few simple cases, like timestamps, random values, UUIDs, etc. the Temporal SDK in your language may provide durable variants that are simple to use. See `references/{your_language}/determinism.md` for the language you are working in for more info.
7777

7878
## SDK Protection Mechanisms
79-
Each Temporal SDK language provides a protection mechanism to make it easier to catch non-determinism errors earlier in development:
79+
Each Temporal SDK language provides a different level of protection against non-determinism:
8080

8181
- Python: The Python SDK runs workflows in a sandbox that intercepts and aborts non-deterministic calls early at runtime.
8282
- TypeScript: The TypeScript SDK runs workflows in an isolated V8 sandbox, intercepting many common sources of non-determinism and replacing them automatically with deterministic variants.
83+
- Java: The Java SDK has no sandbox. Determinism is enforced by developer conventions — the SDK provides `Workflow.*` APIs as safe alternatives (e.g., `Workflow.sleep()` instead of `Thread.sleep()`), and non-determinism is only detected at replay time via `NonDeterministicException`. A static analysis tool (`temporal-workflowcheck`, beta) can catch violations at build time. Cooperative threading under a global lock eliminates the need for synchronization.
8384
- Go: The Go SDK has no runtime sandbox. Therefore, non-determinism bugs will never be immediately appararent, and are usually only observable during replay. The optional `workflowcheck` static analysis tool can be used to check for many sources of non-determinism at compile time.
8485

8586
Regardless of which SDK you are using, it is your responsibility to ensure that workflow code does not contain sources of non-determinism. Use SDK-specific tools as well as replay tests for doing so.

references/core/error-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Common Error Types Reference
22

3-
| Error Type | Error identifier (if any) | Where to Find | What Happened | Recovery | Link to additional info (if any)
3+
| Error Type | Error identifier (if any) | Where to Find | What Happened | Recovery | Link to additional info (if any) |
44
|------------|---------------|---------------|---------------|----------|----------|
55
| **Non-determinism** | TMPRL1100 | `WorkflowTaskFailed` in history | Replay doesn't match history | Analyze error first. **If accidental**: fix code to match history → restart worker. **If intentional v2 change**: terminate → start fresh workflow. | https://github.com/temporalio/rules/blob/main/rules/TMPRL1100.md |
66
| **Deadlock** | TMPRL1101 | `WorkflowTaskFailed` in history, worker logs | Workflow blocked too long (deadlock detected) | Remove blocking operations from workflow code (no I/O, no sleep, no threading locks). Use Temporal primitives instead. | https://github.com/temporalio/rules/blob/main/rules/TMPRL1101.md |

references/core/patterns.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ To ensure that polling_activity is restarted in a timely manner, we make sure th
253253

254254
**Implementation**:
255255

256-
Define an Activty which fails (raises an exception) exactly when polling is not completed.
256+
Define an Activity which fails (raises an exception) exactly when polling is not completed.
257257

258-
The polling loop is accomplised via activity retries, by setting the following Retry options:
258+
The polling loop is accomplished via activity retries, by setting the following Retry options:
259259
- backoff_coefficient: to 1
260260
- initial_interval: to the polling interval (e.g. 60 seconds)
261261

references/core/troubleshooting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ Timeout error?
192192
├─▶ Which timeout?
193193
│ │
194194
│ ├─▶ Workflow timeout
195-
│ │ └─▶ Increase timeout or optimize workflow. Better yet, consider removing the workflow timeout, as it is generally discourged unless *necessary* for your use case.
195+
│ │ └─▶ Increase timeout or optimize workflow. Better yet, consider removing the workflow timeout, as it is generally discouraged unless *necessary* for your use case.
196196
│ │
197197
│ ├─▶ ScheduleToCloseTimeout
198198
│ │ └─▶ Activity taking too long overall (including retries)

references/go/determinism-protection.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
The Go SDK has no runtime sandbox. Determinism is enforced by **developer convention** and **optional static analysis**. Unlike the Python and TypeScript SDKs, the Go SDK will not intercept or replace non-deterministic calls at runtime. The Go SDK does perform a limited runtime command-ordering check, but catching non-deterministic code before deployment requires the `workflowcheck` tool and testing, in particular replay tests (see `references/go/testing`).
5+
The Go SDK has no runtime sandbox (only Python and TypeScript have sandboxing). Determinism is enforced by **developer convention** and **optional static analysis**. The Go SDK will not intercept or replace non-deterministic calls at runtime. The Go SDK does perform a limited runtime command-ordering check, but catching non-deterministic code before deployment requires the `workflowcheck` tool and testing, in particular replay tests (see `references/go/testing.md`).
66

77
## workflowcheck Static Analysis
88

references/go/go.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
The Temporal Go SDK (`go.temporal.io/sdk`) provides a strongly-typed, idiomatic Go approach to building durable workflows. Workflows are regular exported Go functions. The Go SDK does not have an automatic sandbox -- determinism is the developer's responsibility, aided by the `workflowcheck` static analysis tool.
5+
The Temporal Go SDK (`go.temporal.io/sdk`) provides a strongly-typed, idiomatic Go approach to building durable workflows. Workflows are regular exported Go functions.
66

77
## Quick Start
88

@@ -239,4 +239,4 @@ See `references/go/testing.md` for info on writing tests.
239239
- **`references/go/advanced-features.md`** - Schedules, worker tuning, and more
240240
- **`references/go/data-handling.md`** - Data converters, payload codecs, encryption
241241
- **`references/go/versioning.md`** - Patching API (`workflow.GetVersion`), Worker Versioning
242-
- **`references/python/determinism-protection.md`** - Information on **`workflowcheck`** tool to help statically check for determinism issues.
242+
- **`references/go/determinism-protection.md`** - Information on **`workflowcheck`** tool to help statically check for determinism issues.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Java SDK Advanced Features
2+
3+
## Schedules
4+
5+
Create recurring workflow executions.
6+
7+
```java
8+
import io.temporal.client.schedules.*;
9+
10+
ScheduleClient scheduleClient = ScheduleClient.newInstance(service);
11+
12+
// Create a schedule
13+
String scheduleId = "daily-report";
14+
ScheduleHandle handle = scheduleClient.createSchedule(
15+
scheduleId,
16+
Schedule.newBuilder()
17+
.setAction(
18+
ScheduleActionStartWorkflow.newBuilder()
19+
.setWorkflowType(DailyReportWorkflow.class)
20+
.setOptions(
21+
WorkflowOptions.newBuilder()
22+
.setWorkflowId("daily-report")
23+
.setTaskQueue("reports")
24+
.build()
25+
)
26+
.build()
27+
)
28+
.setSpec(
29+
ScheduleSpec.newBuilder()
30+
.setIntervals(
31+
List.of(new ScheduleIntervalSpec(Duration.ofDays(1)))
32+
)
33+
.build()
34+
)
35+
.build(),
36+
ScheduleOptions.newBuilder().build()
37+
);
38+
39+
// Manage schedules
40+
ScheduleHandle scheduleHandle = scheduleClient.getHandle(scheduleId);
41+
scheduleHandle.pause("Maintenance window");
42+
scheduleHandle.unpause();
43+
scheduleHandle.trigger(); // Run immediately
44+
scheduleHandle.delete();
45+
```
46+
47+
## Async Activity Completion
48+
49+
For activities that complete asynchronously (e.g., human tasks, external callbacks).
50+
If you configure a heartbeat timeout on this activity, the external completer is responsible for sending heartbeats via the async handle.
51+
52+
**Note:** If the external system can reliably Signal back with the result and doesn't need to Heartbeat or receive Cancellation, consider using **signals** instead.
53+
54+
```java
55+
public class ApprovalActivitiesImpl implements ApprovalActivities {
56+
@Override
57+
public String requestApproval(String requestId) {
58+
ActivityExecutionContext ctx = Activity.getExecutionContext();
59+
60+
// Get task token for async completion
61+
byte[] taskToken = ctx.getTaskToken();
62+
63+
// Store task token for later completion (e.g., in database)
64+
storeTaskToken(requestId, taskToken);
65+
66+
// Mark this activity as waiting for external completion
67+
ctx.doNotCompleteOnReturn();
68+
69+
return null; // Return value is ignored
70+
}
71+
}
72+
73+
// Later, complete the activity from another process
74+
public void completeApproval(String requestId, boolean approved) {
75+
WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();
76+
WorkflowClient client = WorkflowClient.newInstance(service);
77+
78+
ActivityCompletionClient completionClient = client.newActivityCompletionClient();
79+
80+
byte[] taskToken = getTaskToken(requestId);
81+
82+
if (approved) {
83+
completionClient.complete(taskToken, "approved");
84+
} else {
85+
completionClient.completeExceptionally(
86+
taskToken,
87+
new RuntimeException("Rejected")
88+
);
89+
}
90+
}
91+
```
92+
93+
## Worker Tuning
94+
95+
Configure worker performance settings.
96+
97+
```java
98+
WorkerOptions workerOptions = WorkerOptions.newBuilder()
99+
// Max concurrent workflow task executions (default: 200)
100+
.setMaxConcurrentWorkflowTaskExecutionSize(200)
101+
// Max concurrent activity executions (default: 200)
102+
.setMaxConcurrentActivityExecutionSize(200)
103+
// Max concurrent local activity executions (default: 200)
104+
.setMaxConcurrentLocalActivityExecutionSize(200)
105+
// Max workflow task pollers (default: 5)
106+
.setMaxConcurrentWorkflowTaskPollers(5)
107+
// Max activity task pollers (default: 5)
108+
.setMaxConcurrentActivityTaskPollers(5)
109+
.build();
110+
111+
WorkerFactory factory = WorkerFactory.newInstance(client);
112+
Worker worker = factory.newWorker("my-queue", workerOptions);
113+
worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);
114+
worker.registerActivitiesImplementations(new MyActivitiesImpl());
115+
factory.start();
116+
```
117+
118+
## Workflow Failure Exception Types
119+
120+
Control which exceptions cause workflow failures vs workflow task failures.
121+
122+
By default, only `ApplicationFailure` (and its subclasses) fail the workflow execution. All other exceptions fail the **workflow task**, causing the task to retry indefinitely until the code is fixed or the workflow is terminated.
123+
124+
### Per-Workflow Configuration
125+
126+
Use `WorkflowImplementationOptions` to specify which exception types should fail the workflow:
127+
128+
```java
129+
Worker worker = factory.newWorker("my-queue");
130+
worker.registerWorkflowImplementationTypes(
131+
WorkflowImplementationOptions.newBuilder()
132+
.setFailWorkflowExceptionTypes(
133+
IllegalArgumentException.class,
134+
CustomBusinessException.class
135+
)
136+
.build(),
137+
MyWorkflowImpl.class
138+
);
139+
```
140+
141+
With this configuration, `IllegalArgumentException` and `CustomBusinessException` thrown from the workflow will fail the workflow execution instead of just the workflow task.
142+
143+
### Worker-Level Configuration
144+
145+
Apply to all workflows registered on the worker:
146+
147+
```java
148+
WorkerFactoryOptions factoryOptions = WorkerFactoryOptions.newBuilder()
149+
.setWorkflowHostLocalTaskQueueScheduleToStartTimeout(Duration.ofSeconds(10))
150+
.build();
151+
WorkerFactory factory = WorkerFactory.newInstance(client, factoryOptions);
152+
153+
Worker worker = factory.newWorker("my-queue");
154+
// Register each workflow type with its own failure exception types
155+
worker.registerWorkflowImplementationTypes(
156+
WorkflowImplementationOptions.newBuilder()
157+
.setFailWorkflowExceptionTypes(
158+
IllegalArgumentException.class,
159+
CustomBusinessException.class
160+
)
161+
.build(),
162+
MyWorkflowImpl.class,
163+
AnotherWorkflowImpl.class
164+
);
165+
```
166+
167+
- **Tip for testing:** Set `setFailWorkflowExceptionTypes(Throwable.class)` so any unhandled exception fails the workflow immediately rather than retrying the workflow task forever. This surfaces bugs faster.

0 commit comments

Comments
 (0)