Skip to content

feat: flatten some fields of one request field - #86

Closed
moetemp wants to merge 1 commit into
review/p3-sourcesfrom
review/p3-flatten
Closed

moetemp wants to merge 1 commit into
review/p3-sourcesfrom
review/p3-flatten

Conversation

@moetemp

@moetemp moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner

What changed?

This PR lets @nexus.flatten-in-api go on a field, to flatten only some fields of the field's record.

record create-stream-request {
  /// @nexus.name python="id" typescript="id" dotnet="Id"
  stream-id: string,
  /// @nexus.flatten-in-api fields="backend" fill="id=stream-id"
  %ref: option<stream-ref>,
}
  • fields names the fields of the record that become parameters of the call, in that order.
  • fill="<field>=<sibling>" sets a field of the record from a sibling field of the request, after the sibling's parameter or source. A sourced sibling runs once, into a local.
  • The call sets the field when it sets a promoted field or a fill applies. The Stream create always sets ref, since its fill always applies.
  • Python, TypeScript and .NET generate it, in each target that they have. Go puts the promoted fields in the options struct of the operation, with Go's empty-is-omitted rule. Java doesn't generate proto-backed models, so it refuses such a record already.

nexgen refuses a flatten on a field whose type isn't a proto-backed record, an unknown field or argument, a fill with no =, a required field of the record that the call doesn't give, a promoted field with the name of a sibling, a fill from an omitted field or of another type, a flatten together with a source or an api-omit, and a flatten of a record that flattens all of its fields already.

The Stream create takes id and backend now, as in client.create_stream(Turns, id="s1", backend="redis"), and the ref copies the id. The Workflow create copies the id from its source. A new sample, worker-shutdown, shows the flatten in all four languages. Its request takes the SDK fields of the worker heartbeat, and the heartbeat copies the worker fields of the request.

The TypeScript request of an operation now writes { id } in place of { id: id }.

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.

Why?

The Stream API of the proposal has client.create_stream(definition, *, id, backend=None, **options). The create request holds the backend in its ref, and the id twice, in stream_id and in ref.id. A record-level flatten would promote every field of StreamRef for every request that holds one.

The design also had param= and keep=, which flatten a parameter of a resource constructor in a handle factory. They move to the factory PR, since only the factory reads them.

How did you test it?

A Python test creates a Stream with a backend and checks ref=StreamRef(id="s1", backend="redis") in the request, and stream_id and the ref on the wire. The Python and TypeScript tests of the Workflow create check that the ref copies the id from the source. A .NET compile check creates a Stream with Backend. Go, Python and TypeScript tests run the worker-shutdown call and check the heartbeat, and a .NET compile check calls it. A Go test checks a fill from a sourced sibling, a unit test checks the keys of the flatten, and rejection fixtures cover each refusal.
cargo validate passes.

`@nexus.flatten-in-api fields="..." fill="<field>=<sibling>"` on a field makes the call take the
named fields of its record, and copies sibling fields into the others. The Stream create takes the
backend of its ref this way, and the ref copies the id.
@moetemp

moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner Author

Duplicate of #85, 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