Current section

Files

Jump to
shackle src shackle.erl
Raw

src/shackle.erl

-module(shackle).
-include("shackle_internal.hrl").
-compile(inline).
-compile({inline_size, 512}).
%% public
-export([
call/2,
call/3,
cast/2,
cast/3,
cast/4,
receive_response/1,
receive_response/2
]).
%% types
-type cast() :: #cast {}.
-type cast_error() :: no_server | pool_not_started | shackle_not_started.
-type client() :: module().
-type external_request_id() :: term().
-type inet_address() :: inet:ip_address() | inet:hostname().
-type inet_port() :: inet:port_number().
-type protocol() :: shackle_ssl| shackle_tcp | shackle_udp.
-type request_id() :: {shackle_server:name(), reference()}.
-type response() :: {external_request_id(), term()}.
-type socket() :: inet:socket() | ssl:sslsocket().
-type socket_option() :: gen_tcp:connect_option() | gen_udp:option() | ssl:tls_client_option().
-type socket_options() :: [socket_option()].
-type table() :: atom().
-type time() :: pos_integer().
-export_type([
cast/0,
cast_error/0,
client/0,
external_request_id/0,
inet_address/0,
inet_port/0,
protocol/0,
request_id/0,
response/0,
socket/0,
socket_options/0,
table/0,
time/0
]).
%% public
-spec call(shackle_pool:name(), term()) ->
term() | {error, cast_error()}.
call(PoolName, Request) ->
call(PoolName, Request, ?DEFAULT_TIMEOUT).
-spec call(atom(), term(), timeout()) ->
term() | {error, cast_error()}.
call(PoolName, Request, Timeout) ->
case cast(PoolName, Request, self(), Timeout) of
{ok, RequestId} ->
receive_response(RequestId);
{error, Reason} ->
{error, Reason}
end.
-spec cast(shackle_pool:name(), term()) ->
{ok, request_id()} | {error, cast_error()}.
cast(PoolName, Request) ->
cast(PoolName, Request, self()).
-spec cast(shackle_pool:name(), term(), undefined | pid()) ->
{ok, request_id()} | {error, cast_error()}.
cast(PoolName, Request, Pid) ->
cast(PoolName, Request, Pid, ?DEFAULT_TIMEOUT).
-spec cast(shackle_pool:name(), term(), undefined | pid(), timeout()) ->
{ok, request_id()} | {error, cast_error()}.
cast(PoolName, Request, Pid, Timeout) ->
Timestamp = erlang:monotonic_time(microsecond),
Ref = make_ref(),
case shackle_pool:server(PoolName) of
{ok, Client, Server} ->
RequestId = {Server, Ref},
Server ! {Request, #cast {
client = Client,
pid = Pid,
request_id = RequestId,
timeout = Timeout,
timestamp = Timestamp
}},
{ok, RequestId};
{error, Reason} ->
{error, Reason}
end.
-spec receive_response(request_id()) ->
term() | {error, term()}.
receive_response(RequestId) ->
receive
{#cast {request_id = RequestId}, Reply} ->
Reply
end.
-spec receive_response(request_id(), timeout()) ->
term() | {error, timeout | term()}.
receive_response(RequestId, Timeout) ->
receive
{#cast {request_id = RequestId}, Reply} ->
Reply
after Timeout ->
{error, timeout}
end.