Skip to content

Commit

Permalink
enforce consistency of request and response modes
Browse files Browse the repository at this point in the history
- This adds type safety to ensure the RPCs are called with the
  expected protocol (e.g. you cannot call a unary rpc with a
  server_streaming entry point, etc.).

On the ocaml-protoc-plugin side, currently there are no markers for
the rpc modes - this interface will permit adding them in the future
without user facing changes.

On the ocaml-protoc plugin, the value mode flows from the proto file
definition and is checked in the user code as expected.

Implementation note: There's perhaps a way to shorten the mapping of
value-modes but I couldn't find one given that `Grpc` cannot depend on
`Ocaml_protoc`, and thus the `Value_mode` types are not equal.
  • Loading branch information
mbarbin committed Dec 15, 2023
1 parent 8677baa commit c0c4df5
Show file tree
Hide file tree
Showing 19 changed files with 487 additions and 160 deletions.
2 changes: 1 addition & 1 deletion examples/greeter-client-eio/greeter_client_eio.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ let main env =

let result =
Grpc_eio.Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module Greeter.SayHello))
(Grpc_protoc_plugin.Client_rpc.unary (module Greeter.SayHello))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:(Grpc_eio.Client.Typed_rpc.unary request ~f)
()
Expand Down
3 changes: 2 additions & 1 deletion examples/greeter-protoc-client-eio/greeter_client_eio.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ let main env =

let result =
Grpc_eio.Client.Typed_rpc.call
(Grpc_protoc.client_rpc Greeter_protoc.Greeter.Greeter.Client.sayHello)
(Grpc_protoc.Client_rpc.unary
Greeter_protoc.Greeter.Greeter.Client.sayHello)
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:(Grpc_eio.Client.Typed_rpc.unary request ~f)
()
Expand Down
9 changes: 3 additions & 6 deletions examples/greeter-protoc-server-eio/greeter_server_eio.ml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Grpc_eio

