Skip to content

chore(samples): sync the stream sample with the latest temporalio/api#895 - #374

Merged
moetemp merged 59 commits into
mainfrom
moe/up/stream-writer-sync-1106
Nov 13, 2026
Merged

moetemp merged 59 commits into
mainfrom
moe/up/stream-writer-sync-1106

Conversation

@moetemp

@moetemp moetemp commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

What changed?

This PR syncs the stream sample with temporalio/api#895 at 849243a9.

The protos are those of the API PR, as is. The WIT is too, except for one part. The API's append and close take an optional producer parameter, and that needs a generator change that main doesn't have yet, so the sample's two methods take none. A Stream ref names its store, append returns the whole response and takes an optional sequence, an offset is opaque bytes, and the resource's publish is now append. What nexgen doesn't support yet stays a TODO comment in the WIT.

It also has #407, which makes a list<u8> resource method parameter bytes when it fills a proto bytes field. The stream read needs it to take its from_offset as bytes.

Why?

The sample WIT is a copy of the WIT in temporalio/api#895, so it follows that PR.

How did you test it?

The regenerated sample and its tests, and a Rust unit test for the bytes parameter. cargo validate passes.

tconley1428 and others added 27 commits November 5, 2026 11:01
A resource with `@nexus.type-parameter "<alias>"` is generic in Python, TypeScript and .NET. An
operation that returns it, or that its method binds, takes a runtime type for each type parameter
of its output, so a response decodes its generic values.
The kept fixtures cover an undeclared type parameter, a generic resource in a record field or in a result with no proto message, and a language that refuses it. The others test directive syntax, rare name clashes or another copy of a kept check.
Co-authored-by: Tim Conley <timothy.conley@temporal.io>
A resource that uses a type parameter, also through its records, is generic in it, as a record
is. So a resource needs no annotation, and `@nexus.type-parameter` is valid only on a type alias
again.
Only a returned resource gives its type parameters, as the guide says, so a
parameter or field that holds one doesn't. The declaration order doesn't change
when a method moves.
A list, map, tuple, result or variant case builds the resource from the record's
message too, so it gets no type argument either.
The old reason said a proto message holds the type arguments, which it doesn't.
Two type parameters such as `body` and `body-t` give the same runtime type name,
and a method can take it too. Either one makes a duplicate parameter or member.
The typed hook of a generic response took only the request, so the terminal
decoded `ReadRecordsResponse[Turn]` with the plain class and lost `Turn`.
C# generics are invariant, so the `<object>` checks refused a `Stream<Turn>` call.
The dispatch now compares generic type definitions and keeps the call's types.
A subclass such as `class TurnStream(Stream[Turn])` has no `__orig_class__`, so
the handle reads `__orig_bases__` too. A factory tests `body_type is None`,
since a class can be falsy.
The TypeScript stream test now decodes a body with a runtime type. The Python
test decodes to the bare handle class, since a generic alias fails for another
reason.
No release has the Python constructor change, so it belongs with the added
entry. The fixed entry now describes the System Nexus dispatch fixes.
A few comments used "name" as a verb, ran over two lines or over 100 columns.
The guide's first paragraph read as one long sentence.
Drop the tests that repeat another test or restate generated code, and keep the
ones that guard behavior. Shorten the guide section and the comments.
Python can't subscript a function, so each generic call is an object whose
subscript binds the types, as in `client.get_stream[Turn](ref=ref)`. A factory's
optional field defaults to `None`.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
`@nexus.close` marks the method that ends a resource. Python calls it at the end of `async with`,
and a call that returns the resource returns a `ResourceCall`.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
`@nexus.varargs` makes a resource method take a list's items as positional arguments, and a list of
a flattened one-field record takes that field's values. The Stream's publish takes values and
returns the last offset.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
Workflow code gets a handle on an existing Stream with `get_stream[T]`, from the fields of its ref,
with no call.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
Each client call and client resource method takes `rpc_metadata` and `rpc_timeout`, and passes
them to the `start_operation` of its Nexus client.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
`@nexus.flatten-in-api` on a request field makes that call take the fields of the field's record,
and the models keep the record. The Stream create takes the id, the owner and the backend of its
ref this way, and the other Stream calls keep `ref`.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
A field can leave the API of one target and take a source in another. A call of a target that omits
a required list sends it empty.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
@moetemp moetemp added the skip-changelog No user-facing changelog fragment required label Nov 6, 2026
temporalio/api#895 at 23fac086 drops `StreamWriter` for a plain `producer`, moves the offset into
the read items, and makes the required fields required. The WIT is the API's as is, and the
support helpers are the `producer` sources that it names.
moetemp added a commit to temporalio/api that referenced this pull request Nov 11, 2026
That head has the sample synced to this WIT. Its nexgen code is the same as at the earlier pin.
The API dropped the read position, the close item and the client epoch. The `read` parameter needs #407 to be `bytes`.
moetemp added a commit that referenced this pull request Nov 12, 2026
# Conflicts:
#	GUIDE.md
#	src/planning/resource_resolution.rs
The tree of #406 with `main` matches the combined base that this branch has, so the tree stays the same.
@moetemp
moetemp changed the base branch from moe/up/upstream-combined-1111 to moe/up/bytes-alias-1110 November 12, 2026 17:59
… its field (#407)

* Typed a `list<u8>` method parameter of a proto `bytes` field as bytes.

A proto-backed record reads that field as `bytes`, so a list of integers could not fill it.

* Regenerated the stream sample with the bytes parameter.

The stream `read` takes its `from_offset` as `bytes` in Python, TypeScript and .NET.
Base automatically changed from moe/up/bytes-alias-1110 to main November 12, 2026 18:13
The squash merge of #406 has the same tree as the #406 head that this branch has, so the tree stays the same.

/// @nexus.doc "Append one batch. Workflow code makes the call from a Local Activity."
// Append returns the whole response, so the caller reads both the first and the last offset.
/// @nexus.output-transform python-type="bytes" python="_support.last_offset(result)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed your mind about the return here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed, let's not do this transformation.

@moetemp
moetemp marked this pull request as ready for review November 12, 2026 23:03
@moetemp
moetemp requested a review from a team as a code owner November 12, 2026 23:03
@moetemp
moetemp marked this pull request as draft November 13, 2026 00:37
moetemp and others added 3 commits November 12, 2026 21:48
The API renamed `backend` to `store` in the Stream ref and dropped the `append` result transform.
So `append` returns the `AppendRecordsResponse` in every target. The two optional `producer`
parameters of the API's WIT are not in this sync, since they need a generator change.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
The API gave `append` an optional `sequence`, so a caller can number a batch and the Store can
dedupe a resent one. The optional `producer` parameter still waits for the generator change.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
The API now says that two offsets of one Stream compare bytewise. It also says that Workflow code
on a Store writes through a Local Activity. Only comments changed, so the samples only move in docs.

Co-authored-by: Tim Conley <timothy.conley@temporal.io>
@moetemp
moetemp added this pull request to stack #411 November 13, 2026 18:26
@moetemp
moetemp marked this pull request as ready for review November 13, 2026 18:39
@moetemp
moetemp merged commit 6f49bff into main Nov 13, 2026
5 checks passed
@moetemp
moetemp deleted the moe/up/stream-writer-sync-1106 branch November 13, 2026 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog No user-facing changelog fragment required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants