lib/runbox/runtime/stage/selector_builder.ex

defmodule Runbox.Runtime.Stage.SelectorBuilder do
  @moduledoc """
  Selector function generator which is used to filter messages between GenStage phases.

  Stage based runtime uses BroadcastDispatcher to dispatch messages between TemplateCarriers,
  this kind of dispatcher support message selector function to be passed as part of GenStage
  subscription. This module is used to generate this function based on template configuration.
  """

  alias Toolbox.Message, as: M
  alias Toolbox.Scenario.OutputAction, as: OA

  @doc """
  Builds GenStages BroadcastDispatcher filter function based on template configuration.

  Filter function is produced based on `c:Toolbox.Scenario.Template.StageBased.subscriptions/0`
  callback result.

  Subscription is defined as {message_type, _routing_rule}, we use only message_type part
  of subscription. All message types are stored in produced function clojure and dispatched
  message type is matched against them.

  Exception to the message type matching are output actions and tick messages which are
  always matched.
  """
  @spec build([{String.t() | atom, term}]) :: (OA.t() | M.t() -> boolean())
  def build(config) do
    # parse subscription, take only message type
    msg_types = Enum.map(config, fn {msg_type, _} -> msg_type end)

    fn
      %OA{} ->
        # always propagate output actions
        true

      %M{type: "tick"} ->
        # always propagate tick messages
        true

      %M{type: type} ->
        # other message types propagate only if template is subscribed to them
        Enum.member?(msg_types, type)
    end
  end
end