defmodule MeshxRpc.Common.Options do @moduledoc false def common(), do: [ pool_opts: [ type: :keyword_list, default: [], doc: """ worker pool options for RPC client and server. Server pool is build using [`ranch` socket acceptor pool](https://hex.pm/packages/ranch). `pool_opts` correspond in this case to `ranch` [transport options](https://ninenines.eu/docs/en/ranch/2.0/manual/ranch/). Client pool is build using [`poolboy`](https://hex.pm/packages/poolboy), `pool_opts` correspond here directly to [`poolboy` options](https://github.com/devinus/poolboy#options). Users usually should not set any `pool_opts` for server pools. Options that can be set for RPC client pools: * `:size` - maximum pool size, default 10, * `:max_overflow` - maximum number of workers created if pool is empty, * `:strategy` - `:lifo` or `:fifo`, determines whether checked in workers should be placed first or last in the line of available workers. So, `:lifo` operates like a traditional stack; `:fifo` like a queue. Default is `:lifo`. * """ ], address: [ type: {:custom, __MODULE__, :address, []}, required: true, doc: """ Address on which server will listen for requests or client will send requests to. Two address types are supported: * ethernet interface address: `{:tcp, ip, port}`, where `ip` is defined as tuple (e.g. `{127, 0, 0, 1}`) and `port` is integer in the range `1..65535`, * Unix Domain Socket address: `{:uds, path}`, where socket `path` is defined as string, e.g. `{:uds, "/tmp/beam.sock"}` """ ], blk_max_size: [ type: {:custom, __MODULE__, :int_range, [200..268_435_456]}, default: 16384, doc: """ user request function arguments are first serialized into binary using function specified with `:serialize_mfa` option. Binary is then split into smaller blocks send over the wire. Option defines maximum send block byte size. Must be between 200 bytes and 256 MB (`200..268_435_456`). """ ], cks_mfa: [ type: {:or, [:mfa, :atom]}, default: nil, doc: """ block checksum function `{module, function, argument}`. 2-arity function accepting: 1st argument - binary data to calculate checksum, 2nd argument - as set in option `argument`. Function result should be calculated checksum of `binary()` type. Example checksum implementation is `MeshxRpc.Protocol.Default.checksum/2`, using `:erlang.crc32/1`. To use this function set: `[cks_mfa: {MeshxRpc.Protocol.Default, :checksum, []}]`. If option is left undefined checksums are not calculated. """ ], conn_ref_mfa: [ type: {:or, [:mfa, :string, :atom]}, default: {MeshxRpc.Protocol.Default, :conn_ref, []}, doc: """ `{module, function, argument}` function generating connection reference, 0-arity. """ ], deserialize_mfa: [ type: :mfa, default: {MeshxRpc.Protocol.Default, :deserialize, []}, doc: """ `{module, function, argument}` function used to de-serialize request argument, 3-arity. Function should reverse data serialization process executed by function specified by `:serialize_mfa`. First function argument is binary data to de-serialize, second is option `argument`, third is serialization flag generated by `:serialize_mfa`. Function should return `{:ok, deserialized}` if successful, `{:error, reason}` otherwise. """ ], hsk_dgt_mfa: [ type: :mfa, default: {MeshxRpc.Protocol.Default, :checksum, []}, doc: """ `{module, function, argument}` function used to calculate digest in connection handshake, 2-arity. First argument is binary data for which digest should be calculated, second is option `argument`. """ ], node_ref_mfa: [ type: {:or, [:mfa, :string, :atom]}, default: {MeshxRpc.Protocol.Default, :node_ref, []}, doc: """ `{module, function, argument}` function generating request node reference, 0-arity. """ ], quiet_on_hsk_error?: [ type: :boolean, default: false, doc: """ when connection is established between RPC server and client first step is a two-way handshake. If handshake fails remote node can be notified about failure or failure can be silently discarded. """ ], serialize_mfa: [ type: :mfa, default: {MeshxRpc.Protocol.Default, :serialize, []}, doc: """ `{module, function, argument}` function used to serialize user request function argument(s), 2-arity. First argument is erlang term that requires serialization, second is option `argument`. Function should return if successful `{:ok, serialized_binary, serialization_flag}`. `serialization_flag` should be one byte integer (`0..255`). It states how data should be de-serialized and will be passed as third argument to function specified in `:deserialize_mfa`. In case of error function should return `{:error, reason}`. """ ], shared_key: [ type: :string, default: "", doc: """ shared key must be same for connecting server and client. Can be used to specify for example API version: `shared_key: "api_ver_01"`. """ ], socket_opts: [ type: :keyword_list, default: [], doc: """ connection socket options. Check `:inet.setopts/2` for available settings. """ ], svc_ref_mfa: [ type: {:or, [:mfa, :string, :atom]}, doc: """ `{module, function, argument}` function generating request service reference, 0-arity. If not defined, by default service reference will be calculated from: `service_id |> to_string() |> String.slice(0..255)`. """ ], telemetry_prefix: [ type: {:list, :atom}, doc: """ specifies prefix used when executing telemetry events. If not defined package name and service module will be used, e.g.: `[:meshx_rpc, MyApp.Rpc.Server1]`. """ ], timeout_hsk: [ type: :timeout, default: 5_000, doc: """ handshake timeout. """ ], timeout_cks: [ type: :timeout, default: 500, doc: """ timeout for function calculating block checksums specified by `:cks_mfa`. """ ], gen_statem_opts: [ type: :keyword_list, default: [], doc: """ option passed as third argument to `:gen_statem.start_link/3` when starting RPC server or client pool worker. """ ] ] def int_range(val, min..max) when val in min..max, do: {:ok, val} def int_range(val, range), do: {:error, "Expected integer in range min..max, got: #{inspect(val)} in #{inspect(range)}."} def address(val) do case val do {:tcp, ip, port} when port in 1..65535 -> case :inet.ntoa(ip) do {:error, _e} -> {:error, ~s(Expected socket address, e.g.: {:tcp, {127, 0, 0, 1}, 3333} or {:uds, "/tmp/beam.sock"}. Got: #{inspect(val)})} _ip -> {:ok, val} end {:uds, path} when is_bitstring(path) -> {:ok, {:uds, {:local, path}, 0}} _e -> {:error, ~s(Expected socket address, e.g.: {:tcp, {127, 0, 0, 1}, 3333} or {:uds, "/tmp/beam.sock"}. Got: #{inspect(val)})} end end end