Current section
Files
Jump to
Current section
Files
lib/ping_plug.ex
defmodule PingPlug do
@moduledoc """
PingPlug, a plug to echo a defined message.
PingPlug can be used in two ways, execute a function or echo a message.
#### Execute a function
To execute any function you must define a module function that return:
{:ok, String.t()} | {:error, String.t()}
In which,
* `:ok` will be mapped to HTTP 200, and
* `:error` will be mapped to HTTP 500
A simple use case is to use it as a liveness probe. For example, configure
PingPlug to match a specific path and execute dependency checks.
## Examples
Here is an example of returning a value when a request hits
`/_checks/liveness` path.
```
# endpoint.ex
plug PingPlug, path: ["_checks", "liveness"], return: "alive!"
```
Here is an example of executing a function to check database connectivity.
First, define a module that sends a query to a database to ensure it is up and
running.
```
# db_check.ex
defmodule DBCheck do
@behaviour PingPlug
@impl true
def check do
case Ecto.Adapters.SQL.query(Repo, "SELECT 1") do
{:ok, _result} ->
{:ok, "ready!"}
{:error, exception} ->
{:error, Exception.message(exception)}
end
end
end
```
Then plug it into the readiness endpoint.
```
# endpoint.ex
plug PingPlug, path: ["_checks", "readiness"], execute: {DBCheck, :check, []}
```
"""
@type execute :: {module(), function_name :: atom(), [any()]}
@type options :: [{:path, nonempty_list()}, {:return, String.t()}, {:execute, execute()}]
import Plug.Conn
@spec init(options()) :: options()
def init([{:path, [_ | _]} | _] = options) do
options
end
@spec call(Plug.Conn.t(), options()) :: Plug.Conn.t()
def call(%Plug.Conn{path_info: path_info} = conn, [{:path, path}, {:return, message}]) do
if path_info == path do
conn
|> resp(:ok, message)
|> halt()
else
conn
end
end
def call(%Plug.Conn{path_info: path_info} = conn, [
{:path, path},
{:execute, {mod, function_name, args}}
]) do
if path_info == path do
case apply(mod, function_name, args) do
{:ok, message} ->
conn
|> resp(:ok, message)
|> halt()
{:error, message} ->
conn
|> resp(:internal_server_error, message)
|> halt()
end
else
conn
end
end
end