open-pod/lib/openpod/boundary/archive_server.ex

94 lines
2.6 KiB
Elixir

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