defmodule Openpod.Boundary.ArchiveServer do @moduledoc false use GenServer, restart: :temporary require Logger alias Openpod alias Openpod.Provider.Archive @registry :podcast_registry @archive_supervisor :archive_supervisor ########## ### API def start_link(identifier) do GenServer.start_link(__MODULE__, identifier, name: via(identifier)) end def cache_or_fetch(identifier) do case DynamicSupervisor.start_child(@archive_supervisor, {__MODULE__, identifier}) do {:ok, pid} -> {:ok, pid} {:error, {:already_started, pid}} -> {:ok, pid} error -> error end # %{id: Worker, start: { Worker, :start_link, [child_name]}, restart: :transient}) end def get_feed(identifier) do cache_or_fetch(identifier) GenServer.call(via(identifier), :get_feed) end def reload(pid) when is_pid(pid) do Logger.debug "starting reload..." GenServer.cast(pid, :reload) end def reload(identifier) do cache_or_fetch(identifier) GenServer.call(via(identifier), :reload) end def count(pid) when is_pid(pid) do GenServer.call(pid, :count) end def count(identifier) when is_binary(identifier) do GenServer.call(via(identifier), :count) end ########## ### SERVER def init(identifier) do {:ok, %{count: 1, identifier: identifier, feed_data: fetch_feed_data(identifier)}} end def handle_call(:get_feed, _from, feed = %{count: count, feed_data: feed_data}) do Logger.debug "retrieve cached feed data for #{feed[:identifier]}..." {:reply, feed_data, %{feed | count: count + 1}, Application.fetch_env!(:openpod, :cache_duration)} end def handle_call(:reload, _from, feed = %{count: count, identifier: identifier}) do Logger.debug "discard cached feed data for #{identifier}..." feed_data = fetch_feed_data(identifier) {:reply, feed_data, %{feed | count: count + 1, feed_data: feed_data}} end def handle_call(:count, _from, feed = %{identifier: identifier, count: count}) do {:reply, %{identifier: identifier, count: count}, feed} end def handle_cast(:reload, feed = %{identifier: identifier}) do Logger.debug "discard cached feed data for #{identifier}..." {:noreply, %{feed | feed_data: fetch_feed_data(identifier)}} end def handle_info(:timeout, %{identifier: identifier}) do Logger.debug "shutting down #{identifier}..." {:stop, :normal, []} end ########## ### PRIVATES defp fetch_feed_data(identifier) do Logger.debug "fetching archive metadata for #{identifier}..." Archive.Parser.by_identifier(identifier) end defp via(identifier) do {:via, Registry, {@registry, identifier}} end end