* 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>
3.4 KiB
Java Determinism Protection
Overview
The Java SDK has no sandbox (only Python and TypeScript have sandboxing). Java relies on developer conventions and runtime replay detection to enforce determinism. A static analysis tool (temporal-workflowcheck) is available in beta.
Forbidden Operations in Workflows
The following are forbidden inside workflow code but are appropriate to use in activities.
// BAD: Non-deterministic operations in workflow code
Thread.sleep(1000);
UUID id = UUID.randomUUID();
double val = Math.random();
long now = System.currentTimeMillis();
new Thread(() -> doWork()).start();
CompletableFuture.supplyAsync(() -> compute());
// GOOD: Deterministic Workflow.* alternatives
Workflow.sleep(Duration.ofSeconds(1));
String id = Workflow.randomUUID().toString();
int val = Workflow.newRandom().nextInt();
long now = Workflow.currentTimeMillis();
Promise<Void> promise = Async.procedure(() -> doWork());
CompletablePromise<String> promise = Workflow.newPromise();
Static Analysis with temporal-workflowcheck
Warning: This tool is in beta.
temporal-workflowcheck scans compiled bytecode to detect non-deterministic operations in workflow code. It catches threading, I/O, randomization, system time access, and non-final static field access — including transitive violations through call chains.
Setup (Gradle)
Add the dependency as a compile-only check:
dependencies {
implementation 'io.temporal:temporal-sdk:1.+'
compileOnly 'io.temporal:temporal-workflowcheck:1.+'
}
See the Gradle sample for full task configuration.
Setup (Maven)
See the Maven sample for POM configuration.
Running Manually
Download the -all.jar from Maven Central (io.temporal:temporal-workflowcheck) and run:
java -jar temporal-workflowcheck-<version>-all.jar check <classpath-entries>
Suppressing False Positives
Use the @WorkflowCheck.SuppressWarnings annotation on methods:
@WorkflowCheck.SuppressWarnings(invalidMembers = "currentTimeMillis")
public long getCurrentMillis() {
return System.currentTimeMillis();
}
Or use a .properties configuration file with --config <path> for third-party library false positives.
Convention-Based Enforcement
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. Instead, non-determinism is detected at replay time: if replayed code produces results that differ from the recorded history, the SDK throws a NonDeterministicException.
Use both temporal-workflowcheck (static, pre-deploy) and WorkflowReplayer (replay testing) to catch non-determinism before production.
Best Practices
- Run
temporal-workflowcheckin CI to catch non-deterministic code statically - Always use
Workflow.*APIs instead of standard Java equivalents for time, randomness, UUIDs, sleeping, and threading - Test all workflow code changes with
WorkflowReplayeragainst recorded histories - Keep workflows focused on orchestration logic; move all I/O and side effects into activities
- Avoid mutable static state shared across workflow instances