Skip to main content

lib/dust/supervisor.ex

defmodule Dust.Supervisor do
  use Supervisor

  def start_link(opts) do
    name = Keyword.get(opts, :name, __MODULE__)
    Supervisor.start_link(__MODULE__, opts, name: name)
  end

  @impl true
  def init(opts) do
    stores = Keyword.fetch!(opts, :stores)
    testing = Keyword.get(opts, :testing)

    cache =
      if testing == :manual do
        Keyword.get(opts, :cache, {Dust.Cache.Memory, []})
      else
        Keyword.fetch!(opts, :cache)
      end

    url = Keyword.get(opts, :url, "ws://localhost:7755/ws/sync")
    token = Keyword.get(opts, :token, System.get_env("DUST_API_KEY"))
    device_id = Keyword.get(opts, :device_id)

    activity_name = Keyword.get(opts, :activity_buffer_name, Dust.ActivityBuffer)

    activity_children = [
      {Dust.ActivityBuffer, name: activity_name}
    ]

    engine_children =
      Enum.map(stores, fn store ->
        {Dust.SyncEngine,
         store: store, cache: cache, activity_buffer: activity_name, url: url, token: token}
      end)

    connection_children =
      if testing == :manual do
        []
      else
        connection_opts =
          [
            url: url,
            token: token,
            device_id: device_id,
            stores: stores,
            name: Dust.Connection
          ]
          |> Enum.reject(fn {_k, v} -> is_nil(v) end)

        [{Dust.Connection, connection_opts}]
      end

    registry_children =
      for {name, spec} <- [
            {Dust.SyncEngineRegistry, {Registry, keys: :unique, name: Dust.SyncEngineRegistry}},
            {Dust.ConnectionRegistry, {Registry, keys: :unique, name: Dust.ConnectionRegistry}}
          ],
          !Process.whereis(name),
          do: spec

    subscribers = Keyword.get(opts, :subscribers, [])
    pubsub = Keyword.get(opts, :pubsub)

    registrar_opts =
      [subscribers: subscribers, pubsub: pubsub, stores: stores]
      |> Enum.reject(fn {_k, v} -> is_nil(v) end)

    subscriber_children =
      if subscribers == [] and is_nil(pubsub) do
        []
      else
        [{Dust.SubscriberRegistrar, registrar_opts}]
      end

    children =
      registry_children ++
        activity_children ++
        engine_children ++
        connection_children ++
        subscriber_children

    Supervisor.init(children, strategy: :one_for_one)
  end
end