commit
4b268fe85a
@ -0,0 +1,49 @@ |
|||||||
|
defmodule BlockScoutWeb.API.V1.HealthController do |
||||||
|
use BlockScoutWeb, :controller |
||||||
|
|
||||||
|
alias Explorer.Chain |
||||||
|
|
||||||
|
def health(conn, _) do |
||||||
|
with {:ok, number, timestamp} <- Chain.last_block_status() do |
||||||
|
send_resp(conn, :ok, result(number, timestamp)) |
||||||
|
else |
||||||
|
status -> send_resp(conn, :internal_server_error, error(status)) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def result(number, timestamp) do |
||||||
|
%{ |
||||||
|
"healthy" => true, |
||||||
|
"data" => %{ |
||||||
|
"latest_block_number" => to_string(number), |
||||||
|
"latest_block_inserted_at" => to_string(timestamp) |
||||||
|
} |
||||||
|
} |
||||||
|
|> Jason.encode!() |
||||||
|
end |
||||||
|
|
||||||
|
def error({:error, :no_blocks}) do |
||||||
|
%{ |
||||||
|
"healthy" => false, |
||||||
|
"error_code" => 5002, |
||||||
|
"error_title" => "no blocks in db", |
||||||
|
"error_description" => "There are no blocks in the DB" |
||||||
|
} |
||||||
|
|> Jason.encode!() |
||||||
|
end |
||||||
|
|
||||||
|
def error({:error, number, timestamp}) do |
||||||
|
%{ |
||||||
|
"healthy" => false, |
||||||
|
"error_code" => 5001, |
||||||
|
"error_title" => "blocks fetching is stuck", |
||||||
|
"error_description" => |
||||||
|
"There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance", |
||||||
|
"data" => %{ |
||||||
|
"latest_block_number" => to_string(number), |
||||||
|
"latest_block_inserted_at" => to_string(timestamp) |
||||||
|
} |
||||||
|
} |
||||||
|
|> Jason.encode!() |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,50 @@ |
|||||||
|
defmodule BlockScoutWeb.API.V1.HealthControllerTest do |
||||||
|
use BlockScoutWeb.ConnCase |
||||||
|
|
||||||
|
describe "GET last_block_status/0" do |
||||||
|
test "returns error when there are no blocks in db", %{conn: conn} do |
||||||
|
request = get(conn, api_v1_health_path(conn, :health)) |
||||||
|
|
||||||
|
assert request.status == 500 |
||||||
|
|
||||||
|
assert request.resp_body == |
||||||
|
"{\"error_code\":5002,\"error_description\":\"There are no blocks in the DB\",\"error_title\":\"no blocks in db\",\"healthy\":false}" |
||||||
|
end |
||||||
|
|
||||||
|
test "returns error when last block is stale", %{conn: conn} do |
||||||
|
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) |
||||||
|
|
||||||
|
request = get(conn, api_v1_health_path(conn, :health)) |
||||||
|
|
||||||
|
assert request.status == 500 |
||||||
|
|
||||||
|
assert %{ |
||||||
|
"healthy" => false, |
||||||
|
"error_code" => 5001, |
||||||
|
"error_title" => "blocks fetching is stuck", |
||||||
|
"error_description" => |
||||||
|
"There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance", |
||||||
|
"data" => %{ |
||||||
|
"latest_block_number" => _, |
||||||
|
"latest_block_inserted_at" => _ |
||||||
|
} |
||||||
|
} = Poison.decode!(request.resp_body) |
||||||
|
end |
||||||
|
|
||||||
|
test "returns ok when last block is not stale", %{conn: conn} do |
||||||
|
insert(:block, consensus: true, timestamp: DateTime.utc_now()) |
||||||
|
|
||||||
|
request = get(conn, api_v1_health_path(conn, :health)) |
||||||
|
|
||||||
|
assert request.status == 200 |
||||||
|
|
||||||
|
assert %{ |
||||||
|
"healthy" => true, |
||||||
|
"data" => %{ |
||||||
|
"latest_block_number" => _, |
||||||
|
"latest_block_inserted_at" => _ |
||||||
|
} |
||||||
|
} = Poison.decode!(request.resp_body) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue