Packages

Self-healing clusters for Gleam applications on the BEAM!

Current section

Files

Jump to
barnacle src barnacle@dns.erl
Raw

src/barnacle@dns.erl

-module(barnacle@dns).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([dns_lookup/2, discover_nodes/3]).
-export_type([lookup_error/0, ip_address/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type lookup_error() :: format_error |
query_format_error |
server_failure |
no_such_domain |
timeout |
not_implemented |
refused |
bad_version |
{posix_error, binary()} |
unknown.
-type ip_address() :: {ip_v4, integer(), integer(), integer(), integer()} |
{ip_v6,
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer()}.
-file("src/barnacle/dns.gleam", 40).
?DOC(
" Perform a DNS lookup against a hostname. This will return a list of IP\n"
" addresses. Queries will be performed using the `A` and `AAAA` record types.\n"
).
-spec dns_lookup(binary(), integer()) -> {ok, list(ip_address())} |
{error, lookup_error()}.
dns_lookup(Hostname, Timeout) ->
gleam@result:'try'(
barnacle_ffi:lookup_a(Hostname, Timeout),
fun(A_records) ->
A_records@1 = begin
_pipe = A_records,
gleam@list:map(
_pipe,
fun(Ip) ->
{A, B, C, D} = Ip,
{ip_v4, A, B, C, D}
end
)
end,
gleam@result:'try'(
barnacle_ffi:lookup_aaaa(Hostname, Timeout),
fun(Aaaa_records) ->
Aaaa_records@1 = begin
_pipe@1 = Aaaa_records,
gleam@list:map(
_pipe@1,
fun(Ip@1) ->
{A@1, B@1, C@1, D@1, E, F, G, H} = Ip@1,
{ip_v6, A@1, B@1, C@1, D@1, E, F, G, H}
end
)
end,
{ok, lists:append(A_records@1, Aaaa_records@1)}
end
)
end
).
-file("src/barnacle/dns.gleam", 65).
-spec format_ip_address(ip_address()) -> binary().
format_ip_address(Ip) ->
case Ip of
{ip_v4, A, B, C, D} ->
_pipe = [A, B, C, D],
_pipe@1 = gleam@list:map(_pipe, fun erlang:integer_to_binary/1),
gleam@string:join(_pipe@1, <<"."/utf8>>);
{ip_v6, A@1, B@1, C@1, D@1, E, F, G, H} ->
_pipe@2 = [A@1, B@1, C@1, D@1, E, F, G, H],
_pipe@3 = gleam@list:map(_pipe@2, fun(Value) -> case Value of
0 ->
<<""/utf8>>;
_ ->
gleam@int:to_base16(Value)
end end),
_pipe@4 = gleam@string:join(_pipe@3, <<":"/utf8>>),
string:lowercase(_pipe@4)
end.
-file("src/barnacle/dns.gleam", 92).
?DOC(
" Discover nodes using DNS. The first argument is the basename of the nodes.\n"
" Currently, Barnacle only supports connecting to nodes with the same basename.\n"
"\n"
" The second argument is the hostname to query against. Both A and AAAA records\n"
" will be queried. The final argument is an optional timeout for the DNS\n"
" lookup. This defaults to 5000ms if not supplied.\n"
).
-spec discover_nodes(binary(), binary(), integer()) -> {ok,
list(gleam@erlang@atom:atom_())} |
{error, lookup_error()}.
discover_nodes(Basename, Hostname_query, Timeout) ->
gleam@result:'try'(
dns_lookup(Hostname_query, Timeout),
fun(Ip_addresses) -> _pipe = Ip_addresses,
_pipe@2 = gleam@list:map(
_pipe,
fun(Ip) ->
Ip_string = format_ip_address(Ip),
_pipe@1 = (<<<<Basename/binary, "@"/utf8>>/binary,
Ip_string/binary>>),
erlang:binary_to_atom(_pipe@1)
end
),
{ok, _pipe@2} end
).