I don’t know if you can write a sample on how PubSub can be achieved.
I’m not sure if that’s what you need, but have you checked Registry
module in elixir? It has a note about how to use it as a local pub/sub system in the docs [0].
You can put it in a separate app
under an umbrella and let processes from other apps subscribe to certain topics in it.
apps/pubsub/lib/pubsub.ex
defmodule Test.PubSub do
def start_link do
Registry.start_link(:duplicate, __MODULE__)
end
def subscribe(topic) do
Registry.register(__MODULE__, topic, [])
end
def unsubscribe(topic) do
Registry.unregister(__MODULE__, topic)
end
def publish(topic, message) do
Registry.dispatch(__MODULE__, topic, fn entries ->
for {pid, _value} <- entries, do: send(pid, message)
end)
end
end
apps/pubsub/lib/pubsub/application.ex
defmodule Test.PubSub.Application do
@moduledoc false
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
supervisor(Test.PubSub, [])
]
opts = [strategy: :one_for_one, name: Test.PubSub.Supervisor]
Supervisor.start_link(children, opts)
end
end
To subscribe for updates in user
app in a phoenix channel you would do something like
defmodule Test.Web.UserChannel do
use Test.Web, :channel
def join("user:" <> name = topic, _params, socket) do
{:ok, _owner_pid} = Test.PubSub.subscribe(topic) # subscribe to updates in "user:#{name}"
{:ok, socket}
end
# and handle these updates
def handle_info(:sacked, socket) do
broadcast! socket, "sacked", %{}
{:noreply, socket}
end
end
Somewhere in the user
app you would publish the message :sacked
in case of a ban
...
Test.PubSub.publish("user:idiot", :sacked)
...
These are basically the examples from the Registry
docs, and there are some more about other possible uses for it.
Note however that this pub/sub implementation is local. And if you are using phoenix, you might want to pick Phoenix.PubSub
[1] instead which is not local, so that for the example above (with channels) you would probably use phoenix’s pub/sub library.
[0] https://hexdocs.pm/elixir/master/Registry.html#module-using-as-a-pubsub
[1] Phoenix.PubSub — Phoenix.PubSub v2.1.3