Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
311 changes: 108 additions & 203 deletions docs/develop/dotnet/nexus/feature-guide.mdx

Large diffs are not rendered by default.

334 changes: 126 additions & 208 deletions docs/develop/go/nexus/feature-guide.mdx

Large diffs are not rendered by default.

325 changes: 96 additions & 229 deletions docs/develop/java/nexus/feature-guide.mdx

Large diffs are not rendered by default.

290 changes: 146 additions & 144 deletions docs/develop/python/nexus/feature-guide.mdx

Large diffs are not rendered by default.

327 changes: 142 additions & 185 deletions docs/develop/typescript/nexus/feature-guide.mdx

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions docs/encyclopedia/nexus/nexus-code-generator.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
id: nexus-code-generator
title: Nexus Code Generator
sidebar_label: Nexus Code Generator
description: The Nexus Code Generator turns one schema into typed models, runtime validators, and Nexus Service definitions for Go, Java, Python, and TypeScript.
Comment on lines +4 to +5

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this nexgen to match the language everywhere?
Same goes for the name of the file.

toc_max_heading_level: 4
slug: /nexus/code-generator
tags:
- Nexus
- Concepts
---

import { ReleaseNoteHeader } from '@site/src/components';

<ReleaseNoteHeader type="prerelease" languages={["Go", "Java", "Python", "TypeScript"]} guidePath="nexus/feature-guide">
APIs are experimental and may be subject to backwards-incompatible changes.
</ReleaseNoteHeader>

A [Nexus Service](/nexus/services) is called across a team boundary, often by a caller written in a different language than the handler implementation and deployed on its own schedule.
When each side hand-writes its own request and response types, the two copies drift, and nothing catches it until a call fails.

