33is calling the nexus service, without specifying a separate service definition.
44"""
55
6+ from __future__ import annotations
7+
68import asyncio
79import uuid
810from typing import Optional
911
12+ import temporalio .nexus .handler
1013from nexusrpc .handler import (
1114 StartOperationContext ,
1215 service_handler ,
13- sync_operation_handler ,
1416)
1517from temporalio import workflow
16- from temporalio .client import Client
18+ from temporalio .client import Client , WorkflowHandle
19+ from temporalio .nexus .handler import workflow_run_operation_handler
1720from temporalio .worker import UnsandboxedWorkflowRunner , Worker
1821from temporalio .workflow import NexusClient
1922
2023NAMESPACE = "my-namespace"
2124TASK_QUEUE = "my-task-queue"
2225NEXUS_ENDPOINT = "my-nexus-endpoint"
2326
27+ #
28+ # Handler
29+ #
30+
31+
32+ @workflow .defn
33+ class HandlerWorkflow :
34+ @workflow .run
35+ async def run (self , message : str ) -> str :
36+ return f"Hello { message } from workflow run operation!"
37+
2438
2539# Here we define a nexus service by providing a service handler implementation without a
2640# service contract.
2741@service_handler
2842class MyNexusServiceHandler :
29- @sync_operation_handler
30- async def my_sync_operation (self , ctx : StartOperationContext , name : str ) -> str :
31- return f"Hello { name } from sync operation!"
43+ # The nexus service has one operation. When using the workflow_run_operation_handler
44+ # decorator, your start method must return a WorkflowHandle directly, using the
45+ # temporalio.nexus.handler.start_workflow helper. (Temporal server takes care of
46+ # delivering the workflow result to the caller, using the Nexus RPC callback mechanism).
47+ @workflow_run_operation_handler
48+ async def my_workflow_run_operation (
49+ self , ctx : StartOperationContext , name : str
50+ ) -> WorkflowHandle [HandlerWorkflow , str ]:
51+ return await temporalio .nexus .handler .start_workflow (
52+ ctx , HandlerWorkflow .run , name , id = str (uuid .uuid4 ())
53+ )
54+
55+
56+ #
57+ # Caller
58+ #
3259
3360
3461@workflow .defn
@@ -39,11 +66,11 @@ async def run(self, message: str) -> str:
3966 # operation.
4067 #
4168 # Normally, the first argument to both these calls would reference a service
42- # contract class, but it can also reference your service handler class, as here.
69+ # contract class, but they can also reference your service handler class, as here.
4370
4471 nexus_client = NexusClient (MyNexusServiceHandler , endpoint = NEXUS_ENDPOINT )
4572 return await nexus_client .execute_operation (
46- MyNexusServiceHandler .my_sync_operation , message
73+ MyNexusServiceHandler .my_workflow_run_operation , message
4774 )
4875
4976
@@ -54,7 +81,7 @@ async def execute_caller_workflow(client: Optional[Client] = None) -> str:
5481 async with Worker (
5582 client ,
5683 task_queue = TASK_QUEUE ,
57- workflows = [CallerWorkflow ],
84+ workflows = [CallerWorkflow , HandlerWorkflow ],
5885 nexus_services = [MyNexusServiceHandler ()],
5986 # TODO(dan): isinstance(op, nexusrpc.contract.Operation) is failing under the
6087 # sandbox in temporalio/worker/_interceptor.py
0 commit comments