Skip to content

feat: emit Go transfer type converters for proto-backed models - #205

Open
dplyukhin wants to merge 5 commits into
mainfrom
go-transfer-types
Open

dplyukhin wants to merge 5 commits into
mainfrom
go-transfer-types

Conversation

@dplyukhin

@dplyukhin dplyukhin commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Do not merge before temporalio/sdk-go#2703.

Before this PR, Go converted operation models to protos by calling toProto(ctx) before handing the result to ExecuteOperation. That isn't consistent with Python, .NET, and Typescript.

The PR attaches a transfer type converter to the model type, so that inner user payloads (Args, SignalArgs, Memo, UserMetadata) are encoded during the SDK’s payload-conversion call. We need this for @nexus.serialization-context.

Behaviour changes

  • A proto-backed operation model can no longer be a workflow's top-level return value or an
    activity argument. Converting one outside a workflow fails with can only be converted inside a workflow, matching Python's equivalent RuntimeError.
  • Nexus conversion failures now surface on the returned future rather than synchronously.
  • An @nexus.omited field can no longer feed a resource-return constructor argument; this is
    now a UnsupportedGoProtoConversion error.

Latest Go SDK dependency

Updated to temporalio/sdk-go#2703 head 1e5a27aa2a2df781a2b0b119e03749ff66443161 (v1.49.1-0.20261005152832-1e5a27aa2a2d). This is a dependency update; the nexgen PR still targets main.

  • Emit workflow.NewTransferTypeConverter with four callbacks instead of the removed six-callback NewContextAwareTransferTypeConverter.
  • Cache both the converter and its construction error, and return both from the model's value-receiver TransferTypeConverter method.
  • Regenerate the Go samples and document the public behavior in the guide and changelog.

Capability audit

No required capability was removed. Workflow-context callbacks and serialization-context propagation remain available. The integration tests confirm that nested user payloads are converted before the proto envelope, the envelope gets the Nexus serialization context, and nested payloads retain the calling workflow's serialization context. Redirecting nested payloads to the target workflow remains future @nexus.serialization-context work, not a feature added by this PR.

The SDK now explicitly limits transfer conversion to top-level values, non-pointer model/transfer type arguments, and decoding into *T rather than **T. Generated operation models already use the supported value-type contract. The removed context-free callbacks do not reduce our functionality: they previously returned the same workflow-context-required error as the ordinary context.Context callbacks.

Validation

  • cargo validate passed for Rust, Python, TypeScript, Go, Java, and .NET (using the installed .NET SDK on PATH).
  • cargo test --all-features --test generate_go: 59 passed.
  • Advanced Go sample go test ./... passed against the pinned SDK head.

@dplyukhin
dplyukhin marked this pull request as ready for review September 29, 2026 17:31
@dplyukhin
dplyukhin requested a review from a team as a code owner September 29, 2026 17:31
Generated Go code converted operation models to protos eagerly, calling
toProto(ctx) at the call site before handing the result to
ExecuteOperation. That made Go the odd one out: Python, .NET, and
TypeScript all perform model<->proto conversion inside the payload
converter, so the SDK's chosen converter also encodes the model's inner
user payloads (Args, SignalArgs, Memo, UserMetadata).

Emit workflow.TransferTypeConverter for top-level operation inputs and
outputs instead, and pass the model itself to ExecuteOperation. The SDK
now drives conversion, so inner payloads are encoded by the converter the
SDK selected for the operation. This is a prerequisite for supporting
@nexus.serialization-context in Go.

@nexus.source fields move onto the model as unexported fields, populated
in the generated operation function where a workflow.Context is in scope,
and read back in FromProto so sourced fields round-trip.

Behaviour changes:

- A proto-backed operation model can no longer be a workflow's top-level
  return value or an activity argument. Converting one outside a workflow
  fails with "can only be converted inside a workflow", matching Python's
  equivalent RuntimeError.
- Nexus conversion failures now surface on the returned future rather
  than synchronously.
- An @nexus.omit'ed field can no longer feed a resource-return
  constructor argument; this is now a clear UnsupportedGoProtoConversion
  error rather than silently broken code.

Converters are emitted only for top-level operation inputs and outputs,
not for every proto-backed model. Override-converter types and
resource-return/output-transform outputs keep the eager proto path,
because nexgen does not own those types or the planner emits no usable
model for them.

Depends on temporalio/sdk-go#2703; advanced/samples/go/go.mod pins a
pseudo-version of that branch.
@dplyukhin
dplyukhin added this pull request to stack #207 September 30, 2026 14:42

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