[`nexgen`](https://github.com/temporalio/nexgen) generates client code for Go, Java, Python, and TypeScript from a schema file that defines the contract. The schema's types are modeled with [JSON Schema 2020-12](https://json-schema.org).
Both sides can then use code generated from the same file, which gives data validation and type safety across the languages and helps prevent drift.

For each type it emits:

- **Typed models** — an idiomatic struct, class, interface, or dataclass, with doc comments carried over from the schema.
- **A runtime validator**, automatically applied when a value is parsed off the wire and again when it is serialized onto it.
- **A [Nexus Service](/nexus/services) definition**, for a file that declares Services. The handler implements it; the caller uses it to invoke Operations.

## How it works
Comment thread
Evanthx marked this conversation as resolved.

You write the contract once, as a JSON or YAML definition file, and run `nexgen` against it.
The generator emits contract code in Go, Java, Python, or TypeScript as requested.

Both sides use that generated code: the handler implements the Service, and the caller invokes its Operations.
Because both were generated from the same file, they agree on the contract by construction, and the generated validators enforce it at runtime on every payload.

This is what makes a Nexus Service polyglot.
A Python handler and a Go caller never share code — they share a definition file.
Generate from it in each language and they interoperate, with no coordination between the teams beyond the contract itself.

## Data validation

The generated validators check every payload against the contract, when a value is parsed off the wire and again when it is serialized onto it.
Bad data is rejected at the boundary instead of reaching your Workflow or Activity.

Failures aggregate into a single error listing every violation, each naming the offending field and the constraint it broke.
A handler maps that to a `BAD_REQUEST` [Nexus handler error](/nexus/error-handling), so a malformed request tells the caller everything that was wrong in one response.

A value is validated identically in every language, which is what lets a caller and a handler written in different ones trust the same contract.
Keeping that promise is why the supported schema subset is deliberately strict: anything ambiguous, or anything that cannot be expressed the same way everywhere, is rejected at generation time rather than becoming code that validates differently in one language than another.
Comment thread
jsundai marked this conversation as resolved.

Three numeric and timestamp edge cases do not yet behave the same way in every language, covering negative zero, very large fractional integers, and nanosecond precision in Python.
See [Known cross-language divergences](https://github.com/temporalio/nexgen#known-cross-language-divergences) in the `nexgen` README for what each language does.
2 changes: 2 additions & 0 deletions docs/encyclopedia/nexus/nexus-services.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ Multiple Services can run in the same Worker.
Services typically run alongside the Workflows they abstract, or in a dedicated router Worker using the [router-queue pattern](/nexus/patterns#router-queue-pattern).

Callers reference a Service by name when executing a Nexus Operation.

You can hand-write a Service definition, or generate it from a schema file with the [Nexus Code Generator](/nexus/code-generator), which emits the definition along with typed models and runtime validators for each language.
54 changes: 54 additions & 0 deletions docs/encyclopedia/nexus/nexus-standalone-activity.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
id: nexus-standalone-activity
title: Nexus Standalone Activity
sidebar_label: Nexus Standalone Activity
description: Back a Nexus Operation with a Standalone Activity when the work is a single durable step, with no Workflow wrapped around it.
toc_max_heading_level: 4
slug: /nexus/standalone-activity
tags:
- Nexus
- Concepts
---

import { ReleaseNoteHeader } from '@site/src/components';

<ReleaseNoteHeader type="prerelease" languages={["Go", "Java", "Python", "TypeScript", ".NET"]} guidePath="nexus/feature-guide">
APIs are experimental and may be subject to backwards-incompatible changes.
</ReleaseNoteHeader>

:::note Not the same as a Standalone Nexus Operation
Comment thread
jsundai marked this conversation as resolved.

The two names are close and describe opposite ends of the call.
A [Standalone Nexus Operation](/standalone-nexus-operation) is about the **caller**: a Client starts an Operation directly, with no caller Workflow around it.
A Nexus Standalone Activity is about the **handler**: an Operation is backed by a single Activity, with no Workflow behind it.
They are independent choices, and either can be used without the other.

:::

An Activity-backed [Nexus Operation](/nexus/operations) runs a [Standalone Activity](/standalone-activity) and completes when that Activity returns.
Use it when the work behind an Operation is one durable step rather than a process: calling an external API, running a computation, writing to another system.

Two things combine to make this happen.
The [Activity](/activities) supplies durability — retries on the policy you set, timeouts you control, and a record of every attempt.
The Operation supplies a typed contract and a [Namespace](/namespaces) boundary, so another team can call it without sharing your code, your deployment, or write access to your Namespace.

Because the Activity carries the durability, no Workflow is needed behind the Operation.
A Workflow wrapping a single Activity costs two [Billable Actions](/cloud/actions-usage#actions-in-workflows) in Temporal Cloud — one to start the Workflow, one to start the Activity — where a Standalone Activity costs one.
Retries and heartbeats are billed the same way in either shape.

## Required options

Starting an Activity this way needs values a Workflow-called Activity does not, because there is no parent Workflow to supply them:

- **An Activity Id**, unique within the Namespace. Deriving it from the Nexus request Id makes the start idempotent, so a retried request targets the same Activity Execution instead of sending a second notification or charge.
- **A timeout.** At least one of start-to-close or schedule-to-close.

The Task Queue is optional and defaults to the one the Operation is running on. Set it explicitly to run the Activity on its own Worker fleet.

## Cancellation

An Activity is not interrupted by a cancellation request the way a Workflow is.
The Worker only learns about it on the next Heartbeat, so an Activity that never Heartbeats runs until it completes or times out.
Nothing here is Nexus-specific — see [Activity Cancellation](/activity-execution#cancellation).

Back an Operation with a **Workflow** instead when the work has more than one step, needs to wait for something, needs to receive [messages](/sending-messages), or needs durable intermediate state.
36 changes: 36 additions & 0 deletions docs/encyclopedia/nexus/temporal-operation-handler.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
id: temporal-operation-handler
title: Temporal Operation Handler
sidebar_label: Temporal Operation Handler
description: The Temporal Operation Handler is a single handler type that backs a Nexus Operation with a Workflow, an Update, or an Activity, and links every Execution back to the caller.
toc_max_heading_level: 4
slug: /nexus/temporal-operation-handler
tags:
- Nexus
- Concepts
---

import { ReleaseNoteHeader } from '@site/src/components';

<ReleaseNoteHeader type="prerelease" languages={["Go", "Java", "Python", "TypeScript", ".NET"]} guidePath="nexus/feature-guide">
APIs are experimental and may be subject to backwards-incompatible changes.
</ReleaseNoteHeader>

Temporal has unified the Workflow handler and the synchronous operation handler into a single handler, and added the ability to back an Operation with a [Standalone Activity](/nexus/standalone-activity).

What runs behind an Operation remains private to the handler, so you can change it later without touching the contract or any caller.

## The Nexus-aware Client

The Operation handler receives a context, the Operation input, and a Client.

That Client is not an ordinary Temporal Client.
It propagates [bidirectional links](/nexus/execution-debugging#bi-directional-linking) and request Ids on every call, so caller-side and handler-side Executions are connected in the UI and in [Event History](/encyclopedia/event-history) without wiring anything.
Constructing your own Client inside a handler works, but the Executions it starts are not linked back to the caller.

It exposes two kinds of call:

- **Async backings**, at most one per Operation invocation. These determine what the Operation *is*, and their result reaches the caller through the Nexus completion callback. Starting a Workflow, starting an Activity, and starting a Workflow Update are all async backings.
- **Sync messaging**, as many as you need. Signals and Signal-with-Start take effect during the handler call and do not require an async backing.

Deriving the backing Execution's Id from the Nexus request Id keeps a retried start request targeting the same Execution instead of creating a second one.
6 changes: 5 additions & 1 deletion sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -2111,14 +2111,18 @@ module.exports = {
items: [
'encyclopedia/nexus/nexus-services',
'encyclopedia/nexus/nexus-operations',
'encyclopedia/nexus/standalone-nexus-operation',
'encyclopedia/nexus/nexus-endpoints',
'encyclopedia/nexus/nexus-registry',
'encyclopedia/nexus/nexus-patterns',
'encyclopedia/nexus/nexus-security',
'encyclopedia/nexus/nexus-execution-debugging',
'encyclopedia/nexus/nexus-error-handling',
'encyclopedia/nexus/nexus-metrics',
// Pre-release features, kept at the bottom of the section.
'encyclopedia/nexus/temporal-operation-handler',
'encyclopedia/nexus/nexus-code-generator',
'encyclopedia/nexus/standalone-nexus-operation',
'encyclopedia/nexus/nexus-standalone-activity',
],
},
{
Expand Down