Current section

Files

Jump to
gen_spoxy lib prerender gen_prerender.ex
Raw

lib/prerender/gen_prerender.ex

defmodule GenSpoxy.Prerender do
@moduledoc """
a behaviour for defining prerender
"""
defmacro __using__(_opts) do
quote do
use GenSpoxy.Partitionable
alias Spoxy.Prerender.Server
@behaviour Spoxy.Prerender.Behaviour
@default_timeout GenSpoxy.Constants.prerender_timeout()
@total_partitions GenSpoxy.Constants.total_partitions(:gen_prerender)
def start_link(opts) do
Server.start_link(opts)
end
def perform(req, opts \\ []) do
server = lookup_server_name(req)
req_key = calc_req_key(req)
Server.perform(server, __MODULE__, req, req_key, @default_timeout)
end
def sample_task_interval do
Server.sample_task_interval()
end
@impl true
def calc_req_partition(req_key) do
1 + :erlang.phash2(req_key, total_partitions())
end
@doc """
used for testing
"""
def get_req_state(req) do
partition = req_partition(req)
get_partition_state(partition)
end
@impl true
def total_partitions do
@total_partitions
end
@doc """
used for testing
"""
def get_partition_state(partition) do
server = partition_server(partition)
Server.get_partition_state(server)
end
def req_partition(req) do
req_key = calc_req_key(req)
calc_req_partition(req_key)
end
def inspect_all_partitions do
initial_state = %{total_listeners: 0, total_passive: 0}
Enum.reduce(1..@total_partitions, initial_state, fn partition, acc ->
partition_data = inspect_partition(partition)
{:ok, listeners} = Map.fetch(partition_data, :total_listeners)
{:ok, passive} = Map.fetch(partition_data, :total_passive)
{:ok, total_listeners} = Map.fetch(acc, :total_listeners)
{:ok, total_passive} = Map.fetch(acc, :total_passive)
new_total_listeners = total_listeners + listeners
new_total_passive = total_passive + passive
acc
|> Map.put(:total_listeners, new_total_listeners)
|> Map.put(:total_passive, new_total_passive)
end)
end
@doc """
returns for `partition` the total number of listeners across all the partition requests
and how many of them are passive listeners
"""
def inspect_partition(partition) do
%{reqs_state: reqs_state} = get_partition_state(partition)
initial_state = %{total_listeners: 0, total_passive: 0}
Enum.reduce(reqs_state, initial_state, fn {_req_key, req_state}, acc ->
{:ok, total_listeners} = Map.fetch(acc, :total_listeners)
{:ok, total_passive} = Map.fetch(acc, :total_passive)
%{listeners: listeners} = req_state
passive = for {:passive, listener} <- listeners, do: listener
new_total_listeners = total_listeners + Enum.count(listeners)
new_total_passive = total_passive + Enum.count(passive)
acc
|> Map.put(:total_listeners, new_total_listeners)
|> Map.put(:total_passive, new_total_passive)
end)
end
defp lookup_server_name(req) do
partition = req_partition(req)
partition_server(partition)
end
prerender_module = __MODULE__
prerender_sup_module = String.to_atom("#{prerender_module}.Supervisor")
defmodule prerender_sup_module do
use GenSpoxy.Prerender.Supervisor, supervised_module: prerender_module
end
end
end
end