Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file command_rpc_intf.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198(** Utilities for RPC communication with a child process over stdin and stdout. *)open!Coreopen!AsyncmoduletypeT=sigtypequery[@@derivingof_sexp]typeresponse[@@derivingsexp_of]typestatevalrpc:(query,response)Rpc.Rpc.tvalimplementation:state->query->responseDeferred.tendmoduletypeT_conv=sigincludeVersioned_rpc.Callee_converts.Rpc.Stypestatevalname:stringvalquery_of_sexp:Sexp.t->queryvalsexp_of_response:response->Sexp.tvalimplementation:state->query->responseDeferred.tendmoduletypeT_pipe=sigtypequery[@@derivingof_sexp]typeresponse[@@derivingsexp_of]typeerror[@@derivingsexp_of]typestatevalrpc:(query,response,error)Rpc.Pipe_rpc.tvalimplementation:state->query->(responsePipe.Reader.t,error)Result.tDeferred.tendmoduletypeT_pipe_conv=sigtypequery[@@derivingof_sexp]typeresponse[@@derivingsexp_of]typeerror[@@derivingsexp_of]typestateincludeVersioned_rpc.Callee_converts.Pipe_rpc.Swithtypequery:=querywithtyperesponse:=responsewithtypeerror:=errorvalimplementation:state->query->(responsePipe.Reader.t,error)Result.tDeferred.tendmoduletypeCommand_rpc=sig(** [Command] is used for setting up an RPC server in the child process. By default this
will set up an RPC server, but passing the [-sexp] flag will make it run the
implementation on a sexp read from stdin instead. Passing the [-menu] flag
will cause the command to print out a sexp indicating which RPC names and
versions are supported.
*)moduleCommand:sigmoduleInvocation:sigtypet=|Sexp|Bin_ioofRpc.Connection.tendmoduleStateful:sigmoduletypeT=TmoduletypeT_conv=T_convmoduletypeT_pipe=T_pipemoduletypeT_pipe_conv=T_pipe_convtype'statet=[`Plainof(moduleTwithtypestate='state)|`Plain_convof(moduleT_convwithtypestate='state)|`Pipeof(moduleT_pipewithtypestate='state)|`Pipe_convof(moduleT_pipe_convwithtypestate='state)|`Implementationsof'stateRpc.Implementation.tlist](** Given an RPC that expects a state type ['a], it can use a state type ['b] if we
tell it how to extract an ['a] from it. Note that this extraction is done on every
RPC call, so should be cheap and should not copy mutable state that you want to
persist across calls. *)vallift:'at->f:('b->'a)->'btendmoduletypeT=Stateful.Twithtypestate:=Invocation.tmoduletypeT_conv=Stateful.T_convwithtypestate:=Invocation.tmoduletypeT_pipe=Stateful.T_pipewithtypestate:=Invocation.tmoduletypeT_pipe_conv=Stateful.T_pipe_convwithtypestate:=Invocation.ttypet=[`Plainof(moduleT)|`Plain_convof(moduleT_conv)|`Pipeof(moduleT_pipe)|`Pipe_convof(moduleT_pipe_conv)|`ImplementationsofInvocation.tRpc.Implementation.tlist](** You need to call this on your list of stateful RPCs before they can be passed to
[create] or (more usually) the function you get in [Expert.param]. *)valstateful:Invocation.tStateful.tlist->tlistvalcreate:?heartbeat_config:Rpc.Connection.Heartbeat_config.t->?max_message_size:int->?log_not_previously_seen_version:(name:string->int->unit)->?buffer_age_limit:Writer.buffer_age_limit->summary:string->tlist->Command.tmoduleExpert:sig(** [param ()] returns a command line parameter which produces a function. You can
do any initialization (e.g. of mutable state) and then call the function with
your RPC implementations to start the RPC server. The deferred it returns will
become determined when the client closes their connection, after which you may
do any cleanup you need and then exit (possibly with an appropriate exit
status).
This interface is marked [Expert] because consuming from stdin or writing to
stdout during your initialization may prevent you from receiving RPCs or
responding to them properly, but we cannot check that you don't do this or prevent
you from doing it, so you just have to be careful.
You are responsible for ensuring that the async scheduler is started, e.g., by
calling [Command.async_or_error']. *)valparam:unit->(?heartbeat_config:Rpc.Connection.Heartbeat_config.t->?max_message_size:int->?log_not_previously_seen_version:(name:string->int->unit)->?buffer_age_limit:Writer.buffer_age_limit(** Set the buffer age limit of the stdout writer *)->tlist->unitDeferred.t)Command.Param.tendendmoduleConnection:sigtypettype'awith_connection_args=?heartbeat_config:Rpc.Connection.Heartbeat_config.t->?max_message_size:int->?propagate_stderr:bool(* defaults to true *)->?env:Process.env(* defaults to [`Extend []] *)->?process_create:(prog:string->args:stringlist->?env:Process.env->?working_dir:string->unit->Process.tDeferred.Or_error.t)->?working_dir:string(* defaults to [Process.create]. You may want to use [process_create] to run
Command_rpc on binaries from Exe_server. *)->prog:string->args:stringlist->'a(** [create] spawns a child process and returns an RPC connection that operates on the
child's stdin and stdout. The child will be killed and reaped when the connection
is closed. If [propagate_stderr] is true, the child's stderr will be printed on
the parent's stderr; otherwise it will be ignored. *)valcreate:(unit->tOr_error.tDeferred.t)with_connection_args(** [with_close] spawns a child and connects like [create], calls the function passed
in on the resulting connection, and then closes the connection and kills the
child. *)valwith_close:((t->'aOr_error.tDeferred.t)->'aOr_error.tDeferred.t)with_connection_args(** Get the RPC connection needed to talk to the command-rpc executable. *)valrpc_connection:t->Rpc.Connection.t(** This module exists for testing purposes only. For example, clients can test
whether their command-rpc server cleans up after itself properly when a ctrl-c
at the command line kills a whole process group, server included. *)moduleExpert:sig(** Send a signal to the command-rpc executable.
Note that this has a (very small) race condition where we can send a signal
to a reaped pid if the process dies at exactly the right time. *)valkill:t->Signal.t->unit(** Wait for termination of the command-rpc executable. *)valwait:t->Unix.Exit_or_signal.tDeferred.tendendend