Up

module Versioned_rpc

: sig

Infrastructure code for managing RPCs that evolve over time to use different types at different versions.

Three scenarios are supported:

In each scenario, it is desirable that the party responsible for managing versions be coded largely in terms of a single "master" version of the types involved, with all necessary type conversions relegated to a single module. Versioned_rpc is intended for implementing such a module.

Type coercions into and out of the model go in the directions indicated by the following diagram:

        Caller converts                 Callee converts
        ===============                 ===============

            caller                        callee
            |       callee                |      callee
            |       |       caller        |      |       callee
            |       |       |             |      |       |
         ,-->-- Q1 --> R1 -->-.      Q1 -->-.    |    ,-->-- R1
        /                      \             \   |   /
       Q --->-- Q2 --> R2 -->-- R    Q2 -->-- Q --> R --->-- R2
        \                      /             /       \
         `-->-- Q3 --> R3 -->-'      Q3 -->-'         `-->-- R3
#
module Menu : sig
#
type t

a directory of supported rpc names and versions.

#
val add : 's Rpc.Implementation.t list -> 's Rpc.Implementation.t list

add impls extends a list of rpc implementations with an additional rpc implementation for providing a Menu.t when one is requested via Menu.request.

#
val request : Rpc.Connection.t -> t Core.Std.Or_error.t Import.Deferred.t

request an rpc version menu from an rpc connection

#
val supported_rpcs : t -> Rpc.Implementation.Description.t list

find what rpcs are supported

#
val supported_versions : t -> rpc_name:string -> Core.Std.Int.Set.t

find what versions of a particular rpc are supported

end
#
module Connection_with_menu : sig
#
type t

an rpc connection paired with the menu of rpcs one may call on it

#
val create : Rpc.Connection.t -> t Import.Deferred.Or_error.t
#
val connection : t -> Rpc.Connection.t
#
val menu : t -> Menu.t
end
#
module Caller_converts : sig
#
module Rpc : sig
#
module type S = sig
#
type query
#
type response
#
val deprecated_dispatch_multi : version:int -> Rpc.Connection.t -> query -> response Core.Std.Or_error.t Import.Deferred.t
#
val dispatch_multi : Connection_with_menu.t -> query -> response Core.Std.Or_error.t Import.Deferred.t

multi-version dispatch

#
val versions : unit -> Core.Std.Int.Set.t

All versions supported by dispatch_multi. (useful for computing which old versions may be pruned)

end
#
module Make : functor (Model : sig
#
val name : string
#
type query
#
type response
end
) -> sig

