123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159openCoreopenAsync_kernel(* The reason for defining this module type explicitly is so that we can internally keep
track of what is and isn't exposed. *)moduletypeS=sigtypet[@@derivingsexp_of]moduleHeartbeat_config:sigtypet[@@derivingsexp,bin_io](** Each side of the connection has its own heartbeat config. It sends a heartbeat
every [send_every]. If it doesn't receive any messages for [timeout], whether it's
a heartbeat or not, it drops the connection. It only checks whether [timeout] has
elapsed when it sends heartbeats, so effectively [timeout] is rounded up to the
nearest multiple of [send_every]. *)valcreate:?timeout:Time_ns.Span.t->?send_every:Time_ns.Span.t->unit->tvaltimeout:t->Time_ns.Span.tvalsend_every:t->Time_ns.Span.tendmoduleClient_implementations:sigtypenonrec'st={connection_state:t->'s;implementations:'sImplementations.t}valnull:unit->unittend(** Initiate an Rpc connection on the given transport. [implementations] should be the
bag of implementations that the calling side implements; it defaults to
[Implementations.null] (i.e., "I implement no RPCs").
[connection_state] will be called once, before [create]'s result is determined, on
the same connection that [create] returns. Its output will be provided to the
[implementations] when queries arrive.
WARNING: If specifying a custom [heartbeat_config], make sure that both ends of the
Rpc connection use compatible settings for timeout and send frequency. Otherwise,
your Rpc connections might close unexpectedly.
[description] can be used to give some extra information about the connection, which
will then show up in error messages and the connection's sexp. If you have lots of
connections in your program, this can be useful for distinguishing them.
[time_source] can be given to define the time_source for which the heartbeating
events will be scheduled. Defaults to wall-clock. *)valcreate:?implementations:'sImplementations.t->connection_state:(t->'s)->?handshake_timeout:Time_ns.Span.t->?heartbeat_config:Heartbeat_config.t->?description:Info.t->?time_source:Synchronous_time_source.t->Transport.t->(t,Exn.t)Result.tDeferred.t(** As of Feb 2017, the RPC protocol started to contain a magic number so that one can
identify RPC communication. The bool returned by [contains_magic_prefix] says
whether this magic number was observed. *)valcontains_magic_prefix:boolBin_prot.Type_class.readervaldescription:t->Info.t(** After [add_heartbeat_callback t f], [f ()] will be called after every subsequent
heartbeat received by [t]. *)valadd_heartbeat_callback:t->(unit->unit)->unit(** Changes the heartbeat timeout and restarts the timer by setting [last_seen_alive] to
the current time. *)valreset_heartbeat_timeout:t->Time_ns.Span.t->unit(** The last time either any message has been received or [reset_heartbeat_timeout] was
called. *)vallast_seen_alive:t->Time_ns.t(** [close] starts closing the connection's transport, and returns a deferred that
becomes determined when its close completes. It is ok to call [close] multiple
times on the same [t]; calls subsequent to the initial call will have no effect, but
will return the same deferred as the original call.
Before closing the underlying transport's writer, [close] waits for all streaming
reponses to be [Pipe.upstream_flushed] with a timeout of
[streaming_responses_flush_timeout].
The [reason] for closing the connection will be passed to callers of [close_reason].
*)valclose:?streaming_responses_flush_timeout:Time_ns.Span.t(* default: 5 seconds *)->?reason:Info.t->t->unitDeferred.t(** [close_finished] becomes determined after the close of the connection's transport
completes, i.e. the same deferred that [close] returns. [close_finished] differs
from [close] in that it does not have the side effect of initiating a close. *)valclose_finished:t->unitDeferred.t(** [close_reason ~on_close t] becomes determined when close starts or finishes
based on [on_close], but additionally returns the reason that the connection was
closed. *)valclose_reason:t->on_close:[`started|`finished]->Info.tDeferred.t(** [is_closed t] returns [true] iff [close t] has been called. [close] may be called
internally upon errors or timeouts. *)valis_closed:t->bool(** [bytes_to_write] and [flushed] just call the similarly named functions on the
[Transport.Writer.t] within a connection. *)valbytes_to_write:t->intvalflushed:t->unitDeferred.t(** [with_close] tries to create a [t] using the given transport. If a handshake error
is the result, it calls [on_handshake_error], for which the default behavior is to
raise an exception. If no error results, [dispatch_queries] is called on [t].
After [dispatch_queries] returns, if [server] is None, the [t] will be closed and
the deferred returned by [dispatch_queries] will be determined immediately.
Otherwise, we'll wait until the other side closes the connection and then close [t]
and determine the deferred returned by [dispatch_queries].
When the deferred returned by [with_close] becomes determined, [Transport.close] has
finished.
NOTE: Because this connection is closed when the [Deferred.t] returned by
[dispatch_queries] is determined, you should be careful when using this with
[Pipe_rpc]. For example, simply returning the pipe when you get it will close the
pipe immediately. You should instead either use the pipe inside [dispatch_queries]
and not determine its result until you are done with the pipe, or use a different
function like [create]. *)valwith_close:?implementations:'sImplementations.t->?handshake_timeout:Time_ns.Span.t->?heartbeat_config:Heartbeat_config.t->?description:Info.t->?time_source:Synchronous_time_source.t->connection_state:(t->'s)->Transport.t->dispatch_queries:(t->'aDeferred.t)->on_handshake_error:[`Raise|`CallofExn.t->'aDeferred.t]->'aDeferred.t(** Runs [with_close] but dispatches no queries. The implementations are required
because this function doesn't let you dispatch any queries (i.e., act as a client),
it would be pointless to call it if you didn't want to act as a server.*)valserver_with_close:?handshake_timeout:Time_ns.Span.t->?heartbeat_config:Heartbeat_config.t->?description:Info.t->?time_source:Synchronous_time_source.t->Transport.t->implementations:'sImplementations.t->connection_state:(t->'s)->on_handshake_error:[`Raise|`Ignore|`CallofExn.t->unitDeferred.t]->unitDeferred.tend