diff --git a/server/lib/server_web/controllers/health_controller.ex b/server/lib/server_web/controllers/health_controller.ex new file mode 100644 index 0000000..45f55e4 --- /dev/null +++ b/server/lib/server_web/controllers/health_controller.ex @@ -0,0 +1,35 @@ +defmodule ServerWeb.HealthController do + use ServerWeb, :controller + + @moduledoc """ + Public health check for uptime monitors. + Returns 200 when the process is up AND SQLite is reachable, 503 otherwise. + """ + + def show(conn, _params) do + case probe_db() do + :ok -> + json(conn, %{ + status: "ok", + version: Application.spec(:server, :vsn) |> to_string(), + db: "ok" + }) + + {:error, reason} -> + conn + |> put_status(:service_unavailable) + |> json(%{status: "degraded", db: "error", reason: inspect(reason)}) + end + end + + defp probe_db do + try do + case Ecto.Adapters.SQL.query(Server.Repo, "SELECT 1", []) do + {:ok, _} -> :ok + {:error, e} -> {:error, e} + end + rescue + e -> {:error, e} + end + end +end diff --git a/server/lib/server_web/router.ex b/server/lib/server_web/router.ex index bffd6f2..64f6b61 100644 --- a/server/lib/server_web/router.ex +++ b/server/lib/server_web/router.ex @@ -45,6 +45,12 @@ defmodule ServerWeb.Router do get "/hosts/:name", HostController, :show end + scope "/", ServerWeb do + pipe_through :api + + get "/health", HealthController, :show + end + if Application.compile_env(:server, :dev_routes) do import Phoenix.LiveDashboard.Router diff --git a/server/test/server_web/controllers/health_controller_test.exs b/server/test/server_web/controllers/health_controller_test.exs new file mode 100644 index 0000000..191cbbc --- /dev/null +++ b/server/test/server_web/controllers/health_controller_test.exs @@ -0,0 +1,11 @@ +defmodule ServerWeb.HealthControllerTest do + use ServerWeb.ConnCase, async: true + + test "GET /health returns 200 with status=ok", %{conn: conn} do + conn = get(conn, ~p"/health") + body = json_response(conn, 200) + assert body["status"] == "ok" + assert body["db"] == "ok" + assert is_binary(body["version"]) + end +end