Given a model of the types involved in a family of RPCs, this functor provides a single RPC versioned dispatch function dispatch_multi in terms of that model and a mechanism for registering the individual versions that dispatch_multi knows about. Registration requires knowing how to get into and out of the model.

           ,-->-- Q1 --> R1 -->-.
          /                      \
         Q --->-- Q2 --> R2 -->-- R
          \                      /
           `-->-- Q3 --> R3 -->-'
#
module Register : functor (Version_i : sig
#
val version : int
#
type query
#
type response
#
val query_of_model : Model.query -> query
#
val model_of_response : response -> Model.response
#
val bin_query : query Core.Std.Bin_prot.Type_class.t
#
val bin_read_query : query Core.Std.Bin_prot.Read.reader
#
val __bin_read_query__ : (int -> query) Core.Std.Bin_prot.Read.reader
#
val bin_reader_query : query Core.Std.Bin_prot.Type_class.reader
#
val bin_size_query : query Core.Std.Bin_prot.Size.sizer
#
val bin_write_query : query Core.Std.Bin_prot.Write.writer
#
val bin_writer_query : query Core.Std.Bin_prot.Type_class.writer
#
val bin_response : response Core.Std.Bin_prot.Type_class.t
#
val bin_read_response : response Core.Std.Bin_prot.Read.reader
#
val __bin_read_response__ : (int -> response) Core.Std.Bin_prot.Read.reader
#
val bin_reader_response : response Core.Std.Bin_prot.Type_class.reader
#
val bin_size_response : response Core.Std.Bin_prot.Size.sizer
#
val bin_write_response : response Core.Std.Bin_prot.Write.writer
#
val bin_writer_response : response Core.Std.Bin_prot.Type_class.writer
end
) -> sig

add a new version to the set of versions available via dispatch_multi.

end
include S with type query := Model.query and type response := Model.response
end
end
#
module Pipe_rpc : sig
#
module type S = sig
#
type query
#
type response
#
type error

multi-version dispatch

The return type varies slightly from Rpc.Pipe_rpc.dispatch to make it clear that conversion of each individual element in the returned pipe may fail.

#
val deprecated_dispatch_multi : version:int -> Rpc.Connection.t -> query -> (response Core.Std.Or_error.t Import.Pipe.Reader.t * Rpc.Pipe_rpc.Id.t, error) Core.Std.Result.t Core.Std.Or_error.t Import.Deferred.t
#
val dispatch_multi : Connection_with_menu.t -> query -> (response Core.Std.Or_error.t Import.Pipe.Reader.t * Rpc.Pipe_rpc.Id.t, error) Core.Std.Result.t Core.Std.Or_error.t Import.Deferred.t
#
val versions : unit -> Core.Std.Int.Set.t

All versions supported by dispatch_multi. (useful for computing which old versions may be pruned)

end
#
module Make : functor (Model : sig
#
val name : string
#
type query
#
type response
#
type error
end
) -> sig

Given a model of the types involved in a family of Pipe_RPCs, this functor provides a single Pipe_RPC versioned dispatch function dispatch_multi in terms of that model and a mechanism for registering the individual versions that dispatch_multi knows about. Registration requires knowing how to get into and out of the model.

            ,-->-- Q1 --> R1 -->-.    E1 -->-.
           /                      \           \
          Q --->-- Q2 --> R2 -->-- R  E2 -->-- E
           \                      /           /
            `-->-- Q3 --> R3 -->-'    E3 -->-'
#
module type Version_shared = sig
#
val version : int
#
type query
#
type response
#
type error
#
val query_of_model : Model.query -> query
#
val model_of_error : error -> Model.error
#
val client_pushes_back : bool
#
val bin_query : query Core.Std.Bin_prot.Type_class.t
#
val bin_read_query : query Core.Std.Bin_prot.Read.reader
#
val __bin_read_query__ : (int -> query) Core.Std.Bin_prot.Read.reader
#
val bin_reader_query : query Core.Std.Bin_prot.Type_class.reader
#
val bin_size_query : query Core.Std.Bin_prot.Size.sizer
#
val bin_write_query : query Core.Std.Bin_prot.Write.writer
#
val bin_writer_query : query Core.Std.Bin_prot.Type_class.writer
#
val bin_response : response Core.Std.Bin_prot.Type_class.t
#
val bin_read_response : response Core.Std.Bin_prot.Read.reader
#
val __bin_read_response__ : (int -> response) Core.Std.Bin_prot.Read.reader
#
val bin_reader_response : response Core.Std.Bin_prot.Type_class.reader
#
val bin_size_response : response Core.Std.Bin_prot.Size.sizer
#
val bin_write_response : response Core.Std.Bin_prot.Write.writer
#
val bin_writer_response : response Core.Std.Bin_prot.Type_class.writer
#
val bin_error : error Core.Std.Bin_prot.Type_class.t
#
val bin_read_error : error Core.Std.Bin_prot.Read.reader
#
val __bin_read_error__ : (int -> error) Core.Std.Bin_prot.Read.reader
#
val bin_reader_error : error Core.Std.Bin_prot.Type_class.reader
#
val bin_size_error : error Core.Std.Bin_prot.Size.sizer
#
val bin_write_error : error Core.Std.Bin_prot.Write.writer
#
val bin_writer_error : error Core.Std.Bin_prot.Type_class.writer
end
#
module Register : functor (Version_i : sig
include Version_shared
#
val model_of_response : response -> Model.response
end
) -> sig