let sayHello rpc =
Grpc_eio.Server.Typed_rpc.unary (Grpc_protoc.server_rpc rpc)
Grpc_eio.Server.Typed_rpc.unary (Grpc_protoc.Server_rpc.unary rpc)
~f:(fun (request : Greeter_protoc.Greeter.hello_request) ->
let message =
if request.name = "" then "You forgot your name!"
Expand Down Expand Up @@ -52,11 +52,8 @@ let serve server env =

let () =
let server =
let { Pbrt_services.Server.package; service_name; handlers } =
Greeter_protoc.Greeter.Greeter.Server.make ~sayHello ()
in
Server.Typed_rpc.server
(With_service_spec { package; service_name; handlers })
Greeter_protoc.Greeter.Greeter.Server.make ~sayHello ()
|> Grpc_protoc.handlers |> Server.Typed_rpc.server
in

Eio_main.run (serve server)
6 changes: 4 additions & 2 deletions examples/greeter-server-eio/greeter_server_eio.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ open Grpc_eio
let say_hello =
let module SayHello = Greeter.Mypackage.Greeter.SayHello in
Grpc_eio.Server.Typed_rpc.unary
(Grpc_protoc_plugin.server_rpc (module SayHello))
(Grpc_protoc_plugin.Server_rpc.unary (module SayHello))
~f:(fun request ->
let message =
if request = "" then "You forgot your name!"
Expand Down Expand Up @@ -53,6 +53,8 @@ let serve server env =
listen ()

let () =
let server = Server.Typed_rpc.server (Handlers [ say_hello ]) in
let server =
Server.Typed_rpc.server (Grpc_protoc_plugin.handlers [ say_hello ])
in

Eio_main.run (serve server)
11 changes: 7 additions & 4 deletions examples/routeguide-protoc/src/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ let client ~sw host port network =
let call_get_feature connection point =
let response =
Client.Typed_rpc.call
(Grpc_protoc.client_rpc Route_guide.RouteGuide.Client.getFeature)
(Grpc_protoc.Client_rpc.unary Route_guide.RouteGuide.Client.getFeature)
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.unary point ~f:(function
Expand Down Expand Up @@ -52,7 +52,8 @@ let print_features connection =

let stream =
Client.Typed_rpc.call
(Grpc_protoc.client_rpc Route_guide.RouteGuide.Client.listFeatures)
(Grpc_protoc.Client_rpc.server_streaming
Route_guide.RouteGuide.Client.listFeatures)
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:(Client.Typed_rpc.server_streaming rectangle ~f:Fun.id)
()
Expand Down Expand Up @@ -82,7 +83,8 @@ let run_record_route connection =

let response =
Client.Typed_rpc.call
(Grpc_protoc.client_rpc Route_guide.RouteGuide.Client.recordRoute)
(Grpc_protoc.Client_rpc.client_streaming
Route_guide.RouteGuide.Client.recordRoute)
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.client_streaming ~f:(fun f response ->
Expand Down Expand Up @@ -144,7 +146,8 @@ let run_route_chat clock connection =
in
let result =
Client.Typed_rpc.call
(Grpc_protoc.client_rpc Route_guide.RouteGuide.Client.routeChat)
(Grpc_protoc.Client_rpc.bidirectional_streaming
Route_guide.RouteGuide.Client.routeChat)
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.bidirectional_streaming ~f:(fun writer reader ->
Expand Down
24 changes: 12 additions & 12 deletions examples/routeguide-protoc/src/server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ let calc_distance (p1 : Route_guide.point) (p2 : Route_guide.point) : int =

(* $MDX part-begin=server-get-feature *)
let get_feature (t : t) rpc =
Grpc_eio.Server.Typed_rpc.unary (Grpc_protoc.server_rpc rpc) ~f:(fun point ->
Grpc_eio.Server.Typed_rpc.unary (Grpc_protoc.Server_rpc.unary rpc)
~f:(fun point ->
Eio.traceln "GetFeature = {:%a}" Route_guide.pp_point point;

(* Lookup the feature and if found return it. *)
Expand All @@ -103,8 +104,8 @@ let get_feature (t : t) rpc =
(* $MDX part-end *)
(* $MDX part-begin=server-list-features *)
let list_features (t : t) rpc =
Grpc_eio.Server.Typed_rpc.server_streaming (Grpc_protoc.server_rpc rpc)
~f:(fun rectangle f ->
Grpc_eio.Server.Typed_rpc.server_streaming
(Grpc_protoc.Server_rpc.server_streaming rpc) ~f:(fun rectangle f ->
(* Lookup and reply with features found. *)
let () =
List.iter
Expand All @@ -118,7 +119,8 @@ let list_features (t : t) rpc =
(* $MDX part-end *)
(* $MDX part-begin=server-record-route *)
let record_route (t : t) (clock : _ Eio.Time.clock) rpc =
Grpc_eio.Server.Typed_rpc.client_streaming (Grpc_protoc.server_rpc rpc)
Grpc_eio.Server.Typed_rpc.client_streaming
(Grpc_protoc.Server_rpc.client_streaming rpc)
~f:(fun (stream : Route_guide.point Seq.t) ->
Eio.traceln "RecordRoute";

Expand Down Expand Up @@ -168,7 +170,8 @@ let record_route (t : t) (clock : _ Eio.Time.clock) rpc =
(* $MDX part-end *)
(* $MDX part-begin=server-route-chat *)
let route_chat (_ : t) rpc =
Grpc_eio.Server.Typed_rpc.bidirectional_streaming (Grpc_protoc.server_rpc rpc)
Grpc_eio.Server.Typed_rpc.bidirectional_streaming
(Grpc_protoc.Server_rpc.bidirectional_streaming rpc)
~f:(fun
(stream : Route_guide.route_note Seq.t)
(f : Route_guide.route_note -> unit)
Expand All @@ -187,13 +190,10 @@ let route_chat (_ : t) rpc =
(* $MDX part-end *)
(* $MDX part-begin=server-grpc *)
let server t clock =
let { Pbrt_services.Server.package; service_name; handlers } =
Route_guide.RouteGuide.Server.make ~getFeature:(get_feature t)
~listFeatures:(list_features t) ~recordRoute:(record_route t clock)
~routeChat:(route_chat t) ()
in
Server.Typed_rpc.server
(With_service_spec { package; service_name; handlers })
Route_guide.RouteGuide.Server.make ~getFeature:(get_feature t)
~listFeatures:(list_features t) ~recordRoute:(record_route t clock)
~routeChat:(route_chat t) ()
|> Grpc_protoc.handlers |> Server.Typed_rpc.server

(* $MDX part-end *)
let connection_handler server ~sw =
Expand Down
24 changes: 15 additions & 9 deletions examples/routeguide-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ The individual service functions from our proto definition are implemented using
```ocaml
let server t clock =
Server.Typed_rpc.server
(Handlers
(Grpc_protoc_plugin.handlers
[ get_feature t; list_features t; record_route t clock; route_chat t ])
```
Expand All @@ -206,7 +206,7 @@ Let's look at the simplest type first, `GetFeature` which just gets a `Point` fr
```ocaml
let get_feature (t : t) =
Grpc_eio.Server.Typed_rpc.unary
(Grpc_protoc_plugin.server_rpc (module RouteGuide.GetFeature))
(Grpc_protoc_plugin.Server_rpc.unary (module RouteGuide.GetFeature))
~f:(fun point ->
Eio.traceln "GetFeature = {:%s}" (Point.show point);
Expand Down Expand Up @@ -238,7 +238,8 @@ Now let's look at one of our streaming RPCs. `list_features` is a server-side st
```ocaml
let list_features (t : t) =
Grpc_eio.Server.Typed_rpc.server_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.ListFeatures))
(Grpc_protoc_plugin.Server_rpc.server_streaming
(module RouteGuide.ListFeatures))
~f:(fun rectangle f ->
(* Lookup and reply with features found. *)
let () =
Expand All @@ -261,7 +262,8 @@ Now let's look at something a little more complicated: the client-side streaming
```ocaml
let record_route (t : t) (clock : _ Eio.Time.clock) =
Grpc_eio.Server.Typed_rpc.client_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.RecordRoute))
(Grpc_protoc_plugin.Server_rpc.client_streaming
(module RouteGuide.RecordRoute))
~f:(fun (stream : Point.t Seq.t) ->
Eio.traceln "RecordRoute";
Expand Down Expand Up @@ -312,7 +314,8 @@ Finally, let's look at our bidirectional streaming RPC `route_chat`, which recei
```ocaml
let route_chat (_ : t) =
Grpc_eio.Server.Typed_rpc.bidirectional_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.RouteChat))
(Grpc_protoc_plugin.Server_rpc.bidirectional_streaming
(module RouteGuide.RouteChat))
~f:(fun (stream : RouteNote.t Seq.t) (f : RouteNote.t -> unit) ->
Printf.printf "RouteChat\n";
Expand Down Expand Up @@ -401,7 +404,7 @@ Calling the simple RPC `get_feature` requires building up a `Client.call` repres
let call_get_feature connection point =
let response =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.GetFeature))
(Grpc_protoc_plugin.Client_rpc.unary (module RouteGuide.GetFeature))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.unary point ~f:(function
Expand Down Expand Up @@ -429,7 +432,8 @@ let print_features connection =
let stream =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.ListFeatures))
(Grpc_protoc_plugin.Client_rpc.server_streaming
(module RouteGuide.ListFeatures))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:(Client.Typed_rpc.server_streaming rectangle ~f:Fun.id)
()
Expand Down Expand Up @@ -466,7 +470,8 @@ let run_record_route connection =
let response =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.RecordRoute))
(Grpc_protoc_plugin.Client_rpc.client_streaming
(module RouteGuide.RecordRoute))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.client_streaming ~f:(fun f response ->
Expand Down Expand Up @@ -535,7 +540,8 @@ We start by generating a short sequence of locations, similar to how we did for
in
let result =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.RouteChat))
(Grpc_protoc_plugin.Client_rpc.bidirectional_streaming
(module RouteGuide.RouteChat))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.bidirectional_streaming ~f:(fun writer reader ->
Expand Down
11 changes: 7 additions & 4 deletions examples/routeguide/src/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ let client ~sw host port network =
let call_get_feature connection point =
let response =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.GetFeature))
(Grpc_protoc_plugin.Client_rpc.unary (module RouteGuide.GetFeature))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.unary point ~f:(function
Expand All @@ -45,7 +45,8 @@ let print_features connection =

let stream =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.ListFeatures))
(Grpc_protoc_plugin.Client_rpc.server_streaming
(module RouteGuide.ListFeatures))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:(Client.Typed_rpc.server_streaming rectangle ~f:Fun.id)
()
Expand Down Expand Up @@ -75,7 +76,8 @@ let run_record_route connection =

let response =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.RecordRoute))
(Grpc_protoc_plugin.Client_rpc.client_streaming
(module RouteGuide.RecordRoute))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.client_streaming ~f:(fun f response ->
Expand Down Expand Up @@ -135,7 +137,8 @@ let run_route_chat clock connection =
in
let result =
Client.Typed_rpc.call
(Grpc_protoc_plugin.client_rpc (module RouteGuide.RouteChat))
(Grpc_protoc_plugin.Client_rpc.bidirectional_streaming
(module RouteGuide.RouteChat))
~do_request:(H2_eio.Client.request connection ~error_handler:ignore)
~handler:
(Client.Typed_rpc.bidirectional_streaming ~f:(fun writer reader ->
Expand Down
13 changes: 8 additions & 5 deletions examples/routeguide/src/server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ let calc_distance (p1 : Point.t) (p2 : Point.t) : int =
(* $MDX part-begin=server-get-feature *)
let get_feature (t : t) =
Grpc_eio.Server.Typed_rpc.unary
(Grpc_protoc_plugin.server_rpc (module RouteGuide.GetFeature))
(Grpc_protoc_plugin.Server_rpc.unary (module RouteGuide.GetFeature))
~f:(fun point ->
Eio.traceln "GetFeature = {:%s}" (Point.show point);

Expand All @@ -100,7 +100,8 @@ let get_feature (t : t) =
(* $MDX part-begin=server-list-features *)
let list_features (t : t) =
Grpc_eio.Server.Typed_rpc.server_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.ListFeatures))
(Grpc_protoc_plugin.Server_rpc.server_streaming
(module RouteGuide.ListFeatures))
~f:(fun rectangle f ->
(* Lookup and reply with features found. *)
let () =
Expand All @@ -116,7 +117,8 @@ let list_features (t : t) =
(* $MDX part-begin=server-record-route *)
let record_route (t : t) (clock : _ Eio.Time.clock) =
Grpc_eio.Server.Typed_rpc.client_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.RecordRoute))
(Grpc_protoc_plugin.Server_rpc.client_streaming
(module RouteGuide.RecordRoute))
~f:(fun (stream : Point.t Seq.t) ->
Eio.traceln "RecordRoute";

Expand Down Expand Up @@ -162,7 +164,8 @@ let record_route (t : t) (clock : _ Eio.Time.clock) =
(* $MDX part-begin=server-route-chat *)
let route_chat (_ : t) =
Grpc_eio.Server.Typed_rpc.bidirectional_streaming
(Grpc_protoc_plugin.server_rpc (module RouteGuide.RouteChat))
(Grpc_protoc_plugin.Server_rpc.bidirectional_streaming
(module RouteGuide.RouteChat))
~f:(fun (stream : RouteNote.t Seq.t) (f : RouteNote.t -> unit) ->
Printf.printf "RouteChat\n";

Expand All @@ -179,7 +182,7 @@ let route_chat (_ : t) =
(* $MDX part-begin=server-grpc *)
let server t clock =
Server.Typed_rpc.server
(Handlers
(Grpc_protoc_plugin.handlers
[ get_feature t; list_features t; record_route t clock; route_chat t ])

(* $MDX part-end *)
Expand Down
Loading

0 comments on commit c0c4df5

Please sign in to comment.