Use proto-serialized context metadata in gRPC trailers#10269
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 5555616. Configure here.
5709a34 to
cbd44fc
Compare
| protoMsg.Entries[key] = fmt.Sprint(value) | ||
| } | ||
| if protoBytes, err := proto.Marshal(protoMsg); err != nil { | ||
| c.throttledLogger.Warn("ContextMetadataInterceptor: Failed to marshal proto metadata, falling back to legacy-only", |
There was a problem hiding this comment.
nit: This would be quite hard to check when we want to remove legacy format. Pass metricsHandler if possible
There was a problem hiding this comment.
This information is not currently used by the OSS. We should be able to track SaaS with version numbers.
| // Skip entries with HTTP/2-unsafe values (the proto key handles those). | ||
| for key, value := range allMetadata { | ||
| valStr := fmt.Sprint(value) | ||
| if !isHTTP2SafeValue(valStr) { |
There was a problem hiding this comment.
This means you can now potentially miss some of the values (whereas in the past they would fail to start the workflow). It's probably fine, but I'm unsure how exactly those are used in metering, so flagging.
There was a problem hiding this comment.
This should be ok.
Replace per-key trailer format with a single protobuf ContextMetadata message serialized into a contextmetadata-bin trailer key. gRPC automatically base64-encodes -bin values, making arbitrary bytes (including HTTP/2-unsafe control chars) transport-safe. Writer emits both proto and legacy per-key format for backward compatibility during rolling deploys. Reader prefers proto key, falls back to legacy per-key format for old writers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename contextpropagationpb → contextpropagationspb per project lint rules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Writer now logs a Warn when proto.Marshal fails instead of silently dropping the proto key. Reader logs a Warn when proto.Unmarshal fails before falling back to legacy format. Both use throttled loggers to prevent log storms. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cbd44fc to
155a4e4
Compare

What changed
ContextMetadatamessage serialized intocontextmetadata-bintrailer key-binvalue, making arbitrary bytes (including HTTP/2-unsafe control chars) transport-safeTrailerToContextMetadataInterceptorin test server to match production behaviorWhy
Workflow type names containing control characters (newlines, NUL, etc.) cause the gRPC HTTP/2 framer to reject trailer values. A single proto message in a
-binkey is simpler than per-key-binsuffixes: one trailer key, one serialization, no key naming constraints, cleaner backward compat removal.How tested
Risks
Note
Medium Risk
Changes how context metadata is encoded/decoded in gRPC trailers, which can affect cross-version compatibility and observability of propagated metadata. Backward-compatible legacy fallback and extensive unit/integration tests reduce the rollout risk.
Overview
Switches context-metadata propagation in gRPC trailers to a single proto-encoded payload. Server-side
ContextMetadataInterceptornow serializes all context metadata into a newContextMetadataprotobuf and emits it undercontextmetadata-bin, avoiding HTTP/2-unsafe control characters in values.Maintains rolling-deploy compatibility. Writers still emit legacy per-key trailers (skipping unsafe values), and the client-side
TrailerToContextMetadataInterceptornow prefers the proto trailer and falls back to legacy keys (including unprefixed well-known keys) when needed.Adds the new
contextpropagation/v1proto + generated Go types, plus unit tests around proto/legacy behavior and an integration suite (WorkflowTypeEncodingSuite) covering control characters, UTF-8, long names, and-binsuffix workflow types.Reviewed by Cursor Bugbot for commit e1d772f. Bugbot is set up for automated code reviews on this repo. Configure here.