From a404782cbfcd2299add68d94c1b0ef0b06e73185 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Thu, 9 Jul 2020 08:58:27 +0100 Subject: [PATCH] Add `Sturdy_ref.with_cap` and `with_cap_exn` convenience functions Using the plain `connect` functions, it's easy to forget to release the live-ref at the end. --- README.md | 14 ++++++-------- capnp-rpc-lwt/capnp_rpc_lwt.mli | 11 +++++++++++ capnp-rpc-lwt/sturdy_ref.ml | 9 +++++++++ test-bin/calc.ml | 2 +- test-bin/echo/echo_bench.ml | 3 +-- test-lwt/test_lwt.ml | 7 ++----- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5460bb727..b422d1e65 100644 --- a/README.md +++ b/README.md @@ -440,8 +440,7 @@ let () = Fmt.pr "Connecting to echo service at: %a@." Uri.pp_hum uri; let client_vat = Capnp_rpc_unix.client_only_vat () in let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in - Sturdy_ref.connect_exn sr >>= fun proxy_to_service -> - run_client proxy_to_service + Sturdy_ref.with_cap_exn sr run_client end ``` @@ -522,8 +521,8 @@ In `start_server`: #### The client side After starting the server and getting the sturdy URI, we create a client vat and connect to the sturdy ref. -The result, `proxy_to_service`, is a proxy to the remote service via the network -that can be used in exactly the same way as the direct reference we used before. +The result is a proxy to the remote service via the network that can be used in +exactly the same way as the direct reference we used before. #### Separate processes @@ -605,8 +604,7 @@ let connect uri = Fmt.pr "Connecting to echo service at: %a@." Uri.pp_hum uri; let client_vat = Capnp_rpc_unix.client_only_vat () in let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in - Sturdy_ref.connect_exn sr >>= fun proxy_to_service -> - run_client proxy_to_service + Sturdy_ref.with_cap_exn sr run_client end open Cmdliner @@ -1291,7 +1289,7 @@ The calculator example can also be run across two Unix processes. Start the server with: ``` -$ dune exec -- ./test-bin/calc.bc serve \ +$ dune exec -- ./test-bin/calc.exe serve \ --capnp-listen-address unix:/tmp/calc.socket \ --capnp-secret-key-file=key.pem Waiting for incoming connections at: @@ -1303,7 +1301,7 @@ Note that `key.pem` does not need to exist. A new key will be generated and save In another terminal, run the client and connect to the address displayed by the server: ``` -dune exec -- ./test-bin/calc.bc connect capnp://sha-256:LPp-7l74zqvGcRgcP8b7-kdSpwwzxlA555lYC8W8prc@/tmp/calc.socket/ +dune exec -- ./test-bin/calc.exe connect capnp://sha-256:LPp-7l74zqvGcRgcP8b7-kdSpwwzxlA555lYC8W8prc@/tmp/calc.socket/ ``` You can also use `--capnp-disable-tls` if you prefer to run without encryption diff --git a/capnp-rpc-lwt/capnp_rpc_lwt.mli b/capnp-rpc-lwt/capnp_rpc_lwt.mli index 3cee234ad..d72aab9f3 100644 --- a/capnp-rpc-lwt/capnp_rpc_lwt.mli +++ b/capnp-rpc-lwt/capnp_rpc_lwt.mli @@ -182,6 +182,17 @@ module Sturdy_ref : sig val connect_exn : 'a t -> 'a Capability.t Lwt.t (** [connect_exn] is a wrapper for [connect] that returns a failed Lwt thread on error. *) + val with_cap : + 'a t -> + ('a Capability.t -> ('b, [> `Capnp of Capnp_rpc.Exception.t] as 'e) Lwt_result.t) -> + ('b, 'e) Lwt_result.t + (** [with_cap t f] uses [connect t] to get a live-ref [x], + then does [Capability.with_ref x f]. *) + + val with_cap_exn : 'a t -> ('a Capability.t -> 'b Lwt.t) -> 'b Lwt.t + (** [with_cap_exn t f] uses [connect_exn t] to get a live-ref [x], + then does [Capability.with_ref x f]. *) + val reader : ('a StructStorage.reader_t -> Capnp.MessageSig.ro Slice.t option) -> 'a StructStorage.reader_t -> Uri.t diff --git a/capnp-rpc-lwt/sturdy_ref.ml b/capnp-rpc-lwt/sturdy_ref.ml index c6bfc4315..cc2a70b1d 100644 --- a/capnp-rpc-lwt/sturdy_ref.ml +++ b/capnp-rpc-lwt/sturdy_ref.ml @@ -16,3 +16,12 @@ let builder fn (s : 'a Capnp.BytesMessage.StructStorage.builder_t) (sr : 'a t) = sr#to_uri_with_secrets |> Uri.to_string |> Schema.BuilderOps.write_string (fn s) let cast t = t + +let with_cap t f = + connect t >>= function + | Ok x -> Capability.with_ref x f + | Error e -> Lwt_result.fail (`Capnp e) + +let with_cap_exn t f = + connect_exn t >>= fun x -> + Capability.with_ref x f diff --git a/test-bin/calc.ml b/test-bin/calc.ml index 189d86f86..c11782f7c 100644 --- a/test-bin/calc.ml +++ b/test-bin/calc.ml @@ -45,7 +45,7 @@ let connect addr = Lwt_main.run begin let vat = Capnp_rpc_unix.client_only_vat () in let sr = Vat.import_exn vat addr in - Capnp_rpc_lwt.Sturdy_ref.connect_exn sr >>= fun calc -> + Capnp_rpc_lwt.Sturdy_ref.with_cap_exn sr @@ fun calc -> Logs.info (fun f -> f "Evaluating expression..."); let remote_add = Calc.getOperator calc `Add in let result = Calc.evaluate calc Calc.Expr.(Call (remote_add, [Float 40.0; Float 2.0])) in diff --git a/test-bin/echo/echo_bench.ml b/test-bin/echo/echo_bench.ml index b2d5ad7c6..db6af3ea8 100755 --- a/test-bin/echo/echo_bench.ml +++ b/test-bin/echo/echo_bench.ml @@ -39,6 +39,5 @@ let () = Fmt.pr "Connecting to echo service at: %a@." Uri.pp_hum uri; let client_vat = Capnp_rpc_unix.client_only_vat () in let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in - Sturdy_ref.connect_exn sr >>= fun proxy -> - run_client proxy + Sturdy_ref.with_ref_exn sr run_client end diff --git a/test-lwt/test_lwt.ml b/test-lwt/test_lwt.ml index a6f8b05ae..ee3877031 100644 --- a/test-lwt/test_lwt.ml +++ b/test-lwt/test_lwt.ml @@ -608,7 +608,7 @@ let test_store switch = (* Set up client *) let client = Capnp_rpc_unix.client_only_vat ~tags:Test_utils.client_tags ~switch () in let sr = Capnp_rpc_unix.Vat.import_exn client store_uri in - Sturdy_ref.connect_exn sr >>= fun store -> + Sturdy_ref.with_cap_exn sr @@ fun store -> (* Try creating a file *) let file = Store.create_file store in Store.File.set file "Hello" >>= fun () -> @@ -623,12 +623,9 @@ let test_store switch = (* Restart server *) start_server ~switch () >>= fun _server -> (* Reconnect client *) - Sturdy_ref.connect_exn file_sr >>= fun file -> + Sturdy_ref.with_cap_exn file_sr @@ fun file -> Store.File.get file >>= fun data -> Alcotest.(check string) "Read file" "Hello" data; - (* Clean up *) - Capability.dec_ref file; - Capability.dec_ref store; Lwt.return_unit let run name fn = Alcotest_lwt.test_case_sync name `Quick fn