lib/cachex/services/incubator.ex

defmodule Cachex.Services.Incubator do
  @moduledoc """
  Parent module for all warmer definitions for a cache.

  The Incubator will control the supervision tree for all warmers that
  are associated with a cache. This is very minimal supervision, with
  no linking back except via the `Supervisor` access functions.
  """
  import Cachex.Spec

  ##############
  # Public API #
  ##############

  @doc """
  Starts a new incubation service for a cache.

  This will start a Supervisor to hold all warmer processes as defined in
  the provided cache record. If no warmers are attached in the cache record,
  this will skip creation to avoid unnecessary processes running.
  """
  @spec start_link(Spec.cache()) :: Supervisor.on_start()
  def start_link(cache(warmers: [])),
    do: :ignore

  def start_link(cache(warmers: warmers) = cache) do
    warmers
    |> Enum.map(&spec(&1, cache))
    |> Supervisor.start_link(strategy: :one_for_one)
  end

  ###############
  # Private API #
  ###############

  # Generates a Supervisor specification for a hook.
  defp spec(warmer(module: module) = warmer, cache),
    do: %{
      id: module,
      start: {GenServer, :start_link, [module, {cache, warmer}]}
    }
end