Skip to content

Commit b98ea57

Browse files
Moving decoding logic to the nexus operation handle
1 parent a8fb58f commit b98ea57

4 files changed

Lines changed: 40 additions & 44 deletions

File tree

‎temporalio/client/_impl.py‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@
114114
NexusOperationExecutionAsyncIterator,
115115
NexusOperationExecutionCount,
116116
NexusOperationExecutionDescription,
117-
NexusOperationFailureError,
118117
NexusOperationHandle,
119118
)
120119
from ._schedule import (
@@ -1659,13 +1658,8 @@ async def describe_nexus_operation(
16591658

16601659
async def get_nexus_operation_result(
16611660
self, input: GetNexusOperationResultInput
1662-
) -> Any:
1661+
) -> temporalio.api.workflowservice.v1.PollNexusOperationExecutionResponse:
16631662
"""Poll for nexus operation result until it's available."""
1664-
data_converter = self._client.data_converter
1665-
if input._nexus_serialization_context is not None:
1666-
data_converter = data_converter.with_context(
1667-
input._nexus_serialization_context
1668-
)
16691663
req = temporalio.api.workflowservice.v1.PollNexusOperationExecutionRequest(
16701664
namespace=self._client.namespace,
16711665
operation_id=input.operation_id,
@@ -1684,20 +1678,8 @@ async def get_nexus_operation_result(
16841678
timeout=input.rpc_timeout,
16851679
)
16861680
)
1687-
match res.WhichOneof("outcome"):
1688-
case "result":
1689-
type_hints = [input.result_type] if input.result_type else None
1690-
[result] = await data_converter.decode([res.result], type_hints)
1691-
return result
1692-
1693-
case "failure":
1694-
raise NexusOperationFailureError(
1695-
cause=await data_converter.decode_failure(res.failure)
1696-
)
1697-
1698-
case None:
1699-
# poll again
1700-
pass
1681+
if res.WhichOneof("outcome") is not None:
1682+
return res
17011683
except RPCError as err:
17021684
match err.status:
17031685
case RPCStatusCode.DEADLINE_EXCEEDED:

‎temporalio/client/_interceptor.py‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
import temporalio.api.common.v1
1919
import temporalio.api.workflowservice.v1
2020
import temporalio.common
21-
from temporalio.converter import (
22-
DataConverter,
23-
NexusSerializationContext,
24-
)
21+
from temporalio.converter import DataConverter
2522

2623
if TYPE_CHECKING:
2724
from ._activity import (
@@ -660,8 +657,6 @@ class GetNexusOperationResultInput:
660657
run_id: str | None
661658
rpc_metadata: Mapping[str, str | bytes]
662659
rpc_timeout: timedelta | None
663-
result_type: type[Any] | None
664-
_nexus_serialization_context: NexusSerializationContext | None = None
665660

666661

667662
@dataclass
@@ -1005,9 +1000,11 @@ async def describe_nexus_operation(
10051000

10061001
async def get_nexus_operation_result(
10071002
self, input: GetNexusOperationResultInput
1008-
) -> Any:
1003+
) -> temporalio.api.workflowservice.v1.PollNexusOperationExecutionResponse:
10091004
"""Called for every :py:meth:`NexusOperationHandle.result` call.
10101005
1006+
The raw response is decoded by the handle after interception.
1007+
10111008
.. warning::
10121009
This API is experimental and unstable.
10131010
"""

‎temporalio/client/_nexus.py‎

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,21 +1138,38 @@ async def result(
11381138
RPCError: Operation result could not be fetched for some reason.
11391139
"""
11401140
if self._known_outcome is temporalio.common._arg_unset:
1141-
try:
1142-
self._known_outcome = await self._client._impl.get_nexus_operation_result(
1143-
GetNexusOperationResultInput(
1144-
operation_id=self._operation_id,
1145-
run_id=self._run_id,
1146-
result_type=self._result_type,
1147-
rpc_metadata=rpc_metadata,
1148-
rpc_timeout=rpc_timeout,
1149-
_nexus_serialization_context=self._nexus_serialization_context,
1150-
)
1141+
response = await self._client._impl.get_nexus_operation_result(
1142+
GetNexusOperationResultInput(
1143+
operation_id=self._operation_id,
1144+
run_id=self._run_id,
1145+
rpc_metadata=rpc_metadata,
1146+
rpc_timeout=rpc_timeout,
1147+
)
1148+
)
1149+
1150+
data_converter = self._client.data_converter
1151+
if self._nexus_serialization_context is not None:
1152+
data_converter = data_converter.with_context(
1153+
self._nexus_serialization_context
11511154
)
1152-
return cast(ReturnType, self._known_outcome)
1153-
except NexusOperationFailureError as failure:
1154-
self._known_outcome = failure
1155-
raise
1155+
match response.WhichOneof("outcome"):
1156+
case "result":
1157+
type_hints = [self._result_type] if self._result_type else None
1158+
[result] = await data_converter.decode(
1159+
[response.result], type_hints
1160+
)
1161+
self._known_outcome = result
1162+
return cast(ReturnType, result)
1163+
case "failure":
1164+
operation_failure = NexusOperationFailureError(
1165+
cause=await data_converter.decode_failure(response.failure)
1166+
)
1167+
self._known_outcome = operation_failure
1168+
raise operation_failure
1169+
case None:
1170+
raise RuntimeError(
1171+
"Nexus operation result response did not contain an outcome"
1172+
)
11561173
elif isinstance(self._known_outcome, NexusOperationFailureError):
11571174
raise self._known_outcome
11581175
else:

‎tests/nexus/test_standalone_operations.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
)
2323

2424
import temporalio.api.enums.v1
25+
import temporalio.api.workflowservice.v1
2526
from temporalio import nexus, workflow
2627
from temporalio.client import (
2728
CancelNexusOperationInput,
@@ -867,7 +868,7 @@ async def describe_nexus_operation(
867868

868869
async def get_nexus_operation_result(
869870
self, input: GetNexusOperationResultInput
870-
) -> Any:
871+
) -> temporalio.api.workflowservice.v1.PollNexusOperationExecutionResponse:
871872
self._parent.result_calls.append(input)
872873
return await super().get_nexus_operation_result(input)
873874

@@ -980,7 +981,6 @@ async def test_interceptor_receives_inputs(client: Client, env: WorkflowEnvironm
980981
result_input = interceptor.result_calls[0]
981982
assert isinstance(result_input, GetNexusOperationResultInput)
982983
assert result_input.operation_id == op_id
983-
assert result_input.result_type == EchoOutput
984984

985985
# Start another so we can terminate it
986986
previous_start_count = len(interceptor.start_calls)

0 commit comments

Comments
 (0)