diff --git a/temporalio/nexus/_operation_context.py b/temporalio/nexus/_operation_context.py index 66e675d27..ae310f070 100644 --- a/temporalio/nexus/_operation_context.py +++ b/temporalio/nexus/_operation_context.py @@ -79,6 +79,9 @@ class Info: Retrieved inside a Nexus operation handler via :py:func:`info`. """ + namespace: str + """The namespace of the worker handling this Nexus operation.""" + task_queue: str """The task queue of the worker handling this Nexus operation.""" diff --git a/temporalio/worker/_nexus.py b/temporalio/worker/_nexus.py index 278337746..d324a0c4c 100644 --- a/temporalio/worker/_nexus.py +++ b/temporalio/worker/_nexus.py @@ -67,6 +67,7 @@ def __init__( *, bridge_worker: Callable[[], temporalio.bridge.worker.Worker], client: temporalio.client.Client, + namespace: str, task_queue: str, service_handlers: Sequence[Any], data_converter: temporalio.converter.DataConverter, @@ -76,6 +77,7 @@ def __init__( ) -> None: self._bridge_worker = bridge_worker self._client = client + self._namespace = namespace self._task_queue = task_queue self._metric_meter = metric_meter @@ -242,7 +244,7 @@ async def _handle_cancel_operation_task( request_deadline=request_deadline, ) temporalio.nexus._operation_context._TemporalCancelOperationContext( - info=lambda: Info(task_queue=self._task_queue), + info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), nexus_context=ctx, client=self._client, _runtime_metric_meter=self._metric_meter, @@ -373,7 +375,7 @@ async def _start_operation( temporalio.nexus._operation_context._TemporalStartOperationContext( nexus_context=ctx, client=self._client, - info=lambda: Info(task_queue=self._task_queue), + info=lambda: Info(namespace=self._namespace, task_queue=self._task_queue), _runtime_metric_meter=self._metric_meter, _worker_shutdown_event=self._worker_shutdown_event, ).set() diff --git a/temporalio/worker/_worker.py b/temporalio/worker/_worker.py index 332e2ead7..2ad1d42c6 100644 --- a/temporalio/worker/_worker.py +++ b/temporalio/worker/_worker.py @@ -485,6 +485,7 @@ def _init_from_config(self, client: temporalio.client.Client, config: WorkerConf self._nexus_worker = _NexusWorker( bridge_worker=lambda: self._bridge_worker, client=config["client"], # type: ignore[reportTypedDictNotRequiredAccess] + namespace=client_config["namespace"], task_queue=config["task_queue"], # type: ignore[reportTypedDictNotRequiredAccess] service_handlers=nexus_service_handlers, data_converter=client_config["data_converter"], diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index ca9e2e145..2b9699089 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -696,6 +696,47 @@ async def test_sync_operation_happy_path(client: Client, env: WorkflowEnvironmen assert wf_output.op_output.value == "sync response" +@service_handler +class NexusInfoService: + @sync_operation + async def get_info( + self, _ctx: StartOperationContext, _input: None + ) -> dict[str, str]: + info = nexus.info() + return {"namespace": info.namespace, "task_queue": info.task_queue} + + +@workflow.defn +class NexusInfoCallerWorkflow: + @workflow.run + async def run(self, task_queue: str) -> dict[str, str]: + nexus_client = workflow.create_nexus_client( + service=NexusInfoService, + endpoint=make_nexus_endpoint_name(task_queue), + ) + return await nexus_client.execute_operation(NexusInfoService.get_info, None) + + +async def test_nexus_info_includes_namespace(client: Client, env: WorkflowEnvironment): + task_queue = str(uuid.uuid4()) + async with Worker( + client, + nexus_service_handlers=[NexusInfoService()], + workflows=[NexusInfoCallerWorkflow], + task_queue=task_queue, + ): + endpoint_name = make_nexus_endpoint_name(task_queue) + await env.create_nexus_endpoint(endpoint_name, task_queue) + result = await client.execute_workflow( + NexusInfoCallerWorkflow.run, + task_queue, + id=str(uuid.uuid4()), + task_queue=task_queue, + ) + assert result["namespace"] == client.namespace + assert result["task_queue"] == task_queue + + async def test_workflow_run_operation_happy_path( client: Client, env: WorkflowEnvironment ):