-
Notifications
You must be signed in to change notification settings - Fork 419
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
Conformance to GRPCProtobufPayload generates wrong code when using ProtoPathModuleMappings
option
#801
Comments
Thanks for the super detailed issue and repro @jagobagascon! At the moment the codgen will generate the conformance based on the input and output types of the The rationale for this was that files containing just Perhaps that was the wrong approach and we should generate conformance for the messages passed to us. Since One concern I have is that SwiftProtobuf could vend more In summary, I think I'm leaning towards:
|
Any thoughts on this @Lukasa? |
Wow, awkward. Let me restate my understanding of the problem here in less-Protobuf/more-Swift terms. The The codegen will operate on a bunch of The problem is that some protobufs are defined by SwiftProtobuf. We can use for this example SwiftProtobuf.Google_Protobuf_Empty, but there are several others inside SwiftProtobuf. When used in service protos, these need to be conformed to The problem is that we are breaking the rule of Swift conformances: thou shalt only conform a type to a protocol when you own either the type or the protocol. In this case, as the conformances are emitted by codegen, "thou" is equivalent to "the module owned by the user into which we generate code". That's why it's not a problem for most use-cases: if the user is using custom user-defined proto messages, the user owns the type. They meet the criteria for extension, and so may conform the type to whichever protocol they want. However, for the proto messages owned by SwiftProtobuf, the user owns neither the type (it's owned by SwiftProtobuf) or the protocol (owned by GRPC). Thus they are in violation of the rule of Swift conformances. This is one of many manifestations of this kind of problem. There are two solutions, I think. One is the one @glbrntt has outlined above: bring the protocol conformances into GRPC. This basically works fine so long as protobuf doesn't add new proto messages, and even if it does the problem can be nicely resolved by updating GRPC. The second solution is to remove the protocol altogether. I have to admit that I'm a bit unsure why GRPC cannot simply take That said, I think the first proposal probably gets my vote. I think the risk of breakage is low, and easily mitigated if it happens. It makes things substantively easier to work with without breaking or invalidating wide swathes of code. So I think I'm in favour of going that way. |
Another thing that concerns me is that with the current approach Both of the changes proposed (apart from fixing this bug) would also make the code generation more consistent, because the generated code would be the same in both cases. |
To support different payloads (e.g. FlatBuffers) the public API for creating RPCs uses message types which conform to
To clarify: is your vote for only adding the conformance to the |
Yes, indeed: we'd need to accept
I think that ought to be sufficient, no? |
It's sufficient to fix the problem but I don't think it's optimal. The reason for generating the conformance the way we did was to support the messages whole files we don't have, specifically those provided by SwiftProtobuf. With that now gone I think generating the conformance when we're passed the file is probably for the "stability" reasons @jagobagascon pointed out. We can do these separately, of course. |
Maybe it's just me, but I don't have a clear handle on what you're proposing here @glbrntt. Mind elaborating? |
Eugh, yeah, that was pretty horrendously written! I'm proposing two changes: the first is the add conformance for The second change I'd like to make is to generate the |
Ok, fab, I am in favour of both changes then. |
@jagobagascon this is resolved by #811, please let us know if you have any more problems! |
…rver Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjust the server components such they only support SwiftProtobuf. Once the client side has had the same treatment (and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`), support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
…rver Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjusts server components such that they are not constrained to `GRPCPayload`. At the moment only `SwiftProtobuf.Message` is supported. Once the client side has had the same treatment and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`, support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
…rver Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjusts server components such that they are not constrained to `GRPCPayload`. At the moment only `SwiftProtobuf.Message` is supported. Once the client side has had the same treatment and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`, support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
…rver Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjusts server components such that they are not constrained to `GRPCPayload`. At the moment only `SwiftProtobuf.Message` is supported. Once the client side has had the same treatment and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`, support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
…rver Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjusts server components such that they are not constrained to `GRPCPayload`. At the moment only `SwiftProtobuf.Message` is supported. Once the client side has had the same treatment and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`, support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
…rver (#886) Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: #738, #778, #801, #837, #877, #881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR adjusts server components such that they are not constrained to `GRPCPayload`. At the moment only `SwiftProtobuf.Message` is supported. Once the client side has had the same treatment and `GRPCProtobufPayload` no longer inherits from `SwiftProtobuf.Message`, support for `GRPCPayload` will be added back. Modifications: - The `HTTP1ToGRPCServerCodec` has had the message encoding and decoding removed. It now deals in `ByteBuffer`s rather than request/response messages. - An additional `GRPCServerCodecHandler` which sits between the `HTTP1ToGRPCServerCodec` and `_BaseCallHandler` has been added which serializes/deserializes messages. - Custom payload tests have been commented out. They will return when the transition has completed. Result: - Servers only support SwiftProtobuf - Genertic constraints on the server have been removed; the constraints are place on the `init` of public handlers instead. - `GRPCProtobufPayload` is no longer required on the server.
Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR builds on grpc#886 by increasing the surface area of the client APIs so that they are not constrained to `GRPCPayload`. The surface API now has variants for `GRPCPayload` and `SwiftProtobuf.Message`. Internally the client deals with serializers and deserializers. Modifications: - `GRPCClientChannelHandler` and `GRPCClientStateMachine` are no longer generic over a request and response type, rather they deal with the serialzed version of requests and response (i.e. `ByteBuffer`s) and defer the (de/)serialization to a separate handler. - Added `GRCPClientCodecHandler` to handle (de/)serialization of messages - Clients are no longer constrained to having their request/response payloads conform to `GRPCPayload` - Conformance to `GRPCProtobufPayload` is no longer generated and the protocol is deprecated and has no requirements. - Drop the 'GenerateConformance' option from the codegen since it is no longer required - Reintroduce a filter to the codegen so that we only consider files which contain services, this avoids generating empty files - Regenerate code where necessary Result: - `GRPCProtobufPayload` is no longer required
Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR builds on grpc#886 by increasing the surface area of the client APIs so that they are not constrained to `GRPCPayload`. The surface API now has variants for `GRPCPayload` and `SwiftProtobuf.Message`. Internally the client deals with serializers and deserializers. Modifications: - `GRPCClientChannelHandler` and `GRPCClientStateMachine` are no longer generic over a request and response type, rather they deal with the serialzed version of requests and response (i.e. `ByteBuffer`s) and defer the (de/)serialization to a separate handler. - Added `GRCPClientCodecHandler` to handle (de/)serialization of messages - Clients are no longer constrained to having their request/response payloads conform to `GRPCPayload` - Conformance to `GRPCProtobufPayload` is no longer generated and the protocol is deprecated and has no requirements. - Drop the 'GenerateConformance' option from the codegen since it is no longer required - Reintroduce a filter to the codegen so that we only consider files which contain services, this avoids generating empty files - Regenerate code where necessary Result: - `GRPCProtobufPayload` is no longer required
Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: grpc#738, grpc#778, grpc#801, grpc#837, grpc#877, grpc#881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR builds on grpc#886 by increasing the surface area of the client APIs so that they are not constrained to `GRPCPayload`. The surface API now has variants for `GRPCPayload` and `SwiftProtobuf.Message`. Internally the client deals with serializers and deserializers. Modifications: - `GRPCClientChannelHandler` and `GRPCClientStateMachine` are no longer generic over a request and response type, rather they deal with the serialzed version of requests and response (i.e. `ByteBuffer`s) and defer the (de/)serialization to a separate handler. - Added `GRCPClientCodecHandler` to handle (de/)serialization of messages - Clients are no longer constrained to having their request/response payloads conform to `GRPCPayload` - Conformance to `GRPCProtobufPayload` is no longer generated and the protocol is deprecated and has no requirements. - Drop the 'GenerateConformance' option from the codegen since it is no longer required - Reintroduce a filter to the codegen so that we only consider files which contain services, this avoids generating empty files - Regenerate code where necessary Result: - `GRPCProtobufPayload` is no longer required
Motivation: To support payloads other than `SwiftProtobuf.Message` we required that all messages conform to `GRPCPayload`. For protobuf messages we added `GRPCProtobufPayload` which provides a default implemenation of `GRPCPayload` for protobuf messages. We generated this conformance for all protobuf messages we saw. This lead to a number issues and workarounds including: #738, #778, #801, #837, #877, #881. The intention is to continue to support `GRPCPayload` in addition to protobuf, however, support for protobuf will not be via the `GRPCProtobufPayload` protocol. This PR builds on #886 by increasing the surface area of the client APIs so that they are not constrained to `GRPCPayload`. The surface API now has variants for `GRPCPayload` and `SwiftProtobuf.Message`. Internally the client deals with serializers and deserializers. Modifications: - `GRPCClientChannelHandler` and `GRPCClientStateMachine` are no longer generic over a request and response type, rather they deal with the serialzed version of requests and response (i.e. `ByteBuffer`s) and defer the (de/)serialization to a separate handler. - Added `GRCPClientCodecHandler` to handle (de/)serialization of messages - Clients are no longer constrained to having their request/response payloads conform to `GRPCPayload` - Conformance to `GRPCProtobufPayload` is no longer generated and the protocol is deprecated and has no requirements. - Drop the 'GenerateConformance' option from the codegen since it is no longer required - Reintroduce a filter to the codegen so that we only consider files which contain services, this avoids generating empty files - Regenerate code where necessary Result: - `GRPCProtobufPayload` is no longer required
New Issue Checklist
Issue Description
We are currently generating our swift code using
ProtoPathModuleMappings
option to split it into different modules. As each module needs to be in its own folder we were generating the code by callingprotoc-gen-grpc-swift
plugin once per module with a different out folder.This causes the following error during swift build:
This issue was fixed in this commit by avoiding the definition of multiple conformances to GRPCProtobufPayload for the same class. But for it to work we had to generate all our protos in the same plugin call and then move the generated code to its module folder:
This is not ideal, but it "fixes" our previous problem. After this change, the
GRPCProtobufPayload
is added only to the first class that needs it. In our example this would bea.grpc.swift
and when trying to compile the code in/module-b
it fails with the following error:I'm not sure what the fix should be. I'm kind of new to swift. I managed to compile the code by adding a protocol that extends
GRPCProtobufPayload
per module and using that.I don't know if this is good practice or not, it feels kinda hacky.
You can use the code in this repo to replicate this problem (tested against
master
branch). It contains aMakefile
with three rules:make generate_single build
: will give you our first errormake generate build
: will give you our second errorThe text was updated successfully, but these errors were encountered: