mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-11 02:05:58 +00:00
159 lines
3.3 KiB
Elixir
159 lines
3.3 KiB
Elixir
defmodule WandererApp.Server.ServerStatusTracker do
|
|
@moduledoc false
|
|
use GenServer
|
|
|
|
require Logger
|
|
|
|
@name :server_status_tracker
|
|
|
|
defstruct [
|
|
:players,
|
|
:server_version,
|
|
:start_time,
|
|
:vip,
|
|
:retries
|
|
]
|
|
|
|
@retries_count 3
|
|
|
|
@initial_state %{
|
|
players: 0,
|
|
retries: @retries_count,
|
|
server_version: "0",
|
|
start_time: "0",
|
|
vip: true
|
|
}
|
|
|
|
@refresh_interval :timer.minutes(1)
|
|
|
|
@logger Application.compile_env(:wanderer_app, :logger)
|
|
|
|
def start_link(opts \\ []), do: GenServer.start(__MODULE__, opts, name: @name)
|
|
|
|
@impl true
|
|
def init(_opts) do
|
|
@logger.info("#{__MODULE__} started")
|
|
|
|
{:ok, @initial_state, {:continue, :start}}
|
|
end
|
|
|
|
@impl true
|
|
def terminate(_reason, _state), do: :ok
|
|
|
|
@impl true
|
|
def handle_call(:stop, _, state), do: {:stop, :normal, :ok, state}
|
|
|
|
@impl true
|
|
def handle_call(:error, _, state), do: {:stop, :error, :ok, state}
|
|
|
|
@impl true
|
|
def handle_continue(:start, state) do
|
|
Process.send_after(self(), :refresh_status, 100)
|
|
|
|
{:noreply, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(
|
|
:refresh_status,
|
|
%{
|
|
retries: retries
|
|
} = state
|
|
) do
|
|
Process.send_after(self(), :refresh_status, @refresh_interval)
|
|
Task.async(fn -> get_server_status(retries) end)
|
|
|
|
{:noreply, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(
|
|
{ref, result},
|
|
%{
|
|
retries: retries
|
|
} = state
|
|
) do
|
|
Process.demonitor(ref, [:flush])
|
|
|
|
case result do
|
|
{:status, status} ->
|
|
Phoenix.PubSub.broadcast(
|
|
WandererApp.PubSub,
|
|
"server_status",
|
|
{:server_status, status}
|
|
)
|
|
|
|
{:noreply, state |> Map.merge(status)}
|
|
|
|
:retry ->
|
|
{:noreply, %{state | retries: retries - 1}}
|
|
|
|
{:error, _error} ->
|
|
{:noreply, state}
|
|
|
|
_ ->
|
|
{:noreply, state}
|
|
end
|
|
end
|
|
|
|
def handle_info(_action, state),
|
|
do: {:noreply, state}
|
|
|
|
defp get_server_status(retries) do
|
|
case WandererApp.Esi.get_server_status() do
|
|
{:ok, result} ->
|
|
{:status, _get_status(result)}
|
|
|
|
{:error, :timeout} ->
|
|
if retries > 0 do
|
|
:retry
|
|
else
|
|
Logger.warning("#{__MODULE__} failed to refresh server status: :timeout")
|
|
{:status, @initial_state}
|
|
end
|
|
|
|
{:error, error} ->
|
|
if retries > 0 do
|
|
:retry
|
|
else
|
|
Logger.warning("#{__MODULE__} failed to refresh server status: #{inspect(error)}")
|
|
{:status, @initial_state}
|
|
end
|
|
|
|
_ ->
|
|
{:error, :unknown}
|
|
end
|
|
end
|
|
|
|
defp _get_status(%{
|
|
"players" => 0,
|
|
"server_version" => server_version,
|
|
"start_time" => start_time,
|
|
"vip" => _vip
|
|
}) do
|
|
%{players: 0, server_version: server_version, start_time: start_time, vip: true}
|
|
end
|
|
|
|
defp _get_status(%{
|
|
"players" => players,
|
|
"server_version" => server_version,
|
|
"start_time" => start_time,
|
|
"vip" => vip
|
|
}) do
|
|
%{players: players, server_version: server_version, start_time: start_time, vip: vip}
|
|
end
|
|
|
|
defp _get_status(%{
|
|
"players" => players,
|
|
"server_version" => server_version,
|
|
"start_time" => start_time
|
|
}) do
|
|
%{
|
|
players: players,
|
|
server_version: server_version,
|
|
start_time: start_time,
|
|
vip: false
|
|
}
|
|
end
|
|
end
|