Skip to content

Instantly share code, notes, and snippets.

@alexdesousa

alexdesousa/pub_sub.ex

Last active Mar 26, 2020
Embed
What would you like to do?
Small pubsub implementation using pg2
defmodule PubSub do
@moduledoc """
This module defines the basic pub-sub functions.
"""
@typedoc """
Channel name.
"""
@type channel :: term()
@typedoc """
Message.
"""
@type message :: term()
@doc """
Subscribes to a `channel`.
"""
@spec subscribe(channel()) :: :ok | {:error, {:no_such_group, channel()}}
def subscribe(channel) do
pid = self()
case :pg2.get_members(channel) do
members when is_list(members) ->
if pid in members, do: :ok, else: :pg2.join(channel, pid)
{:error, {:no_such_group, ^channel}} ->
:pg2.create(channel)
:pg2.join(channel, pid)
end
end
@doc """
Unsubscribe from a `channel`.
"""
@spec unsubscribe(channel()) :: :ok
def unsubscribe(channel) do
pid = self()
case :pg2.get_members(channel) do
[^pid] ->
:pg2.leave(channel, pid)
:pg2.delete(channel)
members when is_list(members) ->
if pid in members, do: :pg2.leave(channel, pid), else: :ok
_ ->
:ok
end
end
@doc """
Publishes a `message` in a `channel`.
"""
@spec publish(channel(), message()) :: :ok
def publish(channel, message) do
case :pg2.get_members(channel) do
[_ | _] = members ->
for member <- members, do: send(member, message)
:ok
_ ->
:ok
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.