mirror of
https://github.com/zap-proto/ocaml-rpc.git
synced 2026-10-30 15:04:28 +00:00
104 lines
3.4 KiB
OCaml
104 lines
3.4 KiB
OCaml
open Eio.Std
|
|
open Capnp_rpc.Std
|
|
|
|
module Restorer = Capnp_rpc_net.Restorer
|
|
|
|
let ( / ) = Eio.Path.( / )
|
|
|
|
let () =
|
|
Logs.set_level (Some Logs.Warning);
|
|
Logs.set_reporter (Logs_fmt.reporter ())
|
|
|
|
let or_fail = function
|
|
| Ok x -> x
|
|
| Error (`Msg m) -> failwith m
|
|
|
|
(* $MDX part-begin=server *)
|
|
let serve store_dir config =
|
|
Switch.run @@ fun sw ->
|
|
(* Create the on-disk store *)
|
|
let make_sturdy = Capnp_rpc_unix.Vat_config.sturdy_uri config in
|
|
let db, set_loader = Db.create ~make_sturdy store_dir in
|
|
(* Create the restorer *)
|
|
let services = Restorer.Table.of_loader ~sw (module Db) db in
|
|
Switch.on_release sw (fun () -> Restorer.Table.clear services);
|
|
let restore = Restorer.of_table services in
|
|
(* Add the root service *)
|
|
let persist_new ~label =
|
|
let id = Db.save_new db ~label in
|
|
Capnp_rpc_net.Restorer.restore restore id
|
|
in
|
|
let root_id = Capnp_rpc_unix.Vat_config.derived_id config "root" in
|
|
let root =
|
|
let sr = Capnp_rpc_net.Restorer.Table.sturdy_ref services root_id in
|
|
Logger.local ~persist_new sr "root"
|
|
in
|
|
Restorer.Table.add services root_id root;
|
|
(* Tell the database how to restore saved loggers *)
|
|
Promise.resolve set_loader (fun sr ~label -> Restorer.grant @@ Logger.local ~persist_new sr label);
|
|
(* Run the server *)
|
|
let _vat = Capnp_rpc_unix.serve ~sw ~restore config in
|
|
let uri = Capnp_rpc_unix.Vat_config.sturdy_uri config root_id in
|
|
Capnp_rpc_unix.Cap_file.save_uri uri "admin.cap" |> or_fail;
|
|
print_endline "Wrote admin.cap";
|
|
Fiber.await_cancel ()
|
|
(* $MDX part-end *)
|
|
|
|
let log net cap_file msg =
|
|
Switch.run @@ fun sw ->
|
|
let vat = Capnp_rpc_unix.client_only_vat ~sw net in
|
|
let sr = Capnp_rpc_unix.Cap_file.load vat cap_file |> or_fail in
|
|
Sturdy_ref.with_cap_exn sr @@ fun logger ->
|
|
Logger.log logger msg
|
|
|
|
let sub env cap_file label =
|
|
Switch.run @@ fun sw ->
|
|
let sub_file = label ^ ".cap" in
|
|
if Sys.file_exists sub_file then Fmt.failwith "%S already exists!" sub_file;
|
|
let vat = Capnp_rpc_unix.client_only_vat ~sw env#net in
|
|
let sr = Capnp_rpc_unix.Cap_file.load vat cap_file |> or_fail in
|
|
Sturdy_ref.with_cap_exn sr @@ fun root ->
|
|
let uri = Capability.with_ref (Logger.sub root "alice") Capnp_rpc.Persistence.save_exn in
|
|
Capnp_rpc_unix.Cap_file.save_uri uri sub_file |> or_fail;
|
|
Printf.printf "Wrote %S\n%!" sub_file;
|
|
|
|
open Cmdliner
|
|
|
|
let ( $ ) = Term.( $ )
|
|
let ( $$ ) f x = Term.const f $ x
|
|
|
|
let serve_cmd env =
|
|
let doc = "run the server" in
|
|
let info = Cmd.info "serve" ~doc in
|
|
Cmd.v info (serve (env#cwd / "store") $$ Capnp_rpc_unix.Vat_config.cmd env)
|
|
|
|
let cap_file =
|
|
let i = Arg.info [] ~docv:"PATH" ~doc:"logger.cap file" in
|
|
Arg.(required @@ pos 0 (some file) None i)
|
|
|
|
let msg =
|
|
let i = Arg.info [] ~docv:"MSG" ~doc:"Message to send" in
|
|
Arg.(required @@ pos 1 (some string) None i)
|
|
|
|
let label =
|
|
let i = Arg.info [] ~docv:"LABEL" ~doc:"Tag for new logger" in
|
|
Arg.(required @@ pos 1 (some string) None i)
|
|
|
|
let log_cmd env =
|
|
let doc = "log a message" in
|
|
let info = Cmd.info "log" ~doc in
|
|
Cmd.v info Term.(log env#net $$ cap_file $ msg)
|
|
|
|
let sub_cmd env =
|
|
let doc = "create a sub-logger" in
|
|
let info = Cmd.info "sub" ~doc in
|
|
Cmd.v info Term.(sub env $$ cap_file $ label)
|
|
|
|
let cmds env = [serve_cmd env; sub_cmd env; log_cmd env]
|
|
|
|
let () =
|
|
let doc = "a command-line interface for logger service" in
|
|
let info = Cmd.info ~doc "logger-client" in
|
|
exit @@ Eio_main.run @@ fun env ->
|
|
Cmd.eval @@ Cmd.group info (cmds env)
|