lib/runbox/runtime/component_network.ex

defmodule Runbox.Runtime.ComponentNetwork do
  @moduledoc group: :internal
  @moduledoc """
  Component network builds and validates run component dependency network.

  To build this network, module uses dependencies defined by the scenario.
  """
  alias Runbox.Scenario.Type
  alias Runbox.ScenarioTemplate

  @type t :: any()
  @type component :: any()

  @callback create([ScenarioTemplate.t()], Keyword.t()) :: {:ok, t} | {:error, term}
  @callback convert_to_network([ScenarioTemplate.t()]) :: t
  @callback input_topics(t) :: [String.t()]

  @doc """
  Main function. Given list of template modules,
  expands them into components network with input streams, timezips etc...

  ## Options

    * `:direct_ticking` - if true (default), creates network using direct ticking
  """
  @spec create(Type.t(), [ScenarioTemplate.t()], Keyword.t()) :: {:ok, t} | {:error, term}
  def create(scenario_type, scenario_templates, opts \\ []) do
    get_impl(scenario_type).create(scenario_templates, opts)
  end

  @doc """
  Creates base network with only template nodes
  """
  @spec convert_to_network(Type.t(), [ScenarioTemplate.t()]) :: t
  def convert_to_network(scenario_type, scenario_templates) do
    get_impl(scenario_type).convert_to_network(scenario_templates)
  end

  @doc """
  Return all input topic names that are being subscribed to in component network.
  """
  @spec input_topics(Type.t(), t) :: [String.t()]
  def input_topics(scenario_type, component_network) do
    get_impl(scenario_type).input_topics(component_network)
  end

  @stage Type.stage()
  @simple Type.simple()

  @spec topology_sort(Type.t(), t) :: [component]
  def topology_sort(@stage, network) do
    Runbox.Runtime.Stage.ComponentNetwork.topology_sort(network)
  end

  defp get_impl(@stage), do: Runbox.Runtime.Stage.ComponentNetwork
  defp get_impl(@simple), do: Runbox.Runtime.Simple.ComponentNetwork
end