Skip to content

Sample code for Nexus messaging#290

Open
Evanthx wants to merge 8 commits intomainfrom
signals-nexus-python
Open

Sample code for Nexus messaging#290
Evanthx wants to merge 8 commits intomainfrom
signals-nexus-python

Conversation

@Evanthx
Copy link
Copy Markdown

@Evanthx Evanthx commented Apr 15, 2026

This is sample code to show two ways to send messages (signals, queries, and updates) through Nexus.

@Evanthx Evanthx requested a review from a team as a code owner April 15, 2026 18:31
@Evanthx Evanthx force-pushed the signals-nexus-python branch from d11d1a0 to 83386cf Compare April 15, 2026 22:57
Copy link
Copy Markdown
Contributor

@VegetarianOrc VegetarianOrc left a comment

Choose a reason for hiding this comment

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

Code looks okay to me! A few comments throughout.

Left a couple of comments to help me understand the motivation for the structure of the samples as well.

Would like to clear up the intention around removing the sync operation sample before approving.

from temporalio import workflow
from temporalio.exceptions import ApplicationError

with workflow.unsafe.imports_passed_through():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need to use imports_passed_through() here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Was this same intentionally deleted? I don't think we should remove the basic sync operation example in favor of a messaging sample.

from temporalio import workflow
from temporalio.exceptions import ApplicationError

with workflow.unsafe.imports_passed_through():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above. Shouldn't need imports_passed_through() here.

Comment on lines +3 to +10
The handler worker starts a `GreetingWorkflow` for a user ID.
`NexusGreetingServiceHandler` holds that ID and routes every Nexus operation to it.
The caller's input does not have that workflow ID as the caller doesn't know it -- but the caller
sends in the User ID, and `NexusGreetingServiceHandler` knows how to get the desired workflow ID
from that User ID (see the `get_workflow_id` call).

The handler worker uses the same `get_workflow_id` call to generate a workflow ID from a user ID
when it launches the workflow.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm worried this sample is a little complicated.

For example, if our goal is to demonstrate how to acquire a workflow handle in a nexus operation handler and signal/query/update a workflow I think abstracting workflow ID as a combo of prefix + userID just adds cognitive load and may be confusing.

If the goal is to show how Nexus can be used to abstract the underlying workflow away, then I think that might deserve a sample separate from how to use messaging via Nexus.

Comment on lines +12 to +16
The caller workflow:
1. Queries for supported languages (`get_languages` -- backed by a `@workflow.query`)
2. Changes the language to Arabic (`set_language` -- backed by a `@workflow.update` that calls an activity)
3. Confirms the change via a second query (`get_language`)
4. Approves the workflow (`approve` -- backed by a `@workflow.signal`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: The caller workflow only executes nexus operations and it feels a bit confusing to call out that they're backed by workflow.query/update/signal. IMO that info should be called out about or alongside the service handler.

Comment on lines +35 to +42
workflow_id = get_workflow_id(USER_ID)
await client.start_workflow(
GreetingWorkflow.run,
id=workflow_id,
task_queue=TASK_QUEUE,
id_conflict_policy=WorkflowIDConflictPolicy.USE_EXISTING,
)
logging.info("Started greeting workflow: %s", workflow_id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: this just starts a workflow while no workers are running. I'd consider moving it in the below async with Worker(...) block

Comment on lines +63 to +71
# Routes to set_language_using_activity (not set_language) so that new languages not
# already in the greetings map can be fetched via an activity.
@nexusrpc.handler.sync_operation
async def set_language(
self, ctx: nexusrpc.handler.StartOperationContext, input: SetLanguageInput
) -> Language:
return await self._get_workflow_handle(input.user_id).execute_update(
GreetingWorkflow.set_language_using_activity, input
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If GreetingWorkflow.set_language is unused, we should remove it IMO.

Comment on lines +1 to +6
## On-demand pattern

No workflow is pre-started. The caller creates and controls workflow instances through Nexus
operations. `NexusRemoteGreetingService` adds a `run_from_remote` operation that starts a new
`GreetingWorkflow`, and every other operation includes a `user_id` so the handler knows which
instance to target.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you help me understand the motivation behind the two samples? This sample appears to demonstrate the same thing as the above sample in regards to messaging via Nexus.

The messaging via Nexus part remains using a sync operation to:

  • determine workflow ID
  • execute signal/query/update

The Nexus operations are not opinionated about where the workflow started from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants