Current section

Files

Jump to
discovery lib discovery.ex
Raw

lib/discovery.ex

#
# The MIT License (MIT)
#
# Copyright (c) 2014-2015 Undead Labs, LLC
#
defmodule Discovery do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
worker(Discovery.Directory, []),
worker(Discovery.NodeConnector, []),
]
opts = [strategy: :one_for_one, name: Discovery.Supervisor]
Supervisor.start_link(children, opts)
end
defdelegate [
nodes(service),
find(service, hash),
], to: Discovery.Directory
@doc """
Returns a list of applications that this process provides.
"""
@spec apps :: [binary]
def apps do
Application.get_env(:discovery, :apps, [])
end
@doc """
Registers the given application as a service discovery provides.
"""
@spec register_app(binary | atom) :: :ok
def register_app(app) when is_atom(app), do: Atom.to_string(app) |> register_app
def register_app(app) do
unless Enum.member?(apps, app) do
Application.put_env(:discovery, :apps, [app|apps])
end
:ok
end
@doc """
Select a node providing the given service and run the run fun with that node.
"""
@spec select(binary, atom | binary, function) :: term | {:error, {:no_servers, binary}}
def select(service, hash, fun) when is_atom(service), do: select(Atom.to_string(service), hash, fun)
def select(service, :random, fun) when is_binary(service) and is_function(fun) do
case nodes(service) do
[] ->
fun.({:error, {:no_servers, service}})
service_nodes ->
index = :random.uniform(Enum.count(service_nodes))
fun.({:ok, Enum.at(service_nodes, index - 1)})
end
end
def select(service, hash, fun) when is_binary(service) and is_function(fun) do
case find(service, hash) do
{:error, _} ->
fun.({:error, {:no_servers, service}})
{:ok, _} = result ->
fun.(result)
end
end
end