lib/roles/subscriber.ex

defmodule Wampex.Roles.Subscriber do
  @moduledoc """
  Handles requests and responses for Subscribers
  """

  alias Wampex.Role
  alias Wampex.Roles.Broker.Event
  @behaviour Role

  @subscribe 32
  @subscribed 33
  @unsubscribe 34
  @unsubscribed 35
  @event 36

  defmodule Subscribe do
    @moduledoc false
    @enforce_keys [:topic]
    defstruct [:request_id, :topic, options: %{}]

    @type t :: %__MODULE__{
            request_id: integer() | nil,
            topic: binary(),
            options: map()
          }
  end

  defmodule Unsubscribe do
    @moduledoc false
    @enforce_keys [:subscription_id]
    defstruct [:request_id, :subscription_id]

    @type t :: %__MODULE__{
            request_id: integer() | nil,
            subscription_id: integer()
          }
  end

  @impl true
  def add(roles) do
    Map.put(roles, :subscriber, %{})
  end

  @spec subscribe(Subscribe.t()) :: Wampex.message()
  def subscribe(%Subscribe{topic: t, options: opts}) do
    [@subscribe, opts, t]
  end

  @spec unsubscribe(Unsubscribe.t()) :: Wampex.message()
  def unsubscribe(%Unsubscribe{subscription_id: si}) do
    [@unsubscribe, si]
  end

  @impl true
  def handle([@subscribed, request_id, id]) do
    {[{:next_event, :internal, :established}], request_id, {:ok, id}}
  end

  @impl true
  def handle(<<@unsubscribed, request_id>>) do
    handle([@unsubscribed, request_id])
  end

  @impl true
  def handle([@unsubscribed, request_id]) do
    {[{:next_event, :internal, :established}], request_id, :ok}
  end

  @impl true
  def handle([@event, sub_id, pub_id, dets]) do
    handle([@event, sub_id, pub_id, dets, [], %{}])
  end

  @impl true
  def handle([@event, sub_id, pub_id, dets, arg_l]) do
    handle([@event, sub_id, pub_id, dets, arg_l, %{}])
  end

  @impl true
  def handle([@event, sub_id, pub_id, dets, arg_l, arg_kw]) do
    {[{:next_event, :internal, :event}], nil,
     {:update, :event,
      %Event{
        subscription_id: sub_id,
        publication_id: pub_id,
        details: dets,
        arg_list: arg_l,
        arg_kw: arg_kw
      }}}
  end
end