PubSub registry fails to start or race condition when testing?
I'm having this very random issue (it only happens occasionally, let's say 40% of the time) where it looks like my tests fail because they can't publish to my Phoenix.PubSub. The errors are all similar to this one:
121) test run returns an error tuple when it fails to update an account (MyAppServer.Controllers.CreateOrUpdateAccountTest)
apps/my_app_server/test/my_app_server/controllers/create_or_update_account_test.exs:35
** (ArgumentError) unknown registry: MyAppServer.PubSub
code: {:ok, _account} = Controllers.CreateOrUpdateAccount.run(user)
stacktrace:
(elixir 1.11.4) lib/registry.ex:999: Registry.meta/2
(phoenix_pubsub 2.0.0) lib/phoenix/pubsub.ex:144: Phoenix.PubSub.broadcast/4
(my_app_server 0.0.1) lib/my_app_server/controllers/create_or_update_account.ex:35: MyAppServer.Controllers.CreateOrUpdateAccount.run/1
test/my_app_server/controllers/create_or_update_account_test.exs:38: (test)
the stack trace points to https://github.com/phoenixframework/phoenix_pubsub/blob/7893228b48752437dff20b269ffdf614e07388dc/lib/phoenix/pubsub.ex#L144 when it attempts to broadcast. I'm using a wrapper module around PubSub but it is quite simple and only calling the PubSub API.
I've also seen this issue https://github.com/phoenixframework/phoenix_pubsub/issues/144 where it looks like the author was having a similar problem. However, it seems like he fixed it by having the correct child order in his top-level supervisor.
My top-level supervisor children is the following:
children = [
{Phoenix.PubSub, name: MyAppServer.PubSub},
MyAppServerWeb.Presence,
MyAppServerWeb.Telemetry,
MyAppServerWeb.Endpoint,
{Oban, Application.get_env(:my_app_server, Oban)},
MyAppServer.Event.Bus.Handler.Logging,
{ DynamicSupervisor,
strategy: :one_for_one,
name: MyAppServer.SomeNamespace.Supervisor
},
{ Registry,
keys: :unique,
partitions: System.schedulers_online(),
name: MyAppServer.SomeNamespace.Registry
}
]
and by the docs of all applications I believe it is correct.
I cannot find a reason for this to be happening. It's completely random and sometimes I can execute my test suite many times and it will never happen. Sometimes it will happen occasionally and other times it will be more frequent.
My test_helper.exs also has nothing out of the ordinary:
ExUnit.start()
Faker.start()
Ecto.Adapters.SQL.Sandbox.mode(MyRepo, :manual)
this issue has never happened in the dev environment, however it has been plaguing my test environment for quite a while.
Any tips on how to solve this issue? Thanks!
EDIT 1: I've found that this issue is reproducible using the seed given at the end of the test suite. I'll try to start from here to understand the problem at hand.
EDIT 2: Adding Application.ensure_all_started(:my_app_server) to the setup_all callback of the test files belonging to the top-level supervisor children seems to have fixed this issue (at least for the seeds I knew could reproduce the problem). However, I'm still unaware of the root cause.
I recently upgraded the pubsub dependency in my project following the documentation, but I am getting this error whenever I run the server:
an exception was raised: ** (ArgumentError) unknown registry: Demo.PubSub (elixir 1.10.2) lib/registry.ex:1239: Registry.info!/1 (elixir 1.10.2) lib/registry.ex:920: Registry.register/3 (phoenix_pubsub 2.0.0) lib/phoenix/pubsub.ex:117: Phoenix.PubSub.subscribe/3 (phoenix 1.5.8) lib/phoenix/channel/server.ex:420: Phoenix.Channel.Server.init_join/3 (phoenix 1.5.8) lib/phoenix/channel/server.ex:378: Phoenix.Channel.Server.channel_join/4 (phoenix 1.5.8) lib/phoenix/channel/server.ex:298: Phoenix.Channel.Server.handle_info/2 (stdlib 3.7) gen_server.erl:637: :gen_server.try_dispatch/4 (stdlib 3.7) gen_server.erl:711: :gen_server.handle_msg/6
Here is my application.ex
def start(_type, _args) do
children = [
{Phoenix.PubSub, name: Demo.PubSub},
Demo.Repo,
DemoWeb.Endpoint,
{Demo.ExpireCodesJob, []},
{Demo.DistributeCodesJob, []},
{Oban, oban_config()},
worker(PlugAttack.Storage.Ets, [Demo.PlugAttack.Storage, [clean_period: 60_000]])
]
opts = [strategy: :one_for_one, name: Demo.Supervisor]
Supervisor.start_link(children, opts)
end
It happens occasionally not all the time as other users reported.
Hi there, I am facing similar issues, I had updated to version 2 and now I am confused, the code documentation establish this as a valid example - name as an atom {Phoenix.PubSub, name: :my_pubsub}, but the notes on the readme says {Phoenix.PubSub, name: MyApp.PubSub})
What's the correct one? my test suite is failing since multiple errors like ** (FunctionClauseError) no function clause matching in Phoenix.PubSub.broadcast/4 Any help is very appreciated :D
@sashaafm What does the test look like that is causing the issue? I know it's silly, but since you've confirmed pubsub is starting first in the supervision tree, is it possible there is a typo in the name MyAppServer.PubSub when you call broadcast? Also, if there is or isn't an alias present in that file, that's tripped me up in the past. But yeah, likely the devil is in the details, and seeing the actual test implementation (or place where you call broadcast) might help.