Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
428fc3f
Scaffold the Temporal Essentials Deck and its Java proof harness
nadvolod Nov 4, 2026
337a7b9
Add Temporal Essentials Java Deck wiring: CI, ADR 0004, README rows
nadvolod Nov 4, 2026
4afc45a
Port 17-saga segments to Java
nadvolod Nov 4, 2026
50b2244
Merge branch 'port-java-essentials-saga' into port-java-essentials-deck
nadvolod Nov 4, 2026
50ef066
Port 00-open, 01-why-temporal, 02-local-development, 03-temporal-conc…
nadvolod Nov 4, 2026
3f1fa90
Merge branch 'port-essentials-open-why-localdev-concepts' into port-j…
nadvolod Nov 4, 2026
1088535
Port 22-more-features and 23-timeouts-and-retries to Java
nadvolod Nov 4, 2026
1166e36
Merge branch 'port-essentials-22-23' into port-java-essentials-deck
nadvolod Nov 4, 2026
6823835
Port 07-workers, 07b-client, 08-start-vs-execute, 09-signals, 10-quer…
nadvolod Nov 4, 2026
663b6d4
Merge branch 'port-java-essentials-workers-quiz' into port-java-essen…
nadvolod Nov 4, 2026
51ee2b5
Port 14-child-workflows, 15-continue-as-new, 16-heartbeating and 17b-…
nadvolod Nov 4, 2026
b546e7d
Merge branch 'worktree-agent-a08e2545122e1cd0c' into port-java-essent…
nadvolod Nov 4, 2026
f072695
Port 18-versioning, 19-serialization, 20-encryption, 21-claim-check t…
nadvolod Nov 4, 2026
a9ce49d
Merge branch 'port-essentials-versioning-claimcheck' into port-java-e…
nadvolod Nov 4, 2026
6429185
Port 24-error-handling, 25-observability, 26-worker-tuning to Java
nadvolod Nov 4, 2026
0e9030c
Merge branch 'port-essentials-errors-observability-tuning' into port-…
nadvolod Nov 4, 2026
142b93f
Pin slf4j-api so the Deck's snippet logs reach slf4j-simple
nadvolod Nov 4, 2026
580363e
Port 04-design-patterns, 05-workflows, 06-activities and 06b-event-hi…
nadvolod Nov 4, 2026
30d9bb4
Merge branch 'port-essentials-patterns-workflows-activities-history' …
nadvolod Nov 4, 2026
31f3e8b
Fix the whole-Deck review findings in Temporal Essentials (Java)
nadvolod Nov 4, 2026
814c22e
Record the Temporal Essentials Deck's Authoring cost
nadvolod Nov 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
55 changes: 55 additions & 0 deletions .github/workflows/java-master-deck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: java-master Deck

# Temporal Essentials (decks/java-master): the code on every slide compiles,
# matches its snippet, parses, lights the lines its bubble talks about, and does
# what the speaker notes claim; then the rendered bubbles sit on those lines.
on:
pull_request:
paths: ["decks/java-master/**", ".github/workflows/java-master-deck.yml"]
push:
branches: [main]
paths: ["decks/java-master/**"]

# Read-only: both jobs only check out and test.
permissions:
contents: read

jobs:
snippets:
name: Code slides (compile, drift, parse, walkthrough steps, runtime)
runs-on: ubuntu-latest
defaults:
run:
working-directory: decks/java-master/snippets
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with:
distribution: temurin
java-version: "21"
cache: maven
cache-dependency-path: decks/java-master/snippets/pom.xml
- run: mvn -B -q test

walkthroughs:
name: Walkthrough bubbles sit on their lines (rendered)
runs-on: ubuntu-latest
defaults:
run:
working-directory: decks/java-master
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
cache: npm
cache-dependency-path: decks/java-master/package-lock.json
- run: npm ci
- run: npx playwright install --with-deps chromium
- name: Start the dev server
run: |
npx slidev --port 3030 > slidev.log 2>&1 &
npx --yes wait-on --timeout 120000 http://localhost:3030
- run: npm run check:walkthroughs
- if: failure()
run: cat slidev.log
11 changes: 11 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ _Avoid_: validation, verify
The Slidev presentation delivered alongside a Workshop.
_Avoid_: slides, presentation

**Segment**:
A self-contained section of a Deck, opening with its own divider, that other
Decks import whole.
_Avoid_: chapter, module, section

**Temporal Essentials**:
The Foundations Deck that holds every Segment, delivered end to end or drawn
from by Workshop Decks. A Deck with no Track, Exercise or Solution of its own,
so it is not a Workshop.
_Avoid_: master deck, the master, Essentials Workshop

**Exercise**:
The code tree a learner starts from, with the work left undone as numbered TODOs.
Core TODOs are required to finish; Stretch TODOs are optional extras for learners
Expand Down
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,19 @@ All created via code. Use or repurpose the content to fit your next Dev Day!

