Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocol versioning #65

Closed
jsafrane opened this issue Jul 26, 2017 · 5 comments
Closed

Protocol versioning #65

jsafrane opened this issue Jul 26, 2017 · 5 comments

Comments

@jsafrane
Copy link
Contributor

There should be a chapter that explains evolution of the API. There is Version field in every request, but I don't understand how does it allow us to make API breaking changes.

Let's assume that we need to change the API in backward-incompatible way to 2.0.0, e.g. by changing type of CreateVolumeRequest.name from string to map<string,string>. Note that this example is purely synthetic and meant just to demonstrate an incompatible API change.

API 1.0:

message CreateVolumeRequest {
  Version version = 1;
  string name = 2;
  ...
}

API 2.0:

message CreateVolumeRequest {
  Version version = 1;
  VolumeName name = 2;
  ...
}

message VolumeName {
  map<string, string> values = 1;
}

How will CreateVolumeRequest.version help us in any way? I am looking at golang gRPC implementation and it always parses whole message. A server that knows v2.0 version of the API won't be able to parse v1.0 CreateVolumeRequest because field with nr. "2" will have unexpected type (string instead of VolumeName). Is there any magic beyond simple tutorials on grpc.io that would allow a server to peek into CreateVolumeRequest.version to decide which API definition to choose for parsing whole message?

@cpuguy83
Copy link
Contributor

In this case you wouldn't change the type of the field at position 2.

Instead add a new field with the desired type at the next ordinal position (3 in the example) and rename the old field (obsolete_name or v1_name, for example).
The 2 position would be retired at this point and should not be used again.
WIth renaming, old client code should still work, and server code can check the obsoleted values if it wants to maintain compatibility.

Note, while I've done some work with protobufs, it's definitely far from extensive.

@jieyu
Copy link
Member

jieyu commented Aug 1, 2017

Anyone here knows if there is a standard way of doing versioning and version negotiation in gRPC?

FYI: I asked this in the gRPC mailing list:
https://groups.google.com/forum/#!topic/grpc-io/MTpZYrte4-Y

@akutz
Copy link
Contributor

akutz commented Aug 8, 2017

Hi @jsafrane and @jieyu,

The gRPC folks expect that your code should always be backwards compatible. Besides, gRPC itself can largely handle additive changes. A message with a single field will parse data that has two fields by ignoring the second field.

To @jsafrane's point about breaking changes, perhaps we should consider relocating the version field into the gRPC message metadata, which can then be parsed out via a gRPC interceptor.

That way the message is approved or rejected before it is ever routed to the correct (or rather intended) handler.

Please see the GoCSI client for an example on injecting a message with metadata and the server that extracts said data.

@jdef
Copy link
Member

jdef commented Aug 11, 2017

Seems related: #18 (comment)

TL;DR maybe keep in mind use cases where people are adapting gRPC to other protocols

@saad-ali
Copy link
Member

saad-ali commented Nov 1, 2018

This issues is obsolete considering version was dropped from all RPCs. Closing issue.

@saad-ali saad-ali closed this as completed Nov 1, 2018
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

No branches or pull requests

6 participants