RSDK-13144: Bidirectional grpc arbitrary metadata passing #6049
RSDK-13144: Bidirectional grpc arbitrary metadata passing #6049aldenh-viam wants to merge 4 commits into
Conversation
…from server to client via headers)
fda0809 to
f0a1dfc
Compare
| info *grpc.UnaryServerInfo, | ||
| handler grpc.UnaryHandler, | ||
| ) (any, error) { | ||
| ctx, md := ContextWithMetadata(ctx) |
There was a problem hiding this comment.
This upgrades every context to the ContextWithMetadata, which is akin to the current behavior: server writes its arbitrary metadata (if any) to headers regardless and client only decides whether to read it. The client choosing to not read it does not help save bandwidth.
To make this forwarding optional depending on whether the client wants the metadata or not, we'd need another metadata key, something like VIAM_FORWARD_METADATA=T/F
|
gonna untag myself and tag @danielbotros |
f0a1dfc to
b742bcd
Compare
b742bcd to
6d145e1
Compare
6d145e1 to
e8049d2
Compare
e8049d2 to
e156460
Compare
006a40d to
149f485
Compare
149f485 to
d4e5f40
Compare
d4e5f40 to
f5cc713
Compare
| keys := header.Get(arbitraryMetadataKey) | ||
| if len(keys) > 0 { | ||
| mdMap[arbitraryMetadataKey] = keys | ||
| for _, k := range keys { | ||
| v := header.Get(k) | ||
| if len(v) > 0 { | ||
| mdMap[k] = v | ||
| } | ||
| } |
There was a problem hiding this comment.
This is technically a breaking change, in that the original ContextWithMetadataUnaryClientInterceptor would forward all headers (including opid and SafetyMonitoredResourceMetadataKey), while the updated one only forwards the user-provided ones (registered automatically if you use contextutils.SetHeader instead of grpc.SetHeader). However, given that the original only worked inside viam-server (not across modules), and the only usages are in utils/contextutils/context_test.go and components/camera/client_test.go I expect this change to be safe.
Refresher on metadata passing in both directions: https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-and-receiving-metadata---client-side
Server-to-client (pass arbitrary metadata via headers):
ContextWithMetadataUnaryClientInterceptortoContextWithMetadataServerToClientUnaryClientInterceptorClient-to-server (pass arbitrary metadata via context):
contextutils.AppendToOutgoingContexthelper that records the arbitrary keys to avoid mixing with internal (grpc or viam) keys.I will add these for streaming interceptors next. It should look very similar.
Example
I have a robot with 2 modules and a RobotClient that calls DoCommand on module 1, which calls GetImages on module 2.
The RobotClient sets arbitrary metadata:
module 1 sets:
module 2 sets
Module 1 sees the arbitrary metadata from RobotClient & module 2
Module 2 sees the arbitrary metadata from RobotClient & module1
RobotClient sees the arbitrary metadata from modules 1 & 2
Keys will be merged as needed.
The above will also work for viam-server built-ins, such as if I updated the fake sensor's
GetReadingsto return some arbitrary metadata.These interceptors will run on every GRPC hop, so it will come with a non-zero performance hit, but it should be barely noticeable with 0 or very few arbitrary metadata.
cc @viamrobotics/netcode