Skip to content

feat(python): return a client call's result, with its RPC options - #328

Closed
moetemp wants to merge 1 commit into
moe/up/resource-definitionfrom
moe/up/python-rpc-options
Closed

moetemp wants to merge 1 commit into
moe/up/resource-definitionfrom
moe/up/python-rpc-options

Conversation

@moetemp

@moetemp moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

What changed?

This PR adds the RPC options to the Python client calls, and start_<name> for an operation that WIT declares async func.

  • Each call of the client target takes the keyword options rpc_metadata: Mapping[str, str | bytes] | None = None and rpc_timeout: timedelta | None = None. It passes them to _create_nexus_client, which now takes them too. So one SDK method serves every service, and the SDK applies the options to the call.
  • The methods of a resource class that serves the client target take the same options, and so do the operations objects. The Workflow operations raise ValueError when either option is set, since the options apply to calls outside a Workflow only.
  • An async func operation also gets start_<name> on the client, which returns the handle of the operation. The caller awaits the handle for the result later. A call with no start_ already returns the result with one await, since feat(python): add a client target #324. The handle gives the result of the operation as it is, so an operation that returns a resource or has an output transform gets no start_<name>.
  • nexgen refuses a start_<name> that is also the name of another client method.

A new Python sample, client-calls, has an async func operation and a plain one.

TypeScript and .NET get the options with their client targets. The TypeScript client sets them with withMetadata and withDeadline, and a .NET call will take RpcOptions.

It sits on #327. The stack is #308, #310, #311, #297, #296, #303, #304, #309, #318, #319, #320, #321, #322, #323, #324, #325, #326, #327, then this PR.

Why?

The Stream API of the proposal has rpc_metadata and rpc_timeout on every call, as TemporalClient calls do. Brook's runtime uses the timeout as the deadline of the call, which it sets through a ContextVar today. A client method couldn't tell an operation that can run for a long time apart, so it couldn't give a caller the handle. WIT's async func says it.

The options default to None, not {} as in the SDK, since the samples' basedpyright refuses a mutable default.

How did you test it?

The client-calls tests start the async operation and check that the start returns before the result, run the plain one, and check that the RPC options reach _create_nexus_client. The stream tests check that a resource method passes its options to the client, and that the Workflow operations refuse them. A rejection fixture covers the name clash.
cargo validate passes.

Each client call and resource method takes `rpc_metadata` and `rpc_timeout`, and Workflow code
refuses them. An `async func` operation also gets `start_<name>`, which returns the handle.
@moetemp

moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Moved to moetemp/nexgen#82 for review first. It comes back here after that.

@moetemp moetemp closed this Oct 28, 2026
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.

1 participant