Packages

A distributed service registry built on top of phoenix_pubsub. Requests are dispatched to one or more services based on hashed keys.

Current section

Files

Jump to
dispatch test dispatch registry_test.exs
Raw

test/dispatch/registry_test.exs

defmodule Dispatch.RegistryTest do
use ExUnit.Case, async: false
alias Dispatch.{Registry, Helper}
setup do
type = "RegistryTest"
pubsub_server = Application.get_env(:dispatch, :pubsub)
|> Keyword.get(:name, Dispatch.PubSub)
Phoenix.PubSub.subscribe(pubsub_server, type)
{:ok, _registry_pid} = Helper.setup_registry()
on_exit fn ->
Helper.clear_type(type)
end
{:ok, %{service_type: type}}
end
test "empty registry returns empty service list", %{service_type: type} do
assert [] == Registry.get_services(type)
end
test "empty registry returns empty service list with a different type", %{service_type: type} do
Registry.add_service("Other", self())
assert [] == Registry.get_services(type)
Helper.clear_type("Other")
end
test "enable service adds to registry", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}
[{pid, %{node: node, state: state}}] = Registry.get_services(type)
assert pid == this_pid
assert node == this_node
assert state == :online
end
test "enable service allows multiple different types", %{} do
{:ok, service_1} = Agent.start(fn -> 1 end)
{:ok, service_2} = Agent.start(fn -> 2 end)
Registry.add_service("Type1", service_1)
Registry.add_service("Type2", service_2)
this_node = node()
assert {:ok, ^this_node, ^service_1} = Registry.find_service("Type1", "my_key")
assert {:ok, ^this_node, ^service_2} = Registry.find_service("Type2", "my_key")
end
test "remove service removes it from registry", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert {:ok, this_node, this_pid} == Registry.find_service(type, "key")
Registry.remove_service(type, self())
assert_receive {:leave, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert [] == Registry.get_services(type)
assert {:error, :no_service_for_key} == Registry.find_service(type, "key")
end
test "disable service", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert {:ok, this_node, this_pid} == Registry.find_service(type, "key")
Registry.disable_service(type, self())
assert_receive {:leave, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :offline}}, 1_000
[{pid, %{node: node, state: state}}] = Registry.get_services(type)
assert pid == self
assert node == node()
assert state == :offline
assert {:error, :no_service_for_key} == Registry.find_service(type, "key")
Registry.enable_service(type, self())
assert_receive {:leave, ^this_pid, %{node: ^this_node, state: :offline}}, 1_000
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert {:ok, this_node, this_pid} == Registry.find_service(type, "key")
end
test "enable multiple services", %{service_type: type} do
Registry.add_service(type, self())
other_pid = spawn(fn -> :timer.sleep(30_000) end)
Registry.add_service(type, other_pid)
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert_receive {:join, ^other_pid, %{node: ^this_node, state: :online}}, 1_000
[{first_pid, %{node: ^this_node}}, {second_pid, %{node: ^this_node}}] = Registry.get_services(type)
assert {first_pid, second_pid} == {this_pid, other_pid} or {second_pid, first_pid} == {this_pid, other_pid}
end
test "get online services", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
[{pid, %{node: node, state: state}}] = Registry.get_online_services(type)
assert pid == self
assert node == node()
assert state == :online
Registry.disable_service(type, self())
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :offline}}, 1_000
assert [] == Registry.get_online_services(type)
end
test "get error if no services joined", %{service_type: type} do
assert {:error, :no_service_for_key} == Registry.find_service(type, "my_key")
end
test "get service pid", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert {:ok, this_node, this_pid} == Registry.find_service(type, "my_key")
end
test "get service pid from term key", %{service_type: type} do
Registry.add_service(type, self())
{this_pid, this_node} = {self(), node()}
assert_receive {:join, ^this_pid, %{node: ^this_node, state: :online}}, 1_000
assert {:ok, this_node, this_pid} == Registry.find_service(type, {:abc, 1})
end
end