erps v0.2.0 Erps.Client behaviour View Source
Create an Erps client GenServer.
The best way to think of an Erps client is that it is a GenServer that forwards
its call/2
and cast/2
callbacks to a remote GenServer over a LAN or WAN.
This callbacks would normally be provided by standard GenServer.call/2
and
GenServer.cast/2
semantics over erlang distribution but in some cases you may
want to issue a remote protocol request over high-latency or unreliable network
stretches, or in cases where you would like to have an OTP-supervised connection
orthogonal to standard erlang distribution semantics.
Basic operation
Presuming you have set up an Erps server GenServer on some host at @hostname
,
you can connect the client and the server simply by instantiating the server
module.
Example
defmodule ErpsClient do
use Erps.Client
@hostname <...>
@port <...>
def start_link, do: Erps.Client.start_link(__MODULE__, :ok,
server: @hostname, port: @port, tls_opts: [...])
def init(init_state), do: {:ok, init_state}
end
{:ok, client} = ErpsClient.start_link
GenServer.call(client, :some_remote_call)
# => :some_remote_response
Module options
:version
the version of your Erps API messages. Should be a SemVer string. seeVersion
for more information.:identifier
a binary identifier for your Erps API endpoint. Maximum 12 bytes, suggested to be human-readable.:sign_with
defines the cryptographic signing function for your Erps client/server pair. May take one of two forms:function
(wherefunction
is an atom) calls the signing functionmodule.function/2
with the unsigned binary as the first parameter, and thehmac_key
(seestart_link/3
options) as the second parameter. Thehmac_key
is passed to the function in the event that the client has a KV store which should be queried to find the appropriate signing key for the requested connection instance.module.function/2
should emit a 32-byte signature in response.{external_module, function}
callsexternal_module.function/2
in the same fashion as above.
:safe
(see:erlang.binary_to_term/2
), for decoding terms. If set tofalse
, then allows undefined atoms and lambdas to be passed via the protocol. This should be used with extreme caution, as disabling safe mode can be an attack vector. (defaults totrue
)
Example
defmodule MyClient do
use Erps.Client, version: "0.2.4",
identifier: "my_api",
sign_with: :signing,
safe: false
def signing(binary, hmac_key) do
:crypto.mac(:hmac, :sha256, SecretProvider.secret_for(hmac_key), binary)
end
def start_link(iv) do
Erps.Client.start_link(__MODULE__, init,
hmac_key: "ABCDEFGHIJKLMNOP",
server: "my_api-server.example.com",
port: 4747,
transport: Erps.Transport.Tls,
tls_opts: [...])
end
def init(iv), do: {:ok, iv}
end
Link to this section Summary
Functions
starts a client GenServer, not linked to the caller. Most useful for tests.
starts a client GenServer, linked to the caller.
Callbacks
Invoked when an internal callback requests a continuation, using {:noreply, state, {:continue, continuation}}
, or from init/1
using
{:ok, state, {:continue, continuation}}
Invoked to handle general messages sent to the client process.
Invoked to handle Erps.Server.push/2
messages.
Invoked to set up the process.
Invoked when the client is about to exit.
Link to this section Types
hmac_function()
View Source
hmac_function() :: (() -> String.t())
hmac_function() :: (() -> String.t())
signing_function() View Source
Link to this section Functions
start(module, state, opts) View Source
starts a client GenServer, not linked to the caller. Most useful for tests.
see start_link/3
for a description of avaliable options.
start_link(module, state, opts) View Source
starts a client GenServer, linked to the caller.
Will attempt to contact the server over the specified transport strategy. If the connection fails, the client will be placed in an invalid state until connection succeeds, with a reconnect interval specified in the module options.
options
:server
IP address of the target server (required):port
IP port of the target server (required):transport
module for communication transport strategy:keepalive
time interval for sending a TCP/IP keepalive token.:hmac_key
one of two options:function/0
a zero-arity function which can be used to fetch the key at runtimebinary
a directly instrumented value (this could be fetched at vm startup time and pulled fromSystem.get_env/1
orApplication.get_env/2
)
:tls_opts
options for setting up a TLS connection.:cacertfile
path to the certificate of your signing authority. (required):certfile
path to the server certificate file. (required forErps.Transport.Tls
):keyfile
path to the signing key. (required forErps.Transport.Tls
)
see GenServer.start_link/3
for a description of further options.
Link to this section Callbacks
handle_continue(continue, state) View Source (optional)
Invoked when an internal callback requests a continuation, using {:noreply, state, {:continue, continuation}}
, or from init/1
using
{:ok, state, {:continue, continuation}}
The continuation is passed as the first argument of this callback. Most
useful if init/1
functionality is long-running and needs to be broken
up into separate parts so that the calling start_link/3
doesn't block.
see: GenServer.handle_continue/2
.
Return codes
{:noreply, new_state}
continues the loop with new statenew_state
{:noreply, new_state, timeout}
causes a :timeout message to be sent tohandle_info/2
if no other message comes by{:noreply, new_state, :hibernate}
, causes a hibernation event (see:erlang.hibernate/3
){:noreply, new_state, {:continue, term}}
causes a continuation to be triggered after the message is handled, it will be sent toc:handle_continue/3
{:stop, reason, new_state}
terminates the loop, passingnew_state
toterminate/2
, if it's implemented.
handle_info(msg, state) View Source (optional)
Invoked to handle general messages sent to the client process.
Most useful if the client needs to be attentive to system messages, such as nodedown or monitored processes, but also useful for internal timeouts.
see: GenServer.handle_info/2
.
Return codes
see return codes for handle_continue/2
handle_push(push, state) View Source (optional)
Invoked to handle Erps.Server.push/2
messages.
push
is the push message sent by a Erps.Server.push/2
and state
is the
current state of the Erps.Client
.
Return codes
see return codes for handle_continue/2
init(init_arg) View Source
Invoked to set up the process.
Like GenServer.init/1
, this function is called from inside
the process immediately after start_link/3
or start/3
.
Return codes
{:ok, state}
a succesful startup of your intialization logic and sets the internal state of your server tostate
.{:ok, state, timeout}
the above, plus a :timeout atom will be sent tohandle_info/2
if no other messages come by.{:ok, state, :hibernate}
successful startup, followed by a hibernation event (see:erlang.hibernate/3
){:ok, state, {:continue, term}}
successful startup, and causes a continuation to be triggered after the message is handled, sent toc:handle_continue/3
:ignore
- Drop the gen_server creation request, because for some reason it shouldn't have started.{:stop, reason}
- a failure in creating the gen_server. Results in{:error, reason}
being propagated as the result of the start_link
terminate(reason, state) View Source (optional)
Invoked when the client is about to exit.
This would usually occur due to handle_push/2
returning a
{:stop, reason, new_state}
tuple, but also if the TCP connection
happens to go down.