mirror of
https://github.com/wanderer-industries/wanderer
synced 2026-05-01 15:00:31 +00:00
92 lines
2.2 KiB
Elixir
92 lines
2.2 KiB
Elixir
defmodule WandererApp.Character.TrackerPoolDynamicSupervisor do
|
|
@moduledoc false
|
|
use DynamicSupervisor
|
|
|
|
require Logger
|
|
|
|
@cache :tracked_characters
|
|
@registry :tracker_pool_registry
|
|
@unique_registry :unique_tracker_pool_registry
|
|
@tracker_pool_limit 50
|
|
|
|
@name __MODULE__
|
|
|
|
def start_link(_arg) do
|
|
DynamicSupervisor.start_link(@name, [], name: @name, max_restarts: 10)
|
|
end
|
|
|
|
def init(_arg) do
|
|
DynamicSupervisor.init(strategy: :one_for_one)
|
|
end
|
|
|
|
def start_tracking(tracked_id) do
|
|
case Registry.lookup(@registry, WandererApp.Character.TrackerPool) do
|
|
[] ->
|
|
start_child([tracked_id], 0)
|
|
|
|
pools ->
|
|
case get_available_pool(pools) do
|
|
nil ->
|
|
start_child([tracked_id], pools |> Enum.count())
|
|
|
|
pid ->
|
|
GenServer.cast(pid, {:add_tracked_id, tracked_id})
|
|
end
|
|
end
|
|
end
|
|
|
|
def stop_tracking(tracked_id) do
|
|
{:ok, uuid} = Cachex.get(@cache, tracked_id)
|
|
|
|
case Registry.lookup(
|
|
@unique_registry,
|
|
Module.concat(WandererApp.Character.TrackerPool, uuid)
|
|
) do
|
|
[] ->
|
|
:ok
|
|
|
|
[{pool_pid, _}] ->
|
|
GenServer.cast(pool_pid, {:remove_tracked_id, tracked_id})
|
|
end
|
|
end
|
|
|
|
defp get_available_pool([]), do: nil
|
|
|
|
defp get_available_pool([{_pid, uuid} | pools]) do
|
|
case Registry.lookup(@unique_registry, Module.concat(WandererApp.Character.TrackerPool, uuid)) do
|
|
[] ->
|
|
nil
|
|
|
|
uuid_pools ->
|
|
case get_available_pool_pid(uuid_pools) do
|
|
nil ->
|
|
get_available_pool(pools)
|
|
|
|
pool_pid ->
|
|
pool_pid
|
|
end
|
|
end
|
|
end
|
|
|
|
defp get_available_pool_pid([]), do: nil
|
|
|
|
defp get_available_pool_pid([{pid, tracked_ids} | pools]) do
|
|
if Enum.count(tracked_ids) < @tracker_pool_limit do
|
|
pid
|
|
else
|
|
get_available_pool_pid(pools)
|
|
end
|
|
end
|
|
|
|
defp start_child(tracked_ids, pools_count) do
|
|
case DynamicSupervisor.start_child(@name, {WandererApp.Character.TrackerPool, tracked_ids}) do
|
|
{:ok, pid} ->
|
|
Logger.info("Starting tracking pool, total pools: #{pools_count + 1}")
|
|
{:ok, pid}
|
|
|
|
{:error, {:already_started, pid}} ->
|
|
{:ok, pid}
|
|
end
|
|
end
|
|
end
|