Skip to content

feat(python): yield the items of a poll, with a resume point - #91

Closed
moetemp wants to merge 1 commit into
review/p3-varargsfrom
review/p3-poll
Closed

moetemp wants to merge 1 commit into
review/p3-varargsfrom
review/p3-poll

Conversation

@moetemp

@moetemp moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner

What changed?

This PR lets a Python poll iterator yield the items of each page, with a point to resume from.

/// @nexus.poll python="next_read_request" items="records"
///   python-resume="resume_read_request" target="client"
read-records: func(request: read-records-request) -> read-records-response;
  • items="<field>" names a list field of the response. The iterator yields its items, not the pages. The page helper stays (request, response) -> next request | None.
  • resume= names an optional helper (page request, item) -> request that resumes after that item. The stream sample's helper sets from_offset to the item's offset plus 1.
  • The iterator is a PollIterator, in a new _poll.py module of the package, with next_request. After an item, it is the resume helper's request. After a page's last item, or after a page with no item, it is the page helper's request. It is None after the last page. A caller saves it and resumes with it.
  • Each kind of iterator gets it. That is the operation functions of both targets, the methods of a client extension, the service object of a service with no endpoint, and resource methods.

nexgen refuses items that names no field of the response or a field that isn't a list, resume with no items, and a resume helper that isn't a support helper path.

The stream sample's read takes items="records" and the resume helper, so stream.iter_read() yields each Record. The poll-service sample's feed takes items="executions", so the iterators of a service with no endpoint and of its resource method yield items, in Workflow code and in a client. Its response now declares executions, with the Workflow execution info of the proto-backed showcase.

TypeScript and .NET get item polls with their client targets. Go and Java ignore @nexus.poll, as before.

It is for review here before it goes upstream. It sits on the upstream stack temporalio#308, temporalio#310, temporalio#311, temporalio#297, temporalio#296, temporalio#303, temporalio#304, temporalio#309, temporalio#318, temporalio#319, temporalio#320, temporalio#321, temporalio#322, temporalio#323, temporalio#324, temporalio#325, whose head is review/p3-base, and on #77, #79, #81, #83, #86, #88, #90.

Why?

The Stream API of the proposal reads Records one by one, and a reader saves its place to resume after a restart. The page iterator of temporalio#325 yields responses, so each caller looped over the Records and tracked the offset itself.

The design put one PollIterator class in each module that has an item poll. This PR puts it in one module of the package, which each module imports.

How did you test it?

A Python test reads two pages with an empty one between them, and checks next_request after each item and after the last page. Another checks that an empty page keeps its offset. The poll-service tests read the feed's items from a client, from a resource method, and from Workflow code against the test server. Rejection fixtures cover each refusal.
cargo validate passes.

`@nexus.poll items=` makes the iterator yield the items of each page, and `resume=` names the helper
that resumes after one item. The iterator's `next_request` lets a caller save its place.
@moetemp

moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner Author

Duplicate of #92, which has the same commit.

@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