Extract API events and stream layers
This commit is contained in:
81
test/parrhesia/api/events_test.exs
Normal file
81
test/parrhesia/api/events_test.exs
Normal file
@@ -0,0 +1,81 @@
|
||||
defmodule Parrhesia.API.EventsTest do
|
||||
use ExUnit.Case, async: false
|
||||
|
||||
alias Ecto.Adapters.SQL.Sandbox
|
||||
alias Parrhesia.API.Events
|
||||
alias Parrhesia.API.RequestContext
|
||||
alias Parrhesia.Protocol.EventValidator
|
||||
alias Parrhesia.Repo
|
||||
|
||||
setup do
|
||||
:ok = Sandbox.checkout(Repo)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "publish stores valid events through the shared API" do
|
||||
event = valid_event()
|
||||
|
||||
assert {:ok, result} = Events.publish(event, context: %RequestContext{})
|
||||
assert result.accepted
|
||||
assert result.event_id == event["id"]
|
||||
assert result.message == "ok: event stored"
|
||||
assert result.reason == nil
|
||||
|
||||
assert {:ok, stored_event} = Parrhesia.Storage.events().get_event(%{}, event["id"])
|
||||
assert stored_event["id"] == event["id"]
|
||||
end
|
||||
|
||||
test "publish returns duplicate results without raising transport errors" do
|
||||
event = valid_event()
|
||||
|
||||
assert {:ok, first_result} = Events.publish(event, context: %RequestContext{})
|
||||
assert first_result.accepted
|
||||
|
||||
assert {:ok, second_result} = Events.publish(event, context: %RequestContext{})
|
||||
refute second_result.accepted
|
||||
assert second_result.reason == :duplicate_event
|
||||
assert second_result.message == "duplicate: event already stored"
|
||||
end
|
||||
|
||||
test "query and count preserve read semantics through the shared API" do
|
||||
now = System.system_time(:second)
|
||||
first = valid_event(%{"content" => "first", "created_at" => now})
|
||||
second = valid_event(%{"content" => "second", "created_at" => now + 1})
|
||||
|
||||
assert {:ok, %{accepted: true}} = Events.publish(first, context: %RequestContext{})
|
||||
assert {:ok, %{accepted: true}} = Events.publish(second, context: %RequestContext{})
|
||||
|
||||
assert {:ok, events} =
|
||||
Events.query([%{"kinds" => [1]}], context: %RequestContext{})
|
||||
|
||||
assert Enum.map(events, & &1["id"]) == [second["id"], first["id"]]
|
||||
|
||||
assert {:ok, 2} =
|
||||
Events.count([%{"kinds" => [1]}], context: %RequestContext{})
|
||||
|
||||
assert {:ok, %{"count" => 2, "approximate" => false}} =
|
||||
Events.count([%{"kinds" => [1]}],
|
||||
context: %RequestContext{},
|
||||
options: %{}
|
||||
)
|
||||
end
|
||||
|
||||
defp valid_event(overrides \\ %{}) do
|
||||
base_event = %{
|
||||
"pubkey" => String.duplicate("1", 64),
|
||||
"created_at" => System.system_time(:second),
|
||||
"kind" => 1,
|
||||
"tags" => [],
|
||||
"content" => "hello",
|
||||
"sig" => String.duplicate("3", 128)
|
||||
}
|
||||
|
||||
base_event
|
||||
|> Map.merge(overrides)
|
||||
|> recalculate_event_id()
|
||||
end
|
||||
|
||||
defp recalculate_event_id(event) do
|
||||
Map.put(event, "id", EventValidator.compute_id(event))
|
||||
end
|
||||
end
|
||||
80
test/parrhesia/api/stream_test.exs
Normal file
80
test/parrhesia/api/stream_test.exs
Normal file
@@ -0,0 +1,80 @@
|
||||
defmodule Parrhesia.API.StreamTest do
|
||||
use ExUnit.Case, async: false
|
||||
|
||||
alias Ecto.Adapters.SQL.Sandbox
|
||||
alias Parrhesia.API.Events
|
||||
alias Parrhesia.API.RequestContext
|
||||
alias Parrhesia.API.Stream
|
||||
alias Parrhesia.Protocol.EventValidator
|
||||
alias Parrhesia.Repo
|
||||
|
||||
setup do
|
||||
:ok = Sandbox.checkout(Repo)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "subscribe streams catch-up events followed by eose" do
|
||||
event = valid_event()
|
||||
context = %RequestContext{}
|
||||
|
||||
assert {:ok, %{accepted: true}} = Events.publish(event, context: context)
|
||||
assert {:ok, ref} = Stream.subscribe(self(), "sub-1", [%{"kinds" => [1]}], context: context)
|
||||
|
||||
assert_receive {:parrhesia, :event, ^ref, "sub-1", received_event}
|
||||
assert received_event["id"] == event["id"]
|
||||
assert_receive {:parrhesia, :eose, ^ref, "sub-1"}
|
||||
assert :ok = Stream.unsubscribe(ref)
|
||||
end
|
||||
|
||||
test "subscribe receives live fanout events after eose" do
|
||||
context = %RequestContext{}
|
||||
event = valid_event()
|
||||
|
||||
assert {:ok, ref} =
|
||||
Stream.subscribe(self(), "sub-live", [%{"kinds" => [1]}], context: context)
|
||||
|
||||
assert_receive {:parrhesia, :eose, ^ref, "sub-live"}, 1_000
|
||||
|
||||
assert {:ok, %{accepted: true}} = Events.publish(event, context: context)
|
||||
|
||||
assert_receive {:parrhesia, :event, ^ref, "sub-live", received_event}, 1_000
|
||||
assert received_event["id"] == event["id"]
|
||||
assert :ok = Stream.unsubscribe(ref)
|
||||
end
|
||||
|
||||
test "unsubscribe stops the subscription bridge" do
|
||||
context = %RequestContext{}
|
||||
|
||||
assert {:ok, ref} =
|
||||
Stream.subscribe(self(), "sub-stop", [%{"kinds" => [1]}], context: context)
|
||||
|
||||
assert_receive {:parrhesia, :eose, ^ref, "sub-stop"}
|
||||
|
||||
[{stream_pid, _value}] = Registry.lookup(Parrhesia.API.Stream.Registry, ref)
|
||||
_ = :sys.get_state(stream_pid)
|
||||
monitor_ref = Process.monitor(stream_pid)
|
||||
|
||||
assert :ok = Stream.unsubscribe(ref)
|
||||
assert_receive {:DOWN, ^monitor_ref, :process, ^stream_pid, reason}
|
||||
assert reason in [:normal, :noproc]
|
||||
end
|
||||
|
||||
defp valid_event(overrides \\ %{}) do
|
||||
base_event = %{
|
||||
"pubkey" => String.duplicate("1", 64),
|
||||
"created_at" => System.system_time(:second),
|
||||
"kind" => 1,
|
||||
"tags" => [],
|
||||
"content" => "hello",
|
||||
"sig" => String.duplicate("3", 128)
|
||||
}
|
||||
|
||||
base_event
|
||||
|> Map.merge(overrides)
|
||||
|> recalculate_event_id()
|
||||
end
|
||||
|
||||
defp recalculate_event_id(event) do
|
||||
Map.put(event, "id", EventValidator.compute_id(event))
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user