Add gRPC support to Pact.
We should note that there are four kinds of services:
- Unary RPCs
- Server streaming RPCs
- Client streaming RPCs
- Bidirectional streaming
Should they be included in the formulation of the consumer contract?
TODO: Specify what a successful implemtation of gRPC support in Pact looks like
As suggested by @bootstraponline, we should look into https://github.com/grpc-ecosystem/grpc-gateway. Since grpc-gateway
converts to rest, it seems that some of the streaming services may not translate well. Additionally, this requires existence of protos and annotations.
Would be used in provider tests
Another option is something like what I tried with GraphQL by using a GraphQL specific
interaction
, which behind the scene is marshalled into a standard Pact HTTP request (see Pact JS: https://github.com/pact-foundation/pact-js/blob/feat/message-pact/examples/graphql/consumer.spec.ts#L27-L49). The interface could something that represents or even accepts a valid gRPC definition.This won't work natively over the wire with protobufs/gRPC (due to the binary-ness of the payload) but perhaps this sort of thinking could work. We could fork the concept into two different potential implementation solutions:
1. Preserve core Pact libraries and convert gRPC in the wrapper libraries
Essentially, this option uses the existing pact infra, wrapping it in a "gRPC" interface to trick the system. We would hook into the infrastructure created for Message Pact (see https://gist.github.com/bethesque/c858e5c15649ae525ef0cc5264b8477c and diagrams at https://github.com/pact-foundation/pact-message-demo#how-it-works---consumer-side) to leverage the proxy layer to do this work, preserving as much as possible, the DSL.
The proxy layer would be modified to:
metadata
field to help with the conversion processThe advantage is that the core Pact library does not need to know about all of these interfaces, the downside is that it's more work for wrapper languages.
2. Upgrade Pact libraries to handle gRPC and store in pact files (possibly with custom format)
The underlying Ruby mock service that we use in Pact JS/Go/Python/... would need to be able to (from the consumer side):
a) receive valid grpc interactions from consumers during mock setup
b) take the gRPC message, and convert into a specific interaction type that can be marshalled into the JSON pact file
c) be able to receive and respond with gRPC compatible payloads
The benefits of this approach, are that the client wrappers (e.g. Pact JS, Go etc.) don't need to change much. The downside is that now Pact must be acutely aware of gRPC, which is something we've been trying to avoid .