From 0f57d9bb1426833d67c3032e043985ba976b6691 Mon Sep 17 00:00:00 2001 From: Nic-dorman Date: Tue, 5 May 2026 10:49:01 +0100 Subject: [PATCH] feat(antd-elixir): expose new HealthStatus diagnostic fields Mirrors antd-go v0.5.0 / antd-py: %Antd.HealthStatus{} now carries :version, :evm_network, :uptime_seconds, :build_commit, :payment_token_address, and :payment_vault_address. The defstruct gains explicit defaults ("" / 0) for the diagnostic fields so existing struct constructions and pre-0.4.0 daemon responses both still work. REST Antd.Client.health/1 reads each field via Map.get(body, ..., "") with defaults; gRPC Antd.GrpcClient.health/1 pulls each from the regenerated HealthCheckResponse. Mock fixture in client_test.exs extended to populate all 6 fields. Existing assertion expanded. New regression test covers the empty- defaults case for older daemon responses. Note: elixir/mix toolchain isn't available on the orchestrator's Windows host, so `mix test` was not run locally. The diff is mechanical and follows the antd-go / antd-py reference. Part of #37. Co-Authored-By: Claude Opus 4.7 (1M context) --- antd-elixir/lib/antd/client.ex | 12 ++++++- antd-elixir/lib/antd/grpc_client.ex | 12 ++++++- antd-elixir/lib/antd/models.ex | 26 ++++++++++++-- antd-elixir/test/antd/client_test.exs | 50 +++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 8 deletions(-) diff --git a/antd-elixir/lib/antd/client.ex b/antd-elixir/lib/antd/client.ex index e5e9e74..26e9023 100644 --- a/antd-elixir/lib/antd/client.ex +++ b/antd-elixir/lib/antd/client.ex @@ -73,7 +73,17 @@ defmodule Antd.Client do def health(%__MODULE__{} = client) do case do_json(client, :get, "/health", nil) do {:ok, body} -> - {:ok, %Antd.HealthStatus{ok: body["status"] == "ok", network: body["network"]}} + {:ok, + %Antd.HealthStatus{ + ok: body["status"] == "ok", + network: body["network"], + version: Map.get(body, "version", ""), + evm_network: Map.get(body, "evm_network", ""), + uptime_seconds: Map.get(body, "uptime_seconds", 0), + build_commit: Map.get(body, "build_commit", ""), + payment_token_address: Map.get(body, "payment_token_address", ""), + payment_vault_address: Map.get(body, "payment_vault_address", "") + }} {:error, _} = err -> err diff --git a/antd-elixir/lib/antd/grpc_client.ex b/antd-elixir/lib/antd/grpc_client.ex index edf481d..802614a 100644 --- a/antd-elixir/lib/antd/grpc_client.ex +++ b/antd-elixir/lib/antd/grpc_client.ex @@ -92,7 +92,17 @@ defmodule Antd.GrpcClient do case Antd.V1.HealthService.Stub.check(channel, req) do {:ok, resp} -> - {:ok, %Antd.HealthStatus{ok: resp.status == "ok", network: resp.network}} + {:ok, + %Antd.HealthStatus{ + ok: resp.status == "ok", + network: resp.network, + version: resp.version, + evm_network: resp.evm_network, + uptime_seconds: resp.uptime_seconds, + build_commit: resp.build_commit, + payment_token_address: resp.payment_token_address, + payment_vault_address: resp.payment_vault_address + }} {:error, rpc_error} -> {:error, translate_error(rpc_error)} diff --git a/antd-elixir/lib/antd/models.ex b/antd-elixir/lib/antd/models.ex index 4644ef8..949a920 100644 --- a/antd-elixir/lib/antd/models.ex +++ b/antd-elixir/lib/antd/models.ex @@ -1,12 +1,32 @@ defmodule Antd.HealthStatus do - @moduledoc "Result of a health check." + @moduledoc """ + Result of a health check. + + The diagnostic fields (`:version`, `:evm_network`, `:uptime_seconds`, + `:build_commit`, `:payment_token_address`, `:payment_vault_address`) were + added in antd 0.4.0. They default to `""` / `0` so existing struct + constructions and pre-0.4.0 daemon responses both still work. + """ @enforce_keys [:ok, :network] - defstruct [:ok, :network] + defstruct ok: nil, + network: nil, + version: "", + evm_network: "", + uptime_seconds: 0, + build_commit: "", + payment_token_address: "", + payment_vault_address: "" @type t :: %__MODULE__{ ok: boolean(), - network: String.t() + network: String.t(), + version: String.t(), + evm_network: String.t(), + uptime_seconds: non_neg_integer(), + build_commit: String.t(), + payment_token_address: String.t(), + payment_vault_address: String.t() } end diff --git a/antd-elixir/test/antd/client_test.exs b/antd-elixir/test/antd/client_test.exs index e665e70..09f16bd 100644 --- a/antd-elixir/test/antd/client_test.exs +++ b/antd-elixir/test/antd/client_test.exs @@ -11,14 +11,58 @@ defmodule Antd.ClientTest do # Health # --------------------------------------------------------------------------- - test "health/1 returns health status", %{bypass: bypass, client: client} do + test "health/1 returns health status with all diagnostic fields", + %{bypass: bypass, client: client} do Bypass.expect_once(bypass, "GET", "/health", fn conn -> conn |> Plug.Conn.put_resp_content_type("application/json") - |> Plug.Conn.resp(200, Jason.encode!(%{status: "ok", network: "local"})) + |> Plug.Conn.resp( + 200, + Jason.encode!(%{ + status: "ok", + network: "local", + version: "0.4.0", + evm_network: "local", + uptime_seconds: 42, + build_commit: "abcdef123456", + payment_token_address: "0xtoken", + payment_vault_address: "0xvault" + }) + ) end) - assert {:ok, %Antd.HealthStatus{ok: true, network: "local"}} = Antd.Client.health(client) + assert {:ok, + %Antd.HealthStatus{ + ok: true, + network: "local", + version: "0.4.0", + evm_network: "local", + uptime_seconds: 42, + build_commit: "abcdef123456", + payment_token_address: "0xtoken", + payment_vault_address: "0xvault" + }} = Antd.Client.health(client) + end + + test "health/1 defaults diagnostic fields when daemon is pre-0.4.0", + %{bypass: bypass, client: client} do + # Older daemons reply with just status + network; the struct defaults + # populate the diagnostic fields with empty / 0 instead of nil. + Bypass.expect_once(bypass, "GET", "/health", fn conn -> + conn + |> Plug.Conn.put_resp_content_type("application/json") + |> Plug.Conn.resp(200, Jason.encode!(%{status: "ok", network: "default"})) + end) + + assert {:ok, + %Antd.HealthStatus{ + ok: true, + network: "default", + version: "", + evm_network: "", + uptime_seconds: 0, + build_commit: "" + }} = Antd.Client.health(client) end # ---------------------------------------------------------------------------