| Workshop | Level | Stack | Deck | Code + Track | Lab | Duration | Author | Model | Deck cost ($) | Track cost ($) |
|---|---|---|---|---|---|--:|---|---|--:|--:|
| The Saga Pattern | Advanced | Java · compensation | Pending | [`workshops/saga-order-fulfillment/`](workshops/saga-order-fulfillment/) | [`saga-java`](https://play.instruqt.com/temporal/tracks/saga-java) | 25 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 4.73 |
| Child Workflows | Foundations | Java · child workflows | Pending | [`workshops/child-workflows/`](workshops/child-workflows/) | [`child-workflows-java`](https://play.instruqt.com/temporal/tracks/child-workflows-java) | 15 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 3.98 |
| Continue-As-New | Advanced | Java · event history | Pending | [`workshops/continue-as-new-subscription/`](workshops/continue-as-new-subscription/) | [`continue-as-new-java`](https://play.instruqt.com/temporal/tracks/continue-as-new-java) | 10 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 2.86 |
| Activity Heartbeats | Advanced | Java · activities | Pending | [`workshops/heartbeats-shipment/`](workshops/heartbeats-shipment/) | [`heartbeats-java`](https://play.instruqt.com/temporal/tracks/heartbeats-java) | 10 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 4.45 |
| The Saga Pattern | Advanced | Java · compensation | [`segments/17-saga-*`](decks/java-master/segments/17-saga-01-overview.md) | [`workshops/saga-order-fulfillment/`](workshops/saga-order-fulfillment/) | [`saga-java`](https://play.instruqt.com/temporal/tracks/saga-java) | 25 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 4.73 |
| Child Workflows | Foundations | Java · child workflows | [`segments/14-child-workflows.md`](decks/java-master/segments/14-child-workflows.md) | [`workshops/child-workflows/`](workshops/child-workflows/) | [`child-workflows-java`](https://play.instruqt.com/temporal/tracks/child-workflows-java) | 15 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 3.98 |
| Continue-As-New | Advanced | Java · event history | [`segments/15-continue-as-new.md`](decks/java-master/segments/15-continue-as-new.md) | [`workshops/continue-as-new-subscription/`](workshops/continue-as-new-subscription/) | [`continue-as-new-java`](https://play.instruqt.com/temporal/tracks/continue-as-new-java) | 10 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 2.86 |
| Activity Heartbeats | Advanced | Java · activities | [`segments/16-heartbeating.md`](decks/java-master/segments/16-heartbeating.md) | [`workshops/heartbeats-shipment/`](workshops/heartbeats-shipment/) | [`heartbeats-java`](https://play.instruqt.com/temporal/tracks/heartbeats-java) | 10 min | Nikolay Advolodkin | Opus 5.5 (100%) | Pending | 4.45 |
| Temporal Essentials | Foundations | Java · Workflows, Activities, Workers, Clients, Signals, Queries, Updates, Sagas, versioning, timeouts and retries, observability | [`decks/java-master/`](decks/java-master/) | Deck only; code slides proven in [`snippets/`](decks/java-master/snippets/) | per section, linked in the Deck | Pending | Nikolay Advolodkin | Opus 5.5 (100%) | [112.15](docs/authoring/java-master-deck.md) | — |

**Temporal Essentials is a Deck, not a Workshop**: it has no Track, Exercise or
Solution of its own, so its Track cost is a dash. It is the Foundations Deck
delivered end to end, and the pool of Segments every Workshop's Deck imports
with `src:`; a Workshop's **Deck** column points at its Segment. See
[ADR 0004](docs/adr/0004-temporal-essentials-is-java-master-ported-from-typescript.md)
and [`snippets/README.md`](decks/java-master/snippets/README.md) for how its
code slides are proven.

A Workshop created for this program lives here, under `workshops/<slug>/` with
its Deck in `decks/<slug>/`. A Workshop that already has a Temporal-owned topic
Expand Down
11 changes: 11 additions & 0 deletions decks/java-master/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"plugins": ["prettier-plugin-slidev"],
"overrides": [
{
"files": ["slides.md", "segments/*.md"],
"options": {
"parser": "slidev"
}
}
]
}
119 changes: 119 additions & 0 deletions decks/java-master/components/ParentClosePolicy.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<!--
ABOUTME: One Parent Close Policy as a two-lane timeline: the parent starts a child,
ABOUTME: the parent closes, and the child's lane shows what that policy does to it.

<ParentClosePolicy policy="TERMINATE" />
<ParentClosePolicy policy="ABANDON" />
<ParentClosePolicy policy="REQUEST_CANCEL" />
-->
<script setup lang="ts">
import { computed } from 'vue'

type Policy = 'TERMINATE' | 'ABANDON' | 'REQUEST_CANCEL'
const props = defineProps<{ policy: Policy }>()

const COPY: Record<Policy, { tag?: string; caption: string }> = {
TERMINATE: { tag: 'default', caption: 'The child stops the moment the parent closes. No cleanup runs.' },
ABANDON: { caption: 'The child keeps running on its own, to completion.' },
REQUEST_CANCEL: { caption: 'The child is asked to cancel, runs its cleanup, then ends.' },
}
const copy = computed(() => COPY[props.policy])

// Shared geometry: the parent closes at CLOSE on both lanes.
const P = 38
const C = 98
const START = 64
const SPAWN = 104
const CLOSE = 178
</script>

<template>
<figure class="pcp" :class="policy.toLowerCase()">
<figcaption>
<code>{{ policy }}</code>
<span v-if="copy.tag" class="tag">{{ copy.tag }}</span>
</figcaption>

<svg viewBox="0 0 320 136" role="img" :aria-label="`${policy}: ${copy.caption}`">
<defs>
<marker :id="`pcp-head-${policy}`" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" fill="context-stroke" />
</marker>
</defs>

<text x="6" :y="P + 4" class="lane">Parent</text>
<text x="6" :y="C + 4" class="lane">Child</text>

<!-- Parent: runs, then closes. -->
<line :x1="START" :y1="P" :x2="CLOSE" :y2="P" class="parent" />
<circle :cx="START" :cy="P" r="4" class="parent-dot" />
<rect :x="CLOSE - 4" :y="P - 9" width="8" height="18" rx="1.5" class="close" />
<text :x="CLOSE" :y="P - 15" class="note" text-anchor="middle">parent closes</text>

<!-- The parent starts the child. -->
<line :x1="SPAWN" :y1="P + 4" :x2="SPAWN" :y2="C - 8" class="spawn" :marker-end="`url(#pcp-head-${policy})`" />
<circle :cx="SPAWN" :cy="C" r="4" class="child-dot" />

<template v-if="policy === 'TERMINATE'">
<line :x1="SPAWN" :y1="C" :x2="CLOSE" :y2="C" class="child" />
<line :x1="CLOSE" :y1="P + 9" :x2="CLOSE" :y2="C - 12" class="kill" />
<g class="x" :transform="`translate(${CLOSE} ${C})`">
<line x1="-7" y1="-7" x2="7" y2="7" />
<line x1="-7" y1="7" x2="7" y2="-7" />
</g>
<text :x="CLOSE" :y="C + 24" class="note bad" text-anchor="middle">terminated</text>
</template>

<template v-else-if="policy === 'ABANDON'">
<line :x1="SPAWN" :y1="C" :x2="308" :y2="C" class="child" :marker-end="`url(#pcp-head-${policy})`" />
<text x="250" :y="C + 24" class="note good" text-anchor="middle">keeps running</text>
</template>

<template v-else>
<line :x1="SPAWN" :y1="C" :x2="CLOSE" :y2="C" class="child" />
<line :x1="CLOSE" :y1="P + 9" :x2="CLOSE" :y2="C - 8" class="cancel" :marker-end="`url(#pcp-head-${policy})`" />
<text :x="CLOSE + 6" :y="(P + C) / 2 + 4" class="note warn">cancel request</text>
<line :x1="CLOSE" :y1="C" :x2="248" :y2="C" class="cleanup" />
<circle cx="248" :cy="C" r="5" class="end" />
<text :x="213" :y="C + 24" class="note warn" text-anchor="middle">cleanup, then cancelled</text>
</template>
</svg>

<p>{{ copy.caption }}</p>
</figure>
</template>

<style scoped>
.pcp {
margin: 0; padding: 0.7rem 0.8rem 0.8rem; border-radius: 0.6rem;
border: 1px solid var(--temporal-border); background: var(--temporal-bg-elev);
display: flex; flex-direction: column; gap: 0.4rem; min-width: 0;
}
figcaption { display: flex; align-items: center; gap: 0.5rem; }
figcaption code { font-size: 0.95rem !important; color: var(--temporal-text-strong); }
.tag {
font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.08em; padding: 0.05rem 0.45rem;
border-radius: 999px; border: 1px solid var(--temporal-border-hi); color: var(--temporal-text-muted);
}
svg { width: 100%; height: auto; overflow: visible; }
p { margin: 0; font-size: 0.78rem; line-height: 1.4; color: var(--temporal-text); }

.lane { font-size: 11px; fill: var(--temporal-text-muted); font-weight: 600; }
.note { font-size: 10.5px; fill: var(--temporal-text-muted); }
.note.bad { fill: #f9a8d4; }
.note.good { fill: var(--temporal-green); }
.note.warn { fill: var(--temporal-yellow); }

line { stroke-width: 3; stroke-linecap: round; }
.parent { stroke: var(--temporal-lavender); }
.parent-dot { fill: var(--temporal-lavender); }
.close { fill: var(--temporal-text-strong); }
.spawn { stroke: var(--temporal-lavender); stroke-width: 1.5; stroke-dasharray: 3 3; }
.child { stroke: var(--temporal-cyan); }
.child-dot { fill: var(--temporal-cyan); }
.kill { stroke: #f472b6; stroke-width: 1.5; stroke-dasharray: 3 3; }
.x line { stroke: #f472b6; stroke-width: 3; }
.cancel { stroke: var(--temporal-yellow); stroke-width: 1.5; stroke-dasharray: 3 3; }
.cleanup { stroke: var(--temporal-yellow); }
.end { fill: none; stroke: var(--temporal-yellow); stroke-width: 2.5; }
</style>
Loading
Loading