I think so. I mean if A depends on B, but B can call A’s code, then B also depends on A and you’ve got a circular dependency whether you’ve written it down in mix.exs
or not.
Phoenix.PubSub is both a bit heavy weight, and also I think the wrong paradigm. What you need are event handlers, which can happen with basically just pure data, the process based subscription model of Phoenix.PubSub doesn’t make sense here. Simple version basically just does the following.
Have A configure b with an event handler module found in A:
# in app A's config
config :b, event_handlers: [SomeModuleInA]
Then in B, instead of calling A’s code, grab event handlers and call a function:
for handler <- Application.get_env(:b, :event_handlers) do
handler.dispatch(:foo_created, some_data)
end
We’ve done this in our umbrella apps and it’s worked pretty nicely. It avoids a circular dependency, while still avoiding a “broadcast to the winds and who knows who responds” kind of situation, since it’s pretty easy to keep track of the handlers list.