Align websocket and admin APIs with shared surfaces
This commit is contained in:
@@ -120,9 +120,16 @@ defmodule Parrhesia.API.SyncTest do
|
||||
assert sync_stats["sync"]["servers_total"] == 1
|
||||
assert sync_stats["sync"]["query_runs"] == 1
|
||||
|
||||
assert {:ok, execute_stats} = Admin.execute("stats", %{}, manager: manager)
|
||||
assert execute_stats["sync"]["servers_total"] == 1
|
||||
|
||||
assert {:ok, health} = Admin.health(manager: manager)
|
||||
assert health["status"] == "ok"
|
||||
assert health["sync"]["servers_total"] == 1
|
||||
|
||||
assert {:ok, execute_health} = Admin.execute("health", %{}, manager: manager)
|
||||
assert execute_health["status"] == "ok"
|
||||
assert execute_health["sync"]["servers_total"] == 1
|
||||
end
|
||||
|
||||
defp start_sync_manager do
|
||||
|
||||
@@ -3,6 +3,8 @@ defmodule Parrhesia.Web.ConnectionTest do
|
||||
|
||||
alias Ecto.Adapters.SQL.Sandbox
|
||||
alias Parrhesia.API.ACL
|
||||
alias Parrhesia.API.Events
|
||||
alias Parrhesia.API.RequestContext
|
||||
alias Parrhesia.Negentropy.Engine
|
||||
alias Parrhesia.Negentropy.Message
|
||||
alias Parrhesia.Protocol.EventValidator
|
||||
@@ -11,6 +13,7 @@ defmodule Parrhesia.Web.ConnectionTest do
|
||||
|
||||
setup do
|
||||
:ok = Sandbox.checkout(Repo)
|
||||
ensure_stream_runtime_started()
|
||||
:ok
|
||||
end
|
||||
|
||||
@@ -738,16 +741,47 @@ defmodule Parrhesia.Web.ConnectionTest do
|
||||
|
||||
test "CLOSE removes subscription and replies with CLOSED" do
|
||||
state = subscribed_connection_state([])
|
||||
subscription = state.subscriptions["sub-1"]
|
||||
[{stream_pid, _value}] = Registry.lookup(Parrhesia.API.Stream.Registry, subscription.ref)
|
||||
monitor_ref = Process.monitor(stream_pid)
|
||||
|
||||
close_payload = JSON.encode!(["CLOSE", "sub-1"])
|
||||
|
||||
assert {:push, {:text, response}, next_state} =
|
||||
Connection.handle_in({close_payload, [opcode: :text]}, state)
|
||||
|
||||
assert_receive {:DOWN, ^monitor_ref, :process, ^stream_pid, :normal}
|
||||
refute Map.has_key?(next_state.subscriptions, "sub-1")
|
||||
assert JSON.decode!(response) == ["CLOSED", "sub-1", "error: subscription closed"]
|
||||
end
|
||||
|
||||
test "REQ live delivery is bridged through API.Stream" do
|
||||
state = subscribed_connection_state([])
|
||||
subscription = state.subscriptions["sub-1"]
|
||||
subscription_ref = subscription.ref
|
||||
event = valid_event(%{"content" => "stream-live"}) |> recalculate_event_id()
|
||||
|
||||
assert {:ok, %{accepted: true}} = Events.publish(event, context: %RequestContext{})
|
||||
|
||||
assert_receive {:parrhesia, :event, ^subscription_ref, "sub-1", received_event}
|
||||
assert received_event["id"] == event["id"]
|
||||
|
||||
assert {:ok, queued_state} =
|
||||
Connection.handle_info(
|
||||
{:parrhesia, :event, subscription_ref, "sub-1", received_event},
|
||||
state
|
||||
)
|
||||
|
||||
assert queued_state.outbound_queue_size == 1
|
||||
assert_receive :drain_outbound_queue
|
||||
|
||||
assert {:push, [{:text, payload}], drained_state} =
|
||||
Connection.handle_info(:drain_outbound_queue, queued_state)
|
||||
|
||||
assert drained_state.outbound_queue_size == 0
|
||||
assert JSON.decode!(payload) == ["EVENT", "sub-1", received_event]
|
||||
end
|
||||
|
||||
test "fanout_event enqueues and drains matching events" do
|
||||
state = subscribed_connection_state([])
|
||||
event = live_event("event-1", 1)
|
||||
@@ -841,6 +875,26 @@ defmodule Parrhesia.Web.ConnectionTest do
|
||||
state
|
||||
end
|
||||
|
||||
defp ensure_stream_runtime_started do
|
||||
if is_nil(Process.whereis(Parrhesia.Subscriptions.Supervisor)) do
|
||||
start_supervised!({Parrhesia.Subscriptions.Supervisor, []})
|
||||
end
|
||||
|
||||
if is_nil(Process.whereis(Parrhesia.Subscriptions.Index)) do
|
||||
start_supervised!({Parrhesia.Subscriptions.Index, name: Parrhesia.Subscriptions.Index})
|
||||
end
|
||||
|
||||
if is_nil(Process.whereis(Parrhesia.API.Stream.Registry)) do
|
||||
start_supervised!({Registry, keys: :unique, name: Parrhesia.API.Stream.Registry})
|
||||
end
|
||||
|
||||
if is_nil(Process.whereis(Parrhesia.API.Stream.Supervisor)) do
|
||||
start_supervised!(
|
||||
{DynamicSupervisor, strategy: :one_for_one, name: Parrhesia.API.Stream.Supervisor}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
defp listener(overrides) do
|
||||
base = %{
|
||||
id: :test,
|
||||
|
||||
@@ -5,6 +5,7 @@ defmodule Parrhesia.Web.RouterTest do
|
||||
import Plug.Test
|
||||
|
||||
alias Ecto.Adapters.SQL.Sandbox
|
||||
alias Parrhesia.API.Sync
|
||||
alias Parrhesia.Protocol.EventValidator
|
||||
alias Parrhesia.Repo
|
||||
alias Parrhesia.Web.Listener
|
||||
@@ -334,6 +335,84 @@ defmodule Parrhesia.Web.RouterTest do
|
||||
assert byte_size(pubkey) == 64
|
||||
end
|
||||
|
||||
test "POST /management stats and health include sync summary" do
|
||||
management_url = "http://www.example.com/management"
|
||||
auth_event = nip98_event("POST", management_url)
|
||||
authorization = "Nostr " <> Base.encode64(JSON.encode!(auth_event))
|
||||
initial_total = Sync.sync_stats() |> elem(1) |> Map.fetch!("servers_total")
|
||||
server_id = "router-sync-#{System.unique_integer([:positive, :monotonic])}"
|
||||
|
||||
assert {:ok, _server} =
|
||||
Sync.put_server(%{
|
||||
"id" => server_id,
|
||||
"url" => "wss://relay-a.example/relay",
|
||||
"enabled?" => false,
|
||||
"auth_pubkey" => String.duplicate("a", 64),
|
||||
"filters" => [%{"kinds" => [5000], "#r" => ["tribes.accounts.user"]}],
|
||||
"tls" => %{
|
||||
"pins" => [
|
||||
%{
|
||||
"type" => "spki_sha256",
|
||||
"value" => "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
on_exit(fn ->
|
||||
_ = Sync.remove_server(server_id)
|
||||
end)
|
||||
|
||||
stats_conn =
|
||||
conn(
|
||||
:post,
|
||||
"/management",
|
||||
JSON.encode!(%{
|
||||
"method" => "stats",
|
||||
"params" => %{}
|
||||
})
|
||||
)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put_req_header("authorization", authorization)
|
||||
|> Router.call([])
|
||||
|
||||
assert stats_conn.status == 200
|
||||
|
||||
assert %{
|
||||
"ok" => true,
|
||||
"result" => %{
|
||||
"sync" => %{"servers_total" => servers_total}
|
||||
}
|
||||
} = JSON.decode!(stats_conn.resp_body)
|
||||
|
||||
assert servers_total == initial_total + 1
|
||||
|
||||
health_conn =
|
||||
conn(
|
||||
:post,
|
||||
"/management",
|
||||
JSON.encode!(%{
|
||||
"method" => "health",
|
||||
"params" => %{}
|
||||
})
|
||||
)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put_req_header("authorization", authorization)
|
||||
|> Router.call([])
|
||||
|
||||
assert health_conn.status == 200
|
||||
|
||||
assert %{
|
||||
"ok" => true,
|
||||
"result" => %{
|
||||
"status" => status,
|
||||
"sync" => %{"servers_total" => ^servers_total}
|
||||
}
|
||||
} = JSON.decode!(health_conn.resp_body)
|
||||
|
||||
assert status in ["ok", "degraded"]
|
||||
end
|
||||
|
||||
test "POST /management returns not found when admin feature is disabled on the listener" do
|
||||
conn =
|
||||
conn(:post, "/management", JSON.encode!(%{"method" => "ping", "params" => %{}}))
|
||||
|
||||
Reference in New Issue
Block a user