diff --git a/config/runtime.exs b/config/runtime.exs index 192b8930..17f02488 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -120,6 +120,8 @@ config :wanderer_app, corp_wallet_eve_id: System.get_env("WANDERER_CORP_WALLET_EVE_ID", "-1"), public_api_disabled: public_api_disabled, active_tracking_pool: System.get_env("WANDERER_ACTIVE_TRACKING_POOL", "default"), + tracking_pool_max_size: + System.get_env("WANDERER_TRACKING_POOL_MAX_SIZE", "300") |> String.to_integer(), character_tracking_pause_disabled: System.get_env("WANDERER_CHARACTER_TRACKING_PAUSE_DISABLED", "true") |> String.to_existing_atom(), diff --git a/lib/wanderer_app/character/tracker.ex b/lib/wanderer_app/character/tracker.ex index 1bc38458..fcb900e1 100644 --- a/lib/wanderer_app/character/tracker.ex +++ b/lib/wanderer_app/character/tracker.ex @@ -166,7 +166,7 @@ defmodule WandererApp.Character.Tracker do def update_online(%{track_online: true, character_id: character_id} = character_state) do case WandererApp.Character.get_character(character_id) do - {:ok, %{eve_id: eve_id, access_token: access_token}} + {:ok, %{eve_id: eve_id, access_token: access_token, tracking_pool: tracking_pool}} when not is_nil(access_token) -> (WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") || WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused")) @@ -233,7 +233,7 @@ defmodule WandererApp.Character.Tracker do {:error, :error_limited, headers} -> reset_timeout = get_reset_timeout(headers) - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") WandererApp.Cache.put( "character:#{character_id}:online_forbidden", @@ -287,15 +287,15 @@ defmodule WandererApp.Character.Tracker do defp get_reset_timeout(_headers, default_timeout), do: default_timeout def update_info(character_id) do - (WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") || - WandererApp.Cache.has_key?("character:#{character_id}:info_forbidden") || + (WandererApp.Cache.has_key?("character:#{character_id}:info_forbidden") || WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused")) |> case do true -> {:error, :skipped} false -> - {:ok, %{eve_id: eve_id}} = WandererApp.Character.get_character(character_id) + {:ok, %{eve_id: eve_id, tracking_pool: tracking_pool}} = + WandererApp.Character.get_character(character_id) case WandererApp.Esi.get_character_info(eve_id) do {:ok, _info} -> @@ -320,7 +320,7 @@ defmodule WandererApp.Character.Tracker do {:error, :error_limited, headers} -> reset_timeout = get_reset_timeout(headers) - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") WandererApp.Cache.put( "character:#{character_id}:info_forbidden", @@ -358,7 +358,8 @@ defmodule WandererApp.Character.Tracker do character_id |> WandererApp.Character.get_character() |> case do - {:ok, %{eve_id: eve_id, access_token: access_token}} when not is_nil(access_token) -> + {:ok, %{eve_id: eve_id, access_token: access_token, tracking_pool: tracking_pool}} + when not is_nil(access_token) -> (WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") || WandererApp.Cache.has_key?("character:#{character_id}:ship_forbidden") || WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused")) @@ -397,7 +398,7 @@ defmodule WandererApp.Character.Tracker do {:error, :error_limited, headers} -> reset_timeout = get_reset_timeout(headers) - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") WandererApp.Cache.put( "character:#{character_id}:ship_forbidden", @@ -462,7 +463,8 @@ defmodule WandererApp.Character.Tracker do %{track_location: true, is_online: true, character_id: character_id} = character_state ) do case WandererApp.Character.get_character(character_id) do - {:ok, %{eve_id: eve_id, access_token: access_token}} when not is_nil(access_token) -> + {:ok, %{eve_id: eve_id, access_token: access_token, tracking_pool: tracking_pool}} + when not is_nil(access_token) -> WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused") |> case do true -> @@ -494,7 +496,7 @@ defmodule WandererApp.Character.Tracker do {:error, :skipped} {:error, :error_limited, headers} -> - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") reset_timeout = get_reset_timeout(headers, @location_limit_ttl) @@ -550,7 +552,8 @@ defmodule WandererApp.Character.Tracker do character_id |> WandererApp.Character.get_character() |> case do - {:ok, %{eve_id: eve_id, access_token: access_token} = character} + {:ok, + %{eve_id: eve_id, access_token: access_token, tracking_pool: tracking_pool} = character} when not is_nil(access_token) -> character |> WandererApp.Character.can_track_wallet?() @@ -589,7 +592,7 @@ defmodule WandererApp.Character.Tracker do {:error, :error_limited, headers} -> reset_timeout = get_reset_timeout(headers) - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") WandererApp.Cache.put( "character:#{character_id}:wallet_forbidden", diff --git a/lib/wanderer_app/character/tracking_config_utils.ex b/lib/wanderer_app/character/tracking_config_utils.ex new file mode 100644 index 00000000..bb0e76f3 --- /dev/null +++ b/lib/wanderer_app/character/tracking_config_utils.ex @@ -0,0 +1,142 @@ +defmodule WandererApp.Character.TrackingConfigUtils do + use Nebulex.Caching + @moduledoc false + + @ttl :timer.minutes(5) + @last_active_character_minutes -1 * 60 * 24 * 7 + + @decorate cacheable( + cache: WandererApp.Cache, + key: "tracker-stats", + opts: [ttl: @ttl] + ) + def load_tracker_stats() do + {:ok, characters} = get_active_characters() + + admins_count = + characters |> Enum.filter(&WandererApp.Character.can_track_corp_wallet?/1) |> Enum.count() + + with_wallets_count = + characters + |> Enum.filter( + &(WandererApp.Character.can_track_wallet?(&1) and + not WandererApp.Character.can_track_corp_wallet?(&1)) + ) + |> Enum.count() + + default_count = + characters + |> Enum.filter( + &(is_nil(&1.tracking_pool) and not WandererApp.Character.can_track_wallet?(&1) and + not WandererApp.Character.can_track_corp_wallet?(&1)) + ) + |> Enum.count() + + result = [ + %{id: "admins", title: "Admins", value: admins_count}, + %{id: "wallet", title: "With Wallet", value: with_wallets_count}, + %{id: "default", title: "Default", value: default_count} + ] + + {:ok, pools_count} = + Cachex.get( + :esi_auth_cache, + "configs_total_count" + ) + + {:ok, pools} = get_pools_info(characters) + + {:ok, result ++ pools} + end + + def update_active_tracking_pool() do + {:ok, pools_count} = + Cachex.get( + :esi_auth_cache, + "configs_total_count" + ) + + active_pool = + if not is_nil(pools_count) && pools_count != 0 do + tracking_pool_max_size = WandererApp.Env.tracking_pool_max_size() + {:ok, characters} = get_active_characters() + {:ok, pools} = get_pools_info(characters) + + pool = + pools + |> Enum.find(fn pool -> + pool.value < tracking_pool_max_size + end) + + if not is_nil(pool) do + pool.id + else + "default" + end + else + "default" + end + + Cachex.put( + :esi_auth_cache, + "active_pool", + active_pool + ) + end + + def get_active_pool!() do + Cachex.get( + :esi_auth_cache, + "active_pool" + ) + |> case do + {:ok, active_pool} when not is_nil(active_pool) -> + active_pool + + _ -> + "default" + end + end + + defp get_active_characters() do + WandererApp.Api.Character.last_active(%{ + from: + DateTime.utc_now() + |> DateTime.add(@last_active_character_minutes, :minute) + }) + end + + @decorate cacheable( + cache: WandererApp.Cache, + key: "character-pools-info", + opts: [ttl: @ttl] + ) + defp get_pools_info(characters) do + {:ok, pools_count} = + Cachex.get( + :esi_auth_cache, + "configs_total_count" + ) + + if not is_nil(pools_count) && pools_count != 0 do + pools = + 1..pools_count + |> Enum.map(fn pool_id -> + pools_character_count = + characters + |> Enum.filter( + &(&1.tracking_pool == "#{pool_id}" and + not WandererApp.Character.can_track_wallet?(&1) and + not WandererApp.Character.can_track_corp_wallet?(&1)) + ) + |> Enum.count() + + %{id: "#{pool_id}", title: "Pool #{pool_id}", value: pools_character_count} + end) + + {:ok, pools} + else + {:ok, []} + end + end +end diff --git a/lib/wanderer_app/character/transactions_tracker_impl.ex b/lib/wanderer_app/character/transactions_tracker_impl.ex index 5e3f558f..877175dc 100644 --- a/lib/wanderer_app/character/transactions_tracker_impl.ex +++ b/lib/wanderer_app/character/transactions_tracker_impl.ex @@ -146,7 +146,12 @@ defmodule WandererApp.Character.TransactionsTracker.Impl do end defp get_wallet_journal( - %{id: character_id, corporation_id: corporation_id, access_token: access_token} = + %{ + id: character_id, + corporation_id: corporation_id, + access_token: access_token, + tracking_pool: tracking_pool + } = _character, division ) @@ -164,7 +169,7 @@ defmodule WandererApp.Character.TransactionsTracker.Impl do {:error, :forbidden} {:error, :error_limited, _headers} -> - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") {:error, :error_limited} {:error, error} -> @@ -176,7 +181,12 @@ defmodule WandererApp.Character.TransactionsTracker.Impl do defp get_wallet_journal(_character, _division), do: {:error, :skipped} defp update_corp_wallets( - %{id: character_id, corporation_id: corporation_id, access_token: access_token} = + %{ + id: character_id, + corporation_id: corporation_id, + access_token: access_token, + tracking_pool: tracking_pool + } = _character ) when not is_nil(access_token) do @@ -193,7 +203,7 @@ defmodule WandererApp.Character.TransactionsTracker.Impl do {:error, :forbidden} {:error, :error_limited, _headers} -> - Logger.warning(".") + Logger.warning("#{inspect(tracking_pool)} ..") {:error, :error_limited} {:error, error} -> diff --git a/lib/wanderer_app/env.ex b/lib/wanderer_app/env.ex index 90f297bb..d947e160 100644 --- a/lib/wanderer_app/env.ex +++ b/lib/wanderer_app/env.ex @@ -22,6 +22,12 @@ defmodule WandererApp.Env do key: "active_tracking_pool" ) def active_tracking_pool, do: get_key(:active_tracking_pool, "default") + + @decorate cacheable( + cache: WandererApp.Cache, + key: "tracking_pool_max_size" + ) + def tracking_pool_max_size, do: get_key(:tracking_pool_max_size, 300) def character_tracking_pause_disabled?, do: get_key(:character_tracking_pause_disabled, true) def character_api_disabled?, do: get_key(:character_api_disabled, false) def zkill_preload_disabled?, do: get_key(:zkill_preload_disabled, false) diff --git a/lib/wanderer_app/map.ex b/lib/wanderer_app/map.ex index bd12e701..8e694e9b 100644 --- a/lib/wanderer_app/map.ex +++ b/lib/wanderer_app/map.ex @@ -138,13 +138,8 @@ defmodule WandererApp.Map do def add_characters!(map, []), do: map def add_characters!(%{map_id: map_id} = map, [character | rest]) do - case add_character(map_id, character) do - :ok -> - add_characters!(map, rest) - - {:error, :already_exists} -> - add_characters!(map, rest) - end + add_character(map_id, character) + add_characters!(map, rest) end def add_character( @@ -172,15 +167,15 @@ defmodule WandererApp.Map do map_id |> update_map(%{characters: [character_id | characters]}) - WandererApp.Cache.insert( - "map:#{map_id}:character:#{character_id}:alliance_id", - alliance_id - ) + # WandererApp.Cache.insert( + # "map:#{map_id}:character:#{character_id}:alliance_id", + # alliance_id + # ) - WandererApp.Cache.insert( - "map:#{map_id}:character:#{character_id}:corporation_id", - corporation_id - ) + # WandererApp.Cache.insert( + # "map:#{map_id}:character:#{character_id}:corporation_id", + # corporation_id + # ) # WandererApp.Cache.insert( # "map:#{map_id}:character:#{character_id}:solar_system_id", diff --git a/lib/wanderer_app/ueberauth/strategy/eve.ex b/lib/wanderer_app/ueberauth/strategy/eve.ex index 6658e808..c061eeaa 100644 --- a/lib/wanderer_app/ueberauth/strategy/eve.ex +++ b/lib/wanderer_app/ueberauth/strategy/eve.ex @@ -192,7 +192,7 @@ defmodule WandererApp.Ueberauth.Strategy.Eve do end defp oauth_client_options_from_conn(conn, with_wallet, is_admin?) do - tracking_pool = WandererApp.Env.active_tracking_pool() + tracking_pool = WandererApp.Character.TrackingConfigUtils.get_active_pool!() base_options = [ redirect_uri: callback_url(conn), diff --git a/lib/wanderer_app/ueberauth/strategy/eve/init_configs_task.ex b/lib/wanderer_app/ueberauth/strategy/eve/init_configs_task.ex index 89b8fa67..563743c4 100644 --- a/lib/wanderer_app/ueberauth/strategy/eve/init_configs_task.ex +++ b/lib/wanderer_app/ueberauth/strategy/eve/init_configs_task.ex @@ -10,13 +10,8 @@ defmodule WandererApp.Esi.InitClientsTask do def run(_arg) do Logger.info("starting") - Cachex.put( - :esi_auth_cache, - :active_config, - "config_#{WandererApp.Env.active_tracking_pool()}" - ) - cache_clients() + WandererApp.Character.TrackingConfigUtils.update_active_tracking_pool() end defp cache_clients() do diff --git a/lib/wanderer_app_web/controllers/auth_controller.ex b/lib/wanderer_app_web/controllers/auth_controller.ex index 23cf1de4..956539f2 100644 --- a/lib/wanderer_app_web/controllers/auth_controller.ex +++ b/lib/wanderer_app_web/controllers/auth_controller.ex @@ -8,6 +8,8 @@ defmodule WandererAppWeb.AuthController do require Logger def callback(%{assigns: %{ueberauth_auth: auth, current_user: user} = _assigns} = conn, _params) do + active_tracking_pool = WandererApp.Character.TrackingConfigUtils.get_active_pool!() + character_data = %{ eve_id: "#{auth.info.email}", name: auth.info.name, @@ -15,7 +17,7 @@ defmodule WandererAppWeb.AuthController do refresh_token: auth.credentials.refresh_token, expires_at: auth.credentials.expires_at, scopes: auth.credentials.scopes, - tracking_pool: WandererApp.Env.active_tracking_pool() + tracking_pool: active_tracking_pool } %{ @@ -31,7 +33,7 @@ defmodule WandererAppWeb.AuthController do refresh_token: auth.credentials.refresh_token, expires_at: auth.credentials.expires_at, scopes: auth.credentials.scopes, - tracking_pool: WandererApp.Env.active_tracking_pool() + tracking_pool: active_tracking_pool } {:ok, character} = @@ -80,6 +82,8 @@ defmodule WandererAppWeb.AuthController do maybe_update_character_user_id(character, user_id) + WandererApp.Character.TrackingConfigUtils.update_active_tracking_pool() + conn |> put_session(:user_id, user_id) |> redirect(to: "/characters") diff --git a/lib/wanderer_app_web/live/admin/admin_live.ex b/lib/wanderer_app_web/live/admin/admin_live.ex index 357f9cc3..c2d7f155 100755 --- a/lib/wanderer_app_web/live/admin/admin_live.ex +++ b/lib/wanderer_app_web/live/admin/admin_live.ex @@ -63,6 +63,7 @@ defmodule WandererAppWeb.AdminLive do user_id: user_id, invite_link: nil, tracker_stats: [], + active_tracking_pool: "default", map_subscriptions_enabled?: WandererApp.Env.map_subscriptions_enabled?(), restrict_maps_creation?: WandererApp.Env.restrict_maps_creation?() )} @@ -295,7 +296,8 @@ defmodule WandererAppWeb.AdminLive do defp apply_action(socket, :index, _params, uri) do {:ok, invites} = WandererApp.Api.MapInvite.read() - {:ok, tracker_stats} = load_tracker_stats() + {:ok, tracker_stats} = WandererApp.Character.TrackingConfigUtils.load_tracker_stats() + active_tracking_pool = WandererApp.Character.TrackingConfigUtils.get_active_pool!() socket |> assign(:active_page, :admin) @@ -312,6 +314,7 @@ defmodule WandererAppWeb.AdminLive do |> assign(:unlink_character_form, to_form(%{})) |> assign(:invites, invites) |> assign(:tracker_stats, tracker_stats) + |> assign(:active_tracking_pool, active_tracking_pool) end defp apply_action(socket, :add_invite_link, _params, uri) do @@ -348,70 +351,6 @@ defmodule WandererAppWeb.AdminLive do |> assign(:invites, []) end - defp load_tracker_stats() do - {:ok, characters} = - WandererApp.Api.Character.last_active(%{ - from: - DateTime.utc_now() - |> DateTime.add(-1 * 60 * 24 * 7, :minute) - }) - - admins_count = - characters |> Enum.filter(&WandererApp.Character.can_track_corp_wallet?/1) |> Enum.count() - - with_wallets_count = - characters - |> Enum.filter( - &(WandererApp.Character.can_track_wallet?(&1) and - not WandererApp.Character.can_track_corp_wallet?(&1)) - ) - |> Enum.count() - - default_count = - characters - |> Enum.filter( - &(is_nil(&1.tracking_pool) and not WandererApp.Character.can_track_wallet?(&1) and - not WandererApp.Character.can_track_corp_wallet?(&1)) - ) - |> Enum.count() - - result = [ - %{title: "Admins", value: admins_count}, - %{title: "With Wallet", value: with_wallets_count}, - %{title: "Default", value: default_count} - ] - - {:ok, pools_count} = - Cachex.get( - :esi_auth_cache, - "configs_total_count" - ) - - result = - if not is_nil(pools_count) && pools_count != 0 do - pools = - 1..pools_count - |> Enum.map(fn pool_id -> - pools_character_count = - characters - |> Enum.filter( - &(&1.tracking_pool == "#{pool_id}" and - not WandererApp.Character.can_track_wallet?(&1) and - not WandererApp.Character.can_track_corp_wallet?(&1)) - ) - |> Enum.count() - - %{title: "Pool #{pool_id}", value: pools_character_count} - end) - - result ++ pools - else - result - end - - {:ok, result} - end - defp get_invite_link(uri, token) do uri |> Map.put(:path, "/auth/eve") diff --git a/lib/wanderer_app_web/live/admin/admin_live.html.heex b/lib/wanderer_app_web/live/admin/admin_live.html.heex index 12b8f6cf..924d194e 100644 --- a/lib/wanderer_app_web/live/admin/admin_live.html.heex +++ b/lib/wanderer_app_web/live/admin/admin_live.html.heex @@ -129,18 +129,18 @@ > <:col :let={invite} label="Link">