add a new version to the set of versions available via dispatch_multi.

end
#
module Register' : functor (Version_i : sig
include Version_shared
#
val model_of_response : response Core.Std.Queue.t -> Model.response Core.Std.Queue.t Import.Deferred.t
end
) -> sig
end
include S with type query := Model.query and type response := Model.response and type error := Model.error
end
end
end
#
module Callee_converts : sig
#
module Rpc : sig
#
module Simple : sig
#
type ('query, 'response) t
#
val create : name:string -> ('query, 'response) t
#
val name : (_, _) t -> string
#
val add_version : ('query, 'response) t -> version:int -> bin_query:'old_query Core.Std.Bin_prot.Type_class.t -> bin_response:'old_response Core.Std.Bin_prot.Type_class.t -> ('old_query -> 'query) -> ('response -> 'old_response) -> ('query, 'response) t Core.Std.Or_error.t
#
val add_version_with_failure : ('query, 'response Core.Std.Or_error.t) t -> version:int -> bin_query:'old_query Core.Std.Bin_prot.Type_class.t -> bin_response:('old_response, string) Core.Std.Result.t Core.Std.Bin_prot.Type_class.t -> ('old_query -> 'query Core.Std.Or_error.t) -> ('response -> 'old_response Core.Std.Or_error.t) -> ('query, 'response Core.Std.Or_error.t) t Core.Std.Or_error.t
#
val add_rpc_version : ('query, 'response) t -> ('old_query, 'old_response) Rpc.Rpc.t -> ('old_query -> 'query) -> ('response -> 'old_response) -> ('query, 'response) t Core.Std.Or_error.t
#
val add_rpc_version_with_failure : ('query, 'response Core.Std.Or_error.t) t -> ('old_query, ('old_response, string) Core.Std.Result.t) Rpc.Rpc.t -> ('old_query -> 'query Core.Std.Or_error.t) -> ('response -> 'old_response Core.Std.Or_error.t) -> ('query, 'response Core.Std.Or_error.t) t Core.Std.Or_error.t
#
val implement : ('query, 'response) t -> ('state -> 'query -> 'response Import.Deferred.t) -> 'state Rpc.Implementation.t list
end
#
module type S = sig
#
type query
#
type response
#
val implement_multi : ?log_not_previously_seen_version:(name:string -> int -> unit) -> ('state -> version:int -> query -> response Import.Deferred.t) -> 'state Rpc.Implementation.t list

implement multiple versions at once

#
val rpcs : unit -> Rpc.Any.t list
#
val versions : unit -> Core.Std.Int.Set.t

All versions implemented by implement_multi. (useful for computing which old versions may be pruned)

end
#
module Make : functor (Model : sig
#
val name : string
#
type query
#
type response
end
) -> sig

Given a model of the types involved in a family of RPCs, this functor provides a single multi-version implementation function implement_multi in terms of that model and a mechanism for registering the individual versions that implement_multi knows about. Registration requires knowing how to get into and out of the model.

          Q1 -->-.         ,-->-- R1
                  \       /
          Q2 -->-- Q --> R --->-- R2
                  /       \
          Q3 -->-'         `-->-- R3
#
module Register : functor (Version_i : sig
#
val version : int
#
type query
#
type response
#
val model_of_query : query -> Model.query
#
val response_of_model : Model.response -> response
#
val bin_query : query Core.Std.Bin_prot.Type_class.t
#
val bin_read_query : query Core.Std.Bin_prot.Read.reader
#
val __bin_read_query__ : (int -> query) Core.Std.Bin_prot.Read.reader
#
val bin_reader_query : query Core.Std.Bin_prot.Type_class.reader
#
val bin_size_query : query Core.Std.Bin_prot.Size.sizer
#
val bin_write_query : query Core.Std.Bin_prot.Write.writer
#
val bin_writer_query : query Core.Std.Bin_prot.Type_class.writer
#
val bin_response : response Core.Std.Bin_prot.Type_class.t
#
val bin_read_response : response Core.Std.Bin_prot.Read.reader
#
val __bin_read_response__ : (int -> response) Core.Std.Bin_prot.Read.reader
#
val bin_reader_response : response Core.Std.Bin_prot.Type_class.reader
#
val bin_size_response : response Core.Std.Bin_prot.Size.sizer
#
val bin_write_response : response Core.Std.Bin_prot.Write.writer
#
val bin_writer_response : response Core.Std.Bin_prot.Type_class.writer
end
) -> sig

Add a new version to the set of versions implemented by implement_multi.

end
include S with type query := Model.query and type response := Model.response
end
end
#
module Pipe_rpc : sig
#
module type S = sig
#
type query
#
type response
#
type error
#
val implement_multi : ?log_not_previously_seen_version:(name:string -> int -> unit) -> ('state -> version:int -> query -> aborted:unit Import.Deferred.t -> (response Import.Pipe.Reader.t, error) Core.Std.Result.t Import.Deferred.t) -> 'state Rpc.Implementation.t list

implement multiple versions at once

#
val rpcs : unit -> Rpc.Any.t list
#
val versions : unit -> Core.Std.Int.Set.t

All versions supported by dispatch_multi. (useful for computing which old versions may be pruned)

end
#
module Make : functor (Model : sig
#
val name : string
#
type query
#
type response
#
type error
end
) -> sig

Given a model of the types involved in a family of Pipe_RPCs, this functor provides a single multi-version implementation function implement_multi in terms of that model and a mechanism for registering the individual versions that implement_multi knows about. Registration requires knowing how to get into and out of the model.

          Q1 -->-.         ,-->-- R1
                  \       /
          Q2 -->-- Q --> R --->-- R2
                  /       \
          Q3 -->-'         `-->-- R3
#
module type Version_shared = sig
#
val version : int
#
type query
#
type response
#
type error
#
val model_of_query : query -> Model.query
#
val error_of_model : Model.error -> error
#
val client_pushes_back : bool
#
val bin_query : query Core.Std.Bin_prot.Type_class.t
#
val bin_read_query : query Core.Std.Bin_prot.Read.reader
#
val __bin_read_query__ : (int -> query) Core.Std.Bin_prot.Read.reader
#
val bin_reader_query : query Core.Std.Bin_prot.Type_class.reader
#
val bin_size_query : query Core.Std.Bin_prot.Size.sizer
#
val bin_write_query : query Core.Std.Bin_prot.Write.writer
#
val bin_writer_query : query Core.Std.Bin_prot.Type_class.writer
#
val bin_response : response Core.Std.Bin_prot.Type_class.t
#
val bin_read_response : response Core.Std.Bin_prot.Read.reader
#
val __bin_read_response__ : (int -> response) Core.Std.Bin_prot.Read.reader
#
val bin_reader_response : response Core.Std.Bin_prot.Type_class.reader
#
val bin_size_response : response Core.Std.Bin_prot.Size.sizer
#
val bin_write_response : response Core.Std.Bin_prot.Write.writer
#
val bin_writer_response : response Core.Std.Bin_prot.Type_class.writer
#
val bin_error : error Core.Std.Bin_prot.Type_class.t
#
val bin_read_error : error Core.Std.Bin_prot.Read.reader
#
val __bin_read_error__ : (int -> error) Core.Std.Bin_prot.Read.reader
#
val bin_reader_error : error Core.Std.Bin_prot.Type_class.reader
#
val bin_size_error : error Core.Std.Bin_prot.Size.sizer
#
val bin_write_error : error Core.Std.Bin_prot.Write.writer
#
val bin_writer_error : error Core.Std.Bin_prot.Type_class.writer
end
#
module Register : functor (Version_i : sig
include Version_shared
#
val response_of_model : Model.response -> response
end
) -> sig

add a new version to the set of versions available via implement_multi.

end
#
module Register' : functor (Version_i : sig
include Version_shared
#
val response_of_model : Model.response Core.Std.Queue.t -> response Core.Std.Queue.t Import.Deferred.t
end
) -> sig
end
include S with type query := Model.query and type response := Model.response and type error := Model.error
end
end
end
#
module Both_convert : sig

Both_convert rpcs combine features of both caller-converts and callee-converts versioning schemes in such a way that one can smoothly add a new version of the rpc to a shared library, and it doesn't matter whether the callee or caller upgrades to the latest version of the shared library first, the new version will not be exercised until both sides support it.

                     (conv)   (conv)                          (conv)   (conv)
                     caller   callee                          callee   caller
                     |        |                               |        |
                     |        |                               |        |
        Q.caller ---->-- Q1 -->-.             (impl)        .->-- R1 -->---- R.caller
                \                \            callee       /                /
                 \--->-- Q2 -->---\           |           /--->-- R2 -->---/
                  \                \          |          /                /
                   `->-- Q3 -->---- Q.callee --> R.callee ---->-- R3 -->-'
#
module Plain : sig
#
module type S = sig
#
type caller_query
#
type caller_response
#
type callee_query
#
type callee_response
#
val dispatch_multi : Connection_with_menu.t -> caller_query -> caller_response Core.Std.Or_error.t Import.Deferred.t

multi-version dispatch

#
val implement_multi : ?log_not_previously_seen_version:(name:string -> int -> unit) -> ('state -> version:int -> callee_query -> callee_response Import.Deferred.t) -> 'state Rpc.Implementation.t list

implement multiple versions at once

#
val versions : unit -> Core.Std.Int.Set.t

All supported versions. Useful for detecting old versions that may be pruned.

end
#
module Make : functor (Model : sig
#
val name : string
#
module Caller : sig
#
type query
#
type response
end
#
module Callee : sig
#
type query
#
type response
end
end
) -> sig
#
module Register : functor (Version : sig
#
val version : int
#
type query
#
type response
#
val query_of_caller_model : Model.Caller.query -> query
#
val callee_model_of_query : query -> Model.Callee.query
#
val response_of_callee_model : Model.Callee.response -> response
#
val caller_model_of_response : response -> Model.Caller.response
#
val bin_query : query Core.Std.Bin_prot.Type_class.t
#
val bin_read_query : query Core.Std.Bin_prot.Read.reader
#
val __bin_read_query__ : (int -> query) Core.Std.Bin_prot.Read.reader
#
val bin_reader_query : query Core.Std.Bin_prot.Type_class.reader
#
val bin_size_query : query Core.Std.Bin_prot.Size.sizer
#
val bin_write_query : query Core.Std.Bin_prot.Write.writer
#
val bin_writer_query : query Core.Std.Bin_prot.Type_class.writer
#
val bin_response : response Core.Std.Bin_prot.Type_class.t
#
val bin_read_response : response Core.Std.Bin_prot.Read.reader
#
val __bin_read_response__ : (int -> response) Core.Std.Bin_prot.Read.reader
#
val bin_reader_response : response Core.Std.Bin_prot.Type_class.reader
#
val bin_size_response : response Core.Std.Bin_prot.Size.sizer
#
val bin_write_response : response Core.Std.Bin_prot.Write.writer
#
val bin_writer_response : response Core.Std.Bin_prot.Type_class.writer
end
) -> sig
end
include S with type caller_query := Model.Caller.query and type caller_response := Model.Caller.response and type callee_query := Model.Callee.query and type callee_response := Model.Callee.response
end
end
end
end