gRPC server and client in OCaml

Hey @blandinw, this is very cool work! I’m definitely interested in accommodating any changes to h2 that make using gRPC possible .

I didn’t yet look at your changes in detail, though last time @EduardoRFS spent a little time making this work he came up with this PR.

Note that the Reqd abstraction already sends HEADERS and DATA frames for you, so it might just be that all you need are the changes in Eduardo’s PR. I’m not too familiar with gRPC so I’d appreciate your guidance here.

Feel free to email me or start a discussion in the repo and we can get a plan going for implementing this.

5 Likes

@anmonteiro Sounds good, Eduardo’s changes look pretty similar to mine. You don’t need to look at the commit, I’ll get back to you with a clean PR and we can take it from there :slight_smile:

1 Like

Awesome, thanks! Let me know if you need help setting anything up – it should mostly be straightforward but I don’t use OPAM so that workflow could be broken.

1 Like

I see that a PR has landed in h2, is there any other work I can follow @blandinw?

Hey Ulrik, thanks for following up! My goal here was to provide an example of production-grade gRPC clients and servers using OCaml + Envoy, since I had come across some skepticism about the viability of OCaml in a service-oriented architecture.

I submitted a pull request to ocaml-h2 while the changes needed were still fresh in my mind. The patch enables a pure OCaml implementation of gRPC (no HTTP1 / no Envoy). Once a new version of h2 is uploaded to opam with my changes, I’ll update ocaml-grpc-envoy#http2 to use it.

The next step would be to extract the gRPC layer into a library. Ideally, the library would generate client and server stubs (probably as an extension to ocaml-protoc). The library should also implement the native gRPC protocol, and eventually pass the official interop test suite.

Regarding following progress, I’ll update the ocaml-grpc-envoy if/when I get to it. I won’t be starting work on a gRPC library until I have a real need for it, for motivation and quality reasons. To be honest, I’d also love to build it on top of multicore and with most invariants encoded in the type system, but I need more hammock time to do that.

8 Likes

After reading through @blandinw ocaml-h2 examples, I found that Issuu’s ocaml-protoc-gen can read service definitions and create encoder / decoder functions against them. The only piece missing was outputting the ‘endpoint’ path in the generated module, but I currently have that hacked in on a local branch. Just to test it out I created a couple of naive functions, one to get a ‘grpc connection’ from h2 and another one to make a gRPC request against it by passing in the types and service definition from ocaml-protoc-gen. Zero error handling at the moment and hardcoded to assume Lwt, but still, typed gRPC from OCaml with very little friction looks very possible indeed!

A sample of what it looks like:

  let open Address.Address in
  let* conn = grpc_connect "localhost" 50051 in
  let payload = AddressLookupRequest.make ~country: "FRA" ~postcode: "64000" () in
  let* response = 
    make_request conn AddressLookup.lookupAddress payload
  in    
  List.iter print_endline response.towns

I put in an issue on ocaml-protoc-gen to see if they would accept a PR to emit the endpoint path with the service definition in the module, which is what I hacked into it locally to achieve the above.

There would be a lot more to do as @blandinw suggested, but with service definitions parsed by ocaml-protoc-gen and his patch to ocaml-h2 the foundations are there.

5 Likes

@lepoetemaudit Can I ask what happened to your exploration? I can see the issue is still open even if there is a PR to make the requested changes.

2 Likes

We started using grpc with OCaml. We have an internal fork of GitHub - jeffa5/ocaml-grpc: GRPC implementation in OCaml. We are currently stress testing the application -@quernd is leading it. The results are encouraging for our use case (low latency, relatively high throughput for 10-100 connections, bidirectional streaming). We should start using it in production in early December. At some point we also investigated what it would take to start using grpc-core (the C library) for the transport layer and it doesn’t seem too difficult. It’s possible we will switch to it. That said the current implementation is obviously interesting for other setups like Mirage.

11 Likes

I would be very interested in a release of such work. In the mean time I wrote a binding to grpc-core , but still very POCish: libgrpc . There is also a link grpc-protoc-plugin between ocaml-protoc-plugin and libgrpc. The general POC is to use chaincode (smartcontract) written in OCaml in Hyperledger Fabric: GitHub - bobot/fabric-chaincode-ocaml: OCaml support for smart contracts in Hyperledger Fabric

1 Like

what would you be interested in specifically? I’m asking bc our stack might be less reliable than your experiment. It’s really cool to see some libgrpc bindings.We might consider a switch to such solution sometime in Q1 2022.

Mainly to understand better howto implement the different kind of service in GRPC (one-one, stream-client, stream-server,bidirectionnal). If one wait for the wrong message or at the wrong time, it is very easy to deadlock. fabric-chaincode-ocaml/helpers.ml at 5272b17ae2d4c219af90e12cda6d37d148a51030 · bobot/fabric-chaincode-ocaml · GitHub
An OCaml implementation also as the advantage to avoid to think about C object lifetime that are not easy to get right in the interaction with grpc-core.

1 Like

Ah. I see. All fair points and I believe our work does address the points you’ve raised. We tested both the client and server with different scenarios and the point about lifetime of C values is worth considering. It has to go through a good cycle on production and we will release it.

2 Likes