Skip to content

feat(python): add @nexus.poll - #325

Open
moetemp wants to merge 8 commits into
refactor/api-generation-targetsfrom
moe/up/python-poll
Open

moetemp wants to merge 8 commits into
refactor/api-generation-targetsfrom
moe/up/python-poll

Conversation

@moetemp

@moetemp moetemp commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What changed?

This PR adds @nexus.poll to the Python client target. An operation with @nexus.poll python="<helper>" targets="client" gets an iter_<name> async iterator. It yields each response and asks the support package's <helper>(request, response) for the next request, which returns None to stop.

  • The client extension gets iter_<name>, and so does each client resource method that binds the operation. The stream sample gets iter_read_records and Stream.iter_read. Its helper ends a read that doesn't wait at the newest Record, and starts each later read at the last page's next_offset.
  • Each page is its own operation, with its own random operation ID. The extension iterator uses one Nexus client for all pages.
  • nexgen refuses the directive with no targets, with targets that include workflow, on a resource method, and on an operation it can't poll. The Workflow package doesn't change.

Why?

A WIT stream can't cross a Nexus call, so the Stream read is a request and a response. The iterator reads every page, and the support package decides the next request.

How did you test it?

Link to a test plan if any -

  • Unit Tests
  • Staging
  • End to End Tests

test_stream_client.py reads every page through client.iter_read_records and through Stream.iter_read, ends a read that doesn't wait at the newest Record, and starts the read after start=END at the first page's offset. Rejection fixtures cover the client-only rule, an operation that returns a resource, and an iterator name clash.

This was referenced Oct 28, 2026
@moetemp
moetemp force-pushed the moe/up/python-client-target branch 2 times, most recently from 4d12251 to dd3e142 Compare October 30, 2026 00:00
@moetemp
moetemp force-pushed the moe/up/python-poll branch 2 times, most recently from 8cdaab3 to c00d700 Compare October 30, 2026 01:00
@moetemp
moetemp force-pushed the moe/up/python-client-target branch from dd3e142 to df29fb0 Compare October 30, 2026 01:00
@moetemp
moetemp force-pushed the moe/up/python-poll branch from c00d700 to de33837 Compare October 30, 2026 07:14
@moetemp
moetemp changed the base branch from moe/up/python-client-target to moe/fix/api-generation-targets-review October 30, 2026 07:14
@moetemp
moetemp force-pushed the moe/fix/api-generation-targets-review branch from a5c7270 to 4875677 Compare October 30, 2026 08:06
@moetemp
moetemp force-pushed the moe/up/python-poll branch from de33837 to 17f6c9a Compare October 30, 2026 08:06
@moetemp
moetemp force-pushed the moe/fix/api-generation-targets-review branch from 4875677 to 4660b19 Compare October 30, 2026 23:00
@moetemp
moetemp force-pushed the moe/up/python-poll branch from 17f6c9a to 3e1ca29 Compare October 30, 2026 23:00
Base automatically changed from moe/fix/api-generation-targets-review to refactor/api-generation-targets October 30, 2026 23:28
@moetemp
moetemp force-pushed the moe/up/python-poll branch from 3e1ca29 to 7efc328 Compare October 30, 2026 23:44
@moetemp
moetemp changed the base branch from refactor/api-generation-targets to moe/up/python-workflow-package October 30, 2026 23:45
The poll helper names the support function that builds the next request. Only
the client target gets an iterator, so the parser refuses a poll without
`target="client"` and a poll on a resource method.
@moetemp
moetemp force-pushed the moe/up/python-poll branch from 7efc328 to 26b2571 Compare October 31, 2026 03:11
@moetemp
moetemp changed the base branch from moe/up/python-workflow-package to refactor/api-generation-targets October 31, 2026 03:11
@moetemp
moetemp force-pushed the moe/up/python-poll branch from 26b2571 to 6938695 Compare October 31, 2026 03:17
A WIT stream can't cross a Nexus call, so a read is a request and a response.
The iterator reads every page. The extension creates one Nexus client for the
iteration, and a handle uses its own client.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
@moetemp
moetemp force-pushed the moe/up/python-poll branch from 6938695 to f2cc4b8 Compare October 31, 2026 03:18
The Stream service sets `next_offset` on an empty page too, so the helper
reads it as the Stream reader does. Each answer's next offset sets the later
reads, also after `start` or `last`.
A caller that changes a yielded page then can't change the next read.
`AsyncGenerator` lets a caller close the iterator with `aclose()` or
`contextlib.aclosing`. A handle's iterator also gets the method doc and `Args:`.
The poll directive then reads its targets as the other directives do. A
refused poll gives the service, the operation and the input path.
Also rewrite poll comments that read two ways or use `name` as a verb.
A generic directive check is planned for syntax and placement. The kept fixtures cover the client-only rule, an operation shape the iterator can't take, and an iterator name clash.
The full stream helper is in the sample, so the guide keeps a short version and links to it.

This branch has not been deployed

No deployments
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