1212 Any ,
1313 Callable ,
1414 Generator ,
15+ Generic ,
1516 Optional ,
17+ TypeVar ,
1618 Union ,
1719 overload ,
1820)
1921
20- from nexusrpc .handler import CancelOperationContext , StartOperationContext
22+ from nexusrpc .handler import (
23+ CancelOperationContext ,
24+ OperationContext ,
25+ StartOperationContext ,
26+ )
2127from typing_extensions import Concatenate
2228
2329import temporalio .api .common .v1
@@ -87,8 +93,13 @@ def client() -> temporalio.client.Client:
8793 return _temporal_context ().client
8894
8995
96+ def metric_meter () -> temporalio .common .MetricMeter :
97+ """Get the metric meter for the current Nexus operation."""
98+ return _temporal_context ().metric_meter
99+
100+
90101def _temporal_context () -> (
91- Union [ _TemporalStartOperationContext , _TemporalCancelOperationContext ]
102+ _TemporalStartOperationContext | _TemporalCancelOperationContext
92103):
93104 ctx = _try_temporal_context ()
94105 if ctx is None :
@@ -97,7 +108,7 @@ def _temporal_context() -> (
97108
98109
99110def _try_temporal_context () -> (
100- Optional [ Union [ _TemporalStartOperationContext , _TemporalCancelOperationContext ]]
111+ _TemporalStartOperationContext | _TemporalCancelOperationContext | None
101112):
102113 start_ctx = _temporal_start_operation_context .get (None )
103114 cancel_ctx = _temporal_cancel_operation_context .get (None )
@@ -119,18 +130,39 @@ def _in_nexus_backing_workflow_start_context() -> bool:
119130 return _temporal_nexus_backing_workflow_start_context .get (False )
120131
121132
122- @dataclass
123- class _TemporalStartOperationContext :
124- """Context for a Nexus start operation being handled by a Temporal Nexus Worker."""
133+ _OperationCtxT = TypeVar ("_OperationCtxT" , bound = OperationContext )
125134
126- nexus_context : StartOperationContext
127- """Nexus-specific start operation context."""
135+
136+ @dataclass (kw_only = True )
137+ class _TemporalOperationCtx (Generic [_OperationCtxT ]):
138+ client : temporalio .client .Client
139+ """The Temporal client in use by the worker handling the current Nexus operation."""
128140
129141 info : Callable [[], Info ]
130142 """Temporal information about the running Nexus operation."""
131143
132- client : temporalio .client .Client
133- """The Temporal client in use by the worker handling this Nexus operation."""
144+ nexus_context : _OperationCtxT
145+ """Nexus-specific start operation context."""
146+
147+ runtime_metric_meter : temporalio .common .MetricMeter
148+ _metric_meter : temporalio .common .MetricMeter | None = None
149+
150+ @property
151+ def metric_meter (self ) -> temporalio .common .MetricMeter :
152+ if not self ._metric_meter :
153+ self ._metric_meter = self .runtime_metric_meter .with_additional_attributes (
154+ {
155+ "nexus_service" : self .nexus_context .service ,
156+ "nexus_operation" : self .nexus_context .operation ,
157+ "task_queue" : self .info ().task_queue ,
158+ }
159+ )
160+ return self ._metric_meter
161+
162+
163+ @dataclass
164+ class _TemporalStartOperationContext (_TemporalOperationCtx [StartOperationContext ]):
165+ """Context for a Nexus start operation being handled by a Temporal Nexus Worker."""
134166
135167 @classmethod
136168 def get (cls ) -> _TemporalStartOperationContext :
@@ -217,6 +249,11 @@ def _from_start_operation_context(
217249 ** {f .name : getattr (ctx , f .name ) for f in dataclasses .fields (ctx )},
218250 )
219251
252+ @property
253+ def metric_meter (self ) -> temporalio .common .MetricMeter :
254+ """The metric meter"""
255+ return self ._temporal_context .metric_meter
256+
220257 # Overload for no-param workflow
221258 @overload
222259 async def start_workflow (
@@ -480,19 +517,10 @@ class NexusCallback:
480517 """Header to attach to callback request."""
481518
482519
483- @dataclass ( frozen = True )
484- class _TemporalCancelOperationContext :
520+ @dataclass
521+ class _TemporalCancelOperationContext ( _TemporalOperationCtx [ CancelOperationContext ]) :
485522 """Context for a Nexus cancel operation being handled by a Temporal Nexus Worker."""
486523
487- nexus_context : CancelOperationContext
488- """Nexus-specific cancel operation context."""
489-
490- info : Callable [[], Info ]
491- """Temporal information about the running Nexus cancel operation."""
492-
493- client : temporalio .client .Client
494- """The Temporal client in use by the worker handling the current Nexus operation."""
495-
496524 @classmethod
497525 def get (cls ) -> _TemporalCancelOperationContext :
498526 ctx = _temporal_cancel_operation_context .get (None )
0 commit comments