mirror of
https://github.com/temporalio/skill-temporal-developer.git
synced 2026-09-14 13:52:58 +08:00
44eba4e91c
* Add .NET reference files for temporal-developer skill Created 11 .NET reference files covering: dotnet.md (overview/quick start), patterns.md, determinism.md, determinism-protection.md, error-handling.md, testing.md, versioning.md, observability.md, data-handling.md, gotchas.md, and advanced-features.md. Follows Python/TypeScript patterns with .NET-specific content for Task determinism, CancellationToken, dependency injection, etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix .NET alignment issues from self-review - dotnet.md: Reduce Determinism Rules section to brief cross-reference (was duplicating determinism.md content) - patterns.md: Add ParentClosePolicy to Child Workflows example - gotchas.md: Add missing "Heartbeat Timeout Too Short" subsection - versioning.md: Add missing Key Concepts, Deployment Strategies, Query Filters, PINNED/AUTO_UPGRADE guidance, CLI examples - advanced-features.md: Add worker-level heading for exception types Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix .NET correctness issues from verification pass - patterns.md: Fix cancellation pattern to use official TemporalException.IsCanceledException(e) with detached CancellationTokenSource - advanced-features.md: Fix DI hosting example to use official AddHostedTemporalWorker(clientTargetHost:, clientNamespace:, taskQueue:) pattern Verified against official SDK README, API docs, and temporal-docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Update supported language references to include .NET - SKILL.md: Add "Temporal .NET" and "Temporal C#" trigger phrases, update overview to mention .NET, add .NET entry in getting started - core/determinism.md: Add .NET entry in SDK Protection Mechanisms Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Edits to advanced features * edits to determinism protection, and move the .editorconfig section * missed one * edit determinism.md * edit error-handling.md * edit gotchas.md * edit patterns.md * edit versioning.md * edit observability.md * fix metrics * self-review round 1 * minor correctness fixed * Update references/dotnet/patterns.md Co-authored-by: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> * address comments, clarify reference to earlier code snippet * clarify that operations are forbidden IN WORKFLOWS * cleanup workflow cancellation handling example * add task token retrieval comment * update .net requirements * Fix propagation of workflow cancellation --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com>
58 lines
3.4 KiB
Markdown
58 lines
3.4 KiB
Markdown
# Java SDK Determinism
|
|
|
|
## Overview
|
|
|
|
The Java SDK has **no sandbox** (only Python and TypeScript have sandboxing). The Java SDK relies on developer conventions to enforce determinism. The SDK provides `Workflow.*` APIs as safe replacements for common non-deterministic operations. A static analysis tool (`temporal-workflowcheck`, beta) can catch violations at build time — see `references/java/determinism-protection.md`.
|
|
|
|
## Why Determinism Matters: History Replay
|
|
|
|
Temporal provides durable execution through **History Replay**. When a Worker needs to restore workflow state (after a crash, cache eviction, or to continue after a long timer), it re-executes the workflow code from the beginning, which requires the workflow code to be **deterministic**.
|
|
|
|
## SDK Protection
|
|
|
|
Java workflow code runs in a cooperative threading model where only one workflow thread executes at a time under a global lock. The SDK does not intercept or block non-deterministic calls at runtime. If you call a forbidden operation, it will silently succeed during the initial execution but cause a `NonDeterministicException` when the workflow is replayed.
|
|
|
|
`temporal-workflowcheck` (static analysis, beta) and `WorkflowReplayer` (replay testing) can help uncover some violations, but they are not exhaustive — careful code review and adherence to the rules below remain essential.
|
|
|
|
## Forbidden Operations in Workflows
|
|
|
|
The following are forbidden inside workflow code but are appropriate to use in activities.
|
|
|
|
- `Thread.sleep()` — blocks the real thread, bypasses Temporal timers
|
|
- `new Thread()` or thread pools — breaks the cooperative threading model
|
|
- `synchronized` blocks and explicit locks — can deadlock with the workflow executor
|
|
- `UUID.randomUUID()` — non-deterministic across replays
|
|
- `Math.random()` or `new Random()` — non-deterministic across replays
|
|
- `System.currentTimeMillis()` or `Instant.now()` — non-deterministic across replays
|
|
- Direct I/O (network, filesystem, database) — side effects must run in activities
|
|
- Mutable global/static state — shared state breaks isolation between workflow instances
|
|
- `CompletableFuture` — bypasses the workflow scheduler; use `Promise` instead
|
|
|
|
## Safe Builtin Alternatives
|
|
|
|
| Forbidden | Safe Alternative |
|
|
|-----------|------------------|
|
|
| `Thread.sleep(millis)` | `Workflow.sleep(Duration.ofMillis(millis))` |
|
|
| `UUID.randomUUID()` | `Workflow.randomUUID()` |
|
|
| `Math.random()` | `Workflow.newRandom().nextInt()` |
|
|
| `System.currentTimeMillis()` | `Workflow.currentTimeMillis()` |
|
|
| `new Thread(runnable)` | `Async.function(func)` / `Async.procedure(proc)` |
|
|
| `CompletableFuture<T>` | `Promise<T>` / `CompletablePromise<T>` |
|
|
| `BlockingQueue<T>` | `WorkflowQueue<T>` |
|
|
| `Future<T>` | `Promise<T>` |
|
|
|
|
## Testing Replay Compatibility
|
|
|
|
Use the `WorkflowReplayer` class to verify your code changes are compatible with existing histories. See the Workflow Replay Testing section of `references/java/testing.md`.
|
|
|
|
## Best Practices
|
|
|
|
1. Use `Workflow.currentTimeMillis()` for all time operations
|
|
2. Use `Workflow.newRandom()` for random values
|
|
3. Use `Workflow.randomUUID()` for unique identifiers
|
|
4. Use `Async.function()` / `Async.procedure()` instead of raw threads
|
|
5. Use `Promise` and `CompletablePromise` instead of `CompletableFuture`
|
|
6. Test with `WorkflowReplayer` to catch non-determinism
|
|
7. Keep workflows focused on orchestration, delegate I/O to activities
|
|
8. Use `Workflow.getLogger()` for replay-safe logging
|