-
Notifications
You must be signed in to change notification settings - Fork 328
Updated for Nexus SDK Ergonomics - Not ready to be merged yet!! #5203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Evanthx
wants to merge
10
commits into
main
Choose a base branch
from
nexus-v2-2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
b1245fa
Updated for Nexus SDK Ergonomics
Evanthx 8428734
Updated to address a PR comment.
Evanthx e4fab9a
Add docs for other languages
atol 3b1dd25
fold dev experience content into feature guides. keep feature guide m…
jsundai 30fd810
Update dependency injection reference in feature guide
jsundai b8df4a2
change admonition to note
jsundai 411948f
Restore original line wrapping in Nexus feature guides
jsundai a036845
roeys comments pt 1
jsundai b1b51d0
links, nit, cross language
jsundai f6bcd46
Minor wording tweak
Evanthx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. | ||
| 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 | ||
|
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. | ||
|
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. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
|
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. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.