Skip to content

Commit b81623d

Browse files
authored
Merge pull request #1 from temporalio/init
1 parent 9c68bf8 commit b81623d

219 files changed

Lines changed: 9884 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# This repository is maintained by the Temporal Education team
2+
* @temporalio/education @masonegger

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
tmp/*
12
# Byte-compiled / optimized / DLL files
23
__pycache__/
34
*.py[codz]
@@ -216,3 +217,22 @@ __marimo__/
216217

217218
# Streamlit
218219
.streamlit/secrets.toml
220+
221+
# Java
222+
target/
223+
*.class
224+
*.jar
225+
.idea/
226+
.classpath
227+
.project
228+
.settings/
229+
230+
# Editor / OS
231+
.DS_Store
232+
.vscode/
233+
*.swp
234+
*.swo
235+
236+
# Workshop scratch
237+
commit-msg.md
238+

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.14

CLAUDE.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What this repo is
6+
7+
Code companion for the **Introduction to Temporal Nexus** workshop (Replay 2026). The companion repo
8+
[`workshop-nexus-intro`](https://github.com/temporalio/workshop-nexus-intro) holds the slides, Instruqt
9+
lab, and course plan; this repo holds only the per-chapter source the attendees run on their laptops.
10+
11+
There is no test suite, no CI, and no library code to ship. The "product" is the per-chapter Python
12+
snapshots under `exercises/` and the Java polyglot demo under `polyglot/java-legacy/`. Edits should
13+
preserve the pedagogical progression chapter-to-chapter.
14+
15+
## Common commands
16+
17+
One-time setup from the repo root:
18+
19+
```bash
20+
uv sync # creates the single root .venv all chapters share
21+
temporal server start-dev # dev server at localhost:7233, UI at localhost:8233
22+
```
23+
24+
Per-chapter runtime (from inside `exercises/<chapter>/exercise/` or `exercises/<chapter>/solution/`):
25+
26+
```bash
27+
# Ch 1 only — monolith, single worker, default namespace
28+
uv run python -m payments.worker
29+
uv run python -m payments.starter
30+
31+
# Ch 3–7 — split workers, two namespaces
32+
uv run python -m compliance.worker # terminal 1
33+
uv run python -m payments.worker # terminal 2
34+
uv run python -m payments.starter # terminal 3
35+
36+
# Ch 6 only — submit a human review for the MEDIUM-risk TXN-B
37+
uv run python -m payments.review_starter
38+
39+
# Ch 7 only — exercise non-retryable, retryable, cancellation, and circuit-breaker paths
40+
uv run python -m payments.lifecycle_starter
41+
```
42+
43+
`uv run` walks up to the root `pyproject.toml` and uses the root `.venv`; the chapter's local
44+
`payments/`, `compliance/`, and `shared/` packages get picked up because the working directory is on
45+
`sys.path`. **Always run from inside a chapter directory** — running from the repo root fails with
46+
import errors.
47+
48+
Ch 2 is setup-only. The namespaces and Nexus endpoint are created interactively with `temporal operator`
49+
in that chapter and persist for every later chapter:
50+
51+
```bash
52+
temporal operator namespace create --namespace payments-namespace
53+
temporal operator namespace create --namespace compliance-namespace
54+
temporal operator nexus endpoint create \
55+
--name compliance-endpoint \
56+
--target-namespace compliance-namespace \
57+
--target-task-queue compliance-risk \
58+
--description-file compliance-endpoint.md
59+
```
60+
61+
Java polyglot (from `polyglot/java-legacy/`):
62+
63+
```bash
64+
mvn compile
65+
mvn -q exec:java
66+
```
67+
68+
## Architecture
69+
70+
### The Nexus contract
71+
72+
`shared/service.py` declares a single `@nexusrpc.service` class — `ComplianceNexusService` — with two
73+
operations: `check_compliance` and `submit_review`. This file is the *only* code-level contact point
74+
between the Payments and Compliance teams from Ch 2 onward. Payments imports it to build a Nexus
75+
client (`workflow.create_nexus_client(service=..., endpoint="compliance-endpoint")`); Compliance
76+
imports it to register a `@nexusrpc.handler.service_handler(service=...)` on its worker.
77+
78+
The matching server-side artifact is a Nexus Endpoint named `compliance-endpoint`, registered against
79+
`compliance-namespace` / `compliance-risk` task queue. Endpoints live at the cluster level, not inside
80+
a namespace — that is what lets them bridge teams.
81+
82+
### Two-team / two-namespace topology (Ch 3 onward)
83+
84+
```mermaid
85+
flowchart LR
86+
subgraph PNS[payments-namespace]
87+
PW[Payments worker<br/>task queue: payments-processing]
88+
PWF[PaymentProcessingWorkflow]
89+
PW -.- PWF
90+
end
91+
subgraph EP[compliance-endpoint]
92+
direction LR
93+
end
94+
subgraph CNS[compliance-namespace]
95+
CW[Compliance worker<br/>task queue: compliance-risk]
96+
CWF[ComplianceWorkflow]
97+
CSH[ComplianceNexusServiceHandler]
98+
CW -.- CWF
99+
CW -.- CSH
100+
end
101+
PWF -- "Nexus call<br/>check_compliance" --> EP --> CSH
102+
```
103+
104+
- `payments-namespace` runs the Payments worker on the `payments-processing` task queue.
105+
- `compliance-namespace` runs the Compliance worker on the `compliance-risk` task queue.
106+
- The Payments workflow calls into Compliance only via `compliance-endpoint`. There is no shared task
107+
queue, no shared workflow registry, no Python import from one team's worker into the other's.
108+
109+
### Chapter progression
110+
111+
Each chapter is a complete, self-contained snapshot — never delta-style edits over a prior chapter at
112+
runtime. The deltas exist only in attendee-facing TODOs.
113+
114+
| Ch | Theme | Compliance handler shape |
115+
| -- | ------------------------ | ----------------------------------------------------- |
116+
| 1 | Monolith | `check_compliance` is a Payments-side activity |
117+
| 2 | Service contract | (no workers; contract + endpoint only) |
118+
| 3 | Sync handler | `@nexusrpc.handler.sync_operation` |
119+
| 4 | Caller swap | same as Ch 3 (caller workflow now uses Nexus) |
120+
| 5 | Async / workflow-backed | `@nexus.workflow_run_operation``ComplianceWorkflow`|
121+
| 6 | Updates | adds `@workflow.update review` + real `submit_review` |
122+
| 7 | Lifecycle / errors | adds failure-injection branches + `lifecycle_starter` |
123+
124+
### `exercise/` vs `solution/`
125+
126+
- Ch 1 ships only `solution/` (no TODOs).
127+
- Ch 2–4 `exercise/` is the **previous chapter's `solution/` plus new TODO callouts**.
128+
- Ch 5–7 `exercise/` may also include skeleton files — e.g. an empty `compliance/workflows.py`
129+
that raises `NotImplementedError` — that the chapter's TODOs ask the attendee to fill in.
130+
- TODO numbering is monotonically increasing across the whole workshop (Ch 7's TODO is `TODO 13`).
131+
When editing TODOs, keep them aligned with `assignment.md` in the companion content repo and the
132+
authoring standard. Numbering must not collide across chapters.
133+
134+
When changing one chapter's `solution/`, propagate the change forward into every later chapter's
135+
`exercise/` and `solution/` that ships the same file. The chapters drift if you don't.
136+
137+
### Workflow IDs are chapter-prefixed
138+
139+
Workflow IDs in starters and handlers include the chapter number — e.g. `payment-ch05-TXN-A`,
140+
`compliance-ch05-TXN-A`. This was added deliberately so attendees can re-run earlier chapters
141+
without `WorkflowAlreadyStartedError` / cross-chapter Event History contamination. **When adding a
142+
new starter or workflow ID, keep the `ch{NN}` prefix.** The exception is `review_starter.py`, which
143+
appends a fresh `uuid.uuid4()` to its caller-side `ReviewCallerWorkflow` ID so reviewers can re-submit
144+
freely; the long-running `compliance-chNN-{transaction_id}` it targets keeps the stable business ID.
145+
146+
### Polyglot Java worker
147+
148+
`polyglot/java-legacy/` is a **drop-in replacement for the Python compliance worker, behavior-equivalent
149+
to Ch 6**. It targets `compliance-namespace` / `compliance-risk` and serves the same
150+
`ComplianceNexusService` contract over the wire.
151+
152+
- Run it against the Ch 5, 6, or **7 (preferred)** Python payments side. The Ch 7 caller has the
153+
timeouts and `ReviewCallerWorkflow` registered, but the Java handler does **not** implement Ch 7's
154+
failure-injection branches (`TXN-FAIL-*`, `TXN-CIRCUIT-*`), so use `payments.starter`, not
155+
`payments.lifecycle_starter`.
156+
- The Python and Java compliance workers cannot run simultaneously — they poll the same task queue
157+
and workflow histories from different SDKs are not interchangeable. Stop the Python worker first.
158+
- The Java side carries the polyglot tax: `@Operation(name = "check_compliance")` and `@JsonProperty`
159+
annotations on every field/getter/constructor argument force snake_case wire-compat with the Python
160+
contract. Don't "clean up" these annotations; without them deserialization breaks across the wire.
161+
162+
## Authoring conventions
163+
164+
- **Python target**: 3.14+. `temporalio>=1.24.0`, `nexus-rpc>=1.1.0,<2`. No other deps.
165+
- **Imports inside `@workflow.defn` files**: wrap non-stdlib / non-Temporal imports in
166+
`with workflow.unsafe.imports_passed_through():` (see any chapter's `payments/workflows.py`). The
167+
Nexus client construction (`workflow.create_nexus_client(...)`) lives in the workflow body, not at
168+
module scope.
169+
- **`USE_EXISTING` on workflow-backed Nexus operations**: `check_compliance` starts the backing
170+
workflow with `id_conflict_policy=WorkflowIDConflictPolicy.USE_EXISTING` so a Nexus retry returns a
171+
handle to the running workflow instead of failing with `WorkflowAlreadyStartedError`. Preserve this.
172+
- **Three timeouts on the Nexus call** in `payments/workflows.py` from Ch 5 on:
173+
`schedule_to_close_timeout`, `schedule_to_start_timeout`, `start_to_close_timeout`. The chapter
174+
prose explains each — keep all three when editing.
175+
- **Markdown diagrams**: never ASCII art. Always Mermaid in fenced ```` ```mermaid ```` blocks
176+
(per the user's global markdown rule).
177+
178+
## Notes for editing
179+
180+
- `commit-msg.md` is gitignored — never stage it.
181+
- `tmp/` at the repo root is scratch / gitignored.
182+
- `.venv/` is the single shared environment created by `uv sync` at the root; never create per-chapter
183+
venvs.
184+
- Keep `compliance-endpoint.md` (the Markdown description attached to the Nexus Endpoint) in sync with
185+
whatever the contract advertises. It is the only Nexus artifact attendees see in the Web UI.

0 commit comments

Comments
 (0)