Current section

Files

Jump to
etcdex lib etcd_ex connection.ex
Raw

lib/etcd_ex/connection.ex

defmodule EtcdEx.Connection do
@moduledoc """
Represents a connection to Etcd.
"""
use GenServer
@type t :: atom
@default_eetcd_options []
@default_eetcd_transport :tcp
@default_eetcd_transport_opts []
@doc false
def get(conn, request), do: GenServer.call(conn, {:get, request}, :infinity)
@doc false
def put(conn, request), do: GenServer.call(conn, {:put, request}, :infinity)
@doc false
def delete(conn, request), do: GenServer.call(conn, {:delete, request}, :infinity)
@doc false
def grant(conn, ttl, request), do: GenServer.call(conn, {:grant, ttl, request}, :infinity)
@doc false
def revoke(conn, lease_id, request),
do: GenServer.call(conn, {:revoke, lease_id, request}, :infinity)
@doc false
def keep_alive_once(conn, lease_id),
do: GenServer.call(conn, {:keep_alive_once, lease_id}, :infinity)
@doc false
def ttl(conn, lease_id, with_keys),
do: GenServer.call(conn, {:ttl, lease_id, with_keys}, :infinity)
@doc false
def leases(conn), do: GenServer.call(conn, :leases, :infinity)
@doc false
def start_link(options) do
name =
case Keyword.fetch(options, :name) do
{:ok, name} when is_atom(name) ->
name
{:ok, other} ->
raise ArgumentError, "expected :name to be an atom, got: #{inspect(other)}"
:error ->
raise ArgumentError, "expected :name option to be present"
end
endpoints =
case Keyword.fetch(options, :endpoints) do
{:ok, endpoints} when is_list(endpoints) ->
Enum.map(endpoints, &String.to_charlist/1)
{:ok, other} ->
raise ArgumentError,
"expected :endpoints to be a list of strings, got: #{inspect(other)}"
:error ->
['localhost:2379']
end
options = Keyword.get(options, :options, @default_eetcd_options)
transport = Keyword.get(options, :transport, @default_eetcd_transport)
transport_opts = Keyword.get(options, :transport_opts, @default_eetcd_transport_opts)
init_opts = {name, endpoints, options, transport, transport_opts}
GenServer.start_link(__MODULE__, init_opts, name: name)
end
@impl true
def init({name, endpoints, options, transport, transport_opts}) do
case :eetcd.open(name, endpoints, options, transport, transport_opts) do
{:ok, _pid} ->
{:ok, name}
{:error, reason} ->
{:stop, reason}
end
end
@impl true
def handle_call({method, request}, _from, state) when method in [:get, :put, :delete] do
result = apply(:eetcd_kv, method, [request])
{:reply, result, state}
end
def handle_call({:grant, ttl, request}, _from, state) do
result = :eetcd_lease.grant(request, ttl)
{:reply, result, state}
end
def handle_call({:revoke, lease_id, request}, _from, state) do
result = :eetcd_lease.revoke(request, lease_id)
{:reply, result, state}
end
def handle_call({:keep_alive_once, lease_id}, _from, state) do
result = :eetcd_lease.keep_alive_once(state, lease_id)
{:reply, result, state}
end
def handle_call({:ttl, lease_id, with_keys}, _from, state) do
result = :eetcd_lease.time_to_live(state, lease_id, with_keys)
{:reply, result, state}
end
def handle_call(:leases, _from, state) do
result = :eetcd_lease.leases(state)
{:reply, result, state}
end
@impl true
def handle_info(_message, state) do
# XXX: this is required by Gun, as sometimes it keeps sending messages even
# though the request has already finished (specially on error conditions).
{:noreply, state}
end
end