diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/exping.ex | 20 | ||||
-rw-r--r-- | lib/exping/http.ex | 45 | ||||
-rw-r--r-- | lib/exping/http/task.ex | 45 | ||||
-rw-r--r-- | lib/exping/supervisor.ex | 1 |
4 files changed, 111 insertions, 0 deletions
diff --git a/lib/exping.ex b/lib/exping.ex index 056bfda..c63c37a 100644 --- a/lib/exping.ex +++ b/lib/exping.ex @@ -1,5 +1,25 @@ defmodule ExPing do + require Logger @moduledoc """ Public API for ExPing """ + + @pings [&ExPing.HTTP.get/1, &ExPing.HTTP.head/1] + + @spec ping(URI.t) :: boolean + def ping(address) do + :ok = Logger.info("Attempting to ping #{inspect(address)}") + @pings + |> Enum.map(&spawn_ping(&1, address)) + |> Enum.all? + end + + @spec spawn_ping(fun, URI.t) :: boolean + defp spawn_ping(ping, address) do + case ping.(address) do + {:ok, _} -> true + {:error, _} -> false + end + end + end diff --git a/lib/exping/http.ex b/lib/exping/http.ex new file mode 100644 index 0000000..576562f --- /dev/null +++ b/lib/exping/http.ex @@ -0,0 +1,45 @@ +defmodule ExPing.HTTP do + require Logger + @moduledoc """ + Provides basic HTTP client for pinging endpoints + """ + + @timeout Application.get_env(:exping, :http)[:timeout] || 5000 + + @spec head(URI.t) :: {:ok, {integer, binary}} | {:error, term} + def head(endpoint) do + ref = make_ref() + :ok = Logger.info("Sending HEAD request to #{inspect(endpoint)}") + {:ok, _} = spawn_http_task(:head, [endpoint, ref, self()]) + + receive do + {:http_task_resp, ^ref, {:ok, {_, _}} = resp} -> resp + {:http_task_resp, ^ref, {:error, _} = error} -> error + after @timeout -> + {:error, :timeout} + end + end + + @spec get(URI.t) :: {:ok, {integer, binary}} | {:error, term} + def get(endpoint) do + ref = make_ref() + :ok = Logger.info("Sending GET request to #{inspect(endpoint)}") + {:ok, _} = spawn_http_task(:get, [endpoint, ref, self()]) + + receive do + {:http_task_resp, ^ref, {:ok, _} = resp} -> resp + {:http_task_resp, ^ref, {:error, _} = error} -> error + after @timeout -> + {:error, :timeout} + end + end + + defp spawn_http_task(method, args) do + Task.Supervisor.start_child( + ExPing.Supervisor.Task, + ExPing.HTTP.Task, + method, + args) + end + +end diff --git a/lib/exping/http/task.ex b/lib/exping/http/task.ex new file mode 100644 index 0000000..f9d39f5 --- /dev/null +++ b/lib/exping/http/task.ex @@ -0,0 +1,45 @@ +defmodule ExPing.HTTP.Task do + require Logger + @moduledoc """ + Task module for performing HTTP requests + """ + + @user_agent {'user-agent', 'exping'} + + @http Application.get_env(:exping, :http_client) || :httpc + + @type response :: {integer, binary} + + @spec head(URI.t, reference, pid) :: {:ok, response} | {:error, term} + def head(%URI{} = uri, ref, owner) do + :head + |> @http.request({endpoint(uri), headers()}, [], []) + |> process_response(ref, owner) + end + + @spec get(URI.t, reference, pid) :: {:ok, response} | {:error, term} + def get(%URI{} = uri, ref, owner) do + :get + |> @http.request({endpoint(uri), headers()}, [], []) + |> process_response(ref, owner) + end + + defp process_response({:ok, {{_, code, _}, _, body}}, ref, owner) do + :ok = Logger.info("HTTP request returned: #{code}") + send(owner, {:http_task_resp, ref, {:ok, {code, body}}}) + end + + defp process_response({:error, _} = error, ref, owner) do + :ok = Logger.warn("HTTP request returned error: #{inspect(error)}") + send(owner, {:http_task_resp, ref, error}) + end + + defp endpoint(%URI{} = uri) do + uri |> to_string() |> String.to_charlist + end + + defp headers do + [@user_agent] + end + +end diff --git a/lib/exping/supervisor.ex b/lib/exping/supervisor.ex index 403f35c..faf6ccb 100644 --- a/lib/exping/supervisor.ex +++ b/lib/exping/supervisor.ex @@ -13,6 +13,7 @@ defmodule ExPing.Supervisor do @spec init(any) :: no_return def init(_) do children = [ + supervisor(Task.Supervisor, [[name: ExPing.Supervisor.Task]]) ] supervise(children, strategy: :one_for_one, name: __MODULE__) |