From ecb3ca2b4ed2fe6b6151e95c106ddda336f0adbb Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Tue, 15 Apr 2025 12:15:08 +0200 Subject: [PATCH] fix(Core): Fixed issues with main character & tracking --- .../api/map_character_settings.ex | 6 ++++ lib/wanderer_app/esi/api_client.ex | 4 +-- lib/wanderer_app/map/map_audit.ex | 4 +-- lib/wanderer_app/map/map_server.ex | 1 + .../map/server/map_server_acls_impl.ex | 19 ++++++++++++ .../map/server/map_server_characters_impl.ex | 13 ++++++++ .../map/server/map_server_connections_impl.ex | 3 +- .../map/server/map_server_impl.ex | 8 ++++- lib/wanderer_app/zkb/zkb_kills_preloader.ex | 20 ------------ .../live/characters/characters_live.ex | 19 ++++++++++-- .../live/characters/characters_live.html.heex | 2 +- .../map_activity_event_handler.ex | 4 +-- .../map_characters_event_handler.ex | 11 +++++-- .../event_handlers/map_core_event_handler.ex | 14 +++++++-- .../event_handlers/map_kills_event_handler.ex | 20 ++++++++---- .../live/map/map_event_handler.ex | 31 +------------------ 16 files changed, 105 insertions(+), 74 deletions(-) diff --git a/lib/wanderer_app/api/map_character_settings.ex b/lib/wanderer_app/api/map_character_settings.ex index 796a2687..bf3a1c0a 100644 --- a/lib/wanderer_app/api/map_character_settings.ex +++ b/lib/wanderer_app/api/map_character_settings.ex @@ -17,6 +17,7 @@ defmodule WandererApp.Api.MapCharacterSettings do define(:read_by_map, action: :read_by_map) define(:by_map_filtered, action: :by_map_filtered) define(:tracked_by_map_filtered, action: :tracked_by_map_filtered) + define(:tracked_by_character, action: :tracked_by_character) define(:tracked_by_map_all, action: :tracked_by_map_all) define(:track, action: :track) @@ -61,6 +62,11 @@ defmodule WandererApp.Api.MapCharacterSettings do filter(expr(map_id == ^arg(:map_id) and tracked == true)) end + read :tracked_by_character do + argument(:character_id, :uuid, allow_nil?: false) + filter(expr(character_id == ^arg(:character_id) and tracked == true)) + end + update :track do accept [:map_id, :character_id] argument :map_id, :string, allow_nil?: false diff --git a/lib/wanderer_app/esi/api_client.ex b/lib/wanderer_app/esi/api_client.ex index 4c101824..5bc0e886 100644 --- a/lib/wanderer_app/esi/api_client.ex +++ b/lib/wanderer_app/esi/api_client.ex @@ -33,7 +33,7 @@ defmodule WandererApp.Esi.ApiClient do @cache_opts [cache: true] @retry_opts [max_retries: 1, retry_log_level: :warning] - @timeout_opts [receive_timeout: :timer.seconds(30)] + @timeout_opts [pool_timeout: 15_000, receive_timeout: :timer.seconds(30)] @api_retry_count 1 @logger Application.compile_env(:wanderer_app, :logger) @@ -490,7 +490,7 @@ defmodule WandererApp.Esi.ApiClient do try do case Req.get( "#{@base_url}#{path}", - api_opts |> with_user_agent_opts() |> with_cache_opts() |> Keyword.merge(@retry_opts) + api_opts |> with_user_agent_opts() |> with_cache_opts() |> Keyword.merge(@retry_opts) |> Keyword.merge(@timeout_opts) ) do {:ok, %{status: 200, body: body}} -> {:ok, body} diff --git a/lib/wanderer_app/map/map_audit.ex b/lib/wanderer_app/map/map_audit.ex index c3234d9d..d91b6fa1 100644 --- a/lib/wanderer_app/map/map_audit.ex +++ b/lib/wanderer_app/map/map_audit.ex @@ -70,7 +70,7 @@ defmodule WandererApp.Map.Audit do def track_acl_event( event_type, %{user_id: user_id, acl_id: acl_id} = metadata - ), + ) when not is_nil(user_id) and not is_nil(acl_id), do: WandererApp.Api.UserActivity.new(%{ user_id: user_id, @@ -85,7 +85,7 @@ defmodule WandererApp.Map.Audit do def track_map_event( event_type, %{character_id: character_id, user_id: user_id, map_id: map_id} = metadata - ), + ) when not is_nil(character_id) and not is_nil(user_id) and not is_nil(map_id), do: WandererApp.Api.UserActivity.new(%{ character_id: character_id, diff --git a/lib/wanderer_app/map/map_server.ex b/lib/wanderer_app/map/map_server.ex index 997d3a75..0ffee261 100644 --- a/lib/wanderer_app/map/map_server.ex +++ b/lib/wanderer_app/map/map_server.ex @@ -32,6 +32,7 @@ defmodule WandererApp.Map.Server do map_id nil -> + WandererApp.Cache.insert("map_#{map_id}:started", false) throw("Map server not started") end end diff --git a/lib/wanderer_app/map/server/map_server_acls_impl.ex b/lib/wanderer_app/map/server/map_server_acls_impl.ex index 5165828b..31918412 100644 --- a/lib/wanderer_app/map/server/map_server_acls_impl.ex +++ b/lib/wanderer_app/map/server/map_server_acls_impl.ex @@ -86,6 +86,25 @@ defmodule WandererApp.Map.Server.AclsImpl do end end + def handle_acl_deleted(map_id, acl_id) do + {:ok, map} = + WandererApp.MapRepo.get(map_id, + acls: [ + :owner_id, + members: [:role, :eve_character_id, :eve_corporation_id, :eve_alliance_id] + ] + ) + + WandererApp.Map.update_map(map_id, %{acls: map.acls}) + + character_ids = + map_id + |> WandererApp.Map.get_map!() + |> Map.get(:characters, []) + + WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids) + end + def track_acls([]), do: :ok def track_acls([acl_id | rest]) do diff --git a/lib/wanderer_app/map/server/map_server_characters_impl.ex b/lib/wanderer_app/map/server/map_server_characters_impl.ex index 439d6b94..0820fde6 100644 --- a/lib/wanderer_app/map/server/map_server_characters_impl.ex +++ b/lib/wanderer_app/map/server/map_server_characters_impl.ex @@ -64,6 +64,16 @@ defmodule WandererApp.Map.Server.CharactersImpl do map_tracked_character_ids |> Enum.filter(fn character -> character in tracked_characters end) + {:ok, old_map_tracked_characters} = WandererApp.Cache.lookup("maps:#{map_id}:tracked_characters", []) + characters_to_remove = old_map_tracked_characters -- map_active_tracked_characters + + {:ok, invalidate_character_ids} = + WandererApp.Cache.lookup( + "map_#{map_id}:invalidate_character_ids", + [] + ) + + WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", (invalidate_character_ids ++ characters_to_remove) |> Enum.uniq()) WandererApp.Cache.insert("maps:#{map_id}:tracked_characters", map_active_tracked_characters) :ok @@ -98,6 +108,9 @@ defmodule WandererApp.Map.Server.CharactersImpl do character_id |> WandererApp.Character.get_character() |> case do + {:ok, %{user_id: nil}} -> + {:remove_character, character_id} + {:ok, character} -> [character_permissions] = WandererApp.Permissions.check_characters_access([character], acls) diff --git a/lib/wanderer_app/map/server/map_server_connections_impl.ex b/lib/wanderer_app/map/server/map_server_connections_impl.ex index bba97d09..e00bedfc 100644 --- a/lib/wanderer_app/map/server/map_server_connections_impl.ex +++ b/lib/wanderer_app/map/server/map_server_connections_impl.ex @@ -377,12 +377,11 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do Impl.broadcast!(map_id, :add_connection, connection) {:ok, character} = WandererApp.Character.get_character(character_id) - {:ok, character_with_user} = character |> Ash.load(:user) {:ok, _} = WandererApp.User.ActivityTracker.track_map_event(:map_connection_added, %{ character_id: character_id, - user_id: character_with_user.user_id, + user_id: character.user_id, map_id: map_id, solar_system_source_id: old_location.solar_system_id, solar_system_target_id: location.solar_system_id diff --git a/lib/wanderer_app/map/server/map_server_impl.ex b/lib/wanderer_app/map/server/map_server_impl.ex index eacb8e49..d4714a3b 100644 --- a/lib/wanderer_app/map/server/map_server_impl.ex +++ b/lib/wanderer_app/map/server/map_server_impl.ex @@ -261,6 +261,12 @@ defmodule WandererApp.Map.Server.Impl do state end + def handle_event({:acl_deleted, %{acl_id: acl_id}}, %{map_id: map_id} = state) do + AclsImpl.handle_acl_updated(map_id, acl_id) + + state + end + def handle_event(:cleanup_connections, state) do Process.send_after(self(), :cleanup_connections, @connections_cleanup_timeout) @@ -299,7 +305,7 @@ defmodule WandererApp.Map.Server.Impl do %{state | map_opts: map_options(options)} end - def handle_event({ref, _result}, %{map_id: _map_id} = state) do + def handle_event({ref, _result}, %{map_id: _map_id} = state) when is_reference(ref) do Process.demonitor(ref, [:flush]) state diff --git a/lib/wanderer_app/zkb/zkb_kills_preloader.ex b/lib/wanderer_app/zkb/zkb_kills_preloader.ex index 435a9385..799b3e30 100644 --- a/lib/wanderer_app/zkb/zkb_kills_preloader.ex +++ b/lib/wanderer_app/zkb/zkb_kills_preloader.ex @@ -175,10 +175,6 @@ defmodule WandererApp.Zkb.KillsPreloader do reduce_task_result(pass_type, task_result, acc_state, acc_map) end) - if map_size(kills_map) > 0 do - broadcast_all_kills(kills_map, pass_type) - end - final_state end @@ -276,22 +272,6 @@ defmodule WandererApp.Zkb.KillsPreloader do defp log_failed_task(:expanded, reason), do: Logger.error("[KillsPreloader] Expanded fetch task failed => #{inspect(reason)}") - defp broadcast_all_kills(kills_map, pass_type) do - Logger.info( - "[KillsPreloader] Broadcasting kills => #{map_size(kills_map)} systems (#{pass_type})" - ) - - Phoenix.PubSub.broadcast!( - WandererApp.PubSub, - "zkb_preload", - %{ - event: :detailed_kills_updated, - payload: kills_map, - fetch_type: pass_type - } - ) - end - defp merge_calls_count(%{calls_count: c1} = st1, %{calls_count: c2}), do: %{st1 | calls_count: c1 + c2} diff --git a/lib/wanderer_app_web/live/characters/characters_live.ex b/lib/wanderer_app_web/live/characters/characters_live.ex index b001bd2f..8ca3b99c 100755 --- a/lib/wanderer_app_web/live/characters/characters_live.ex +++ b/lib/wanderer_app_web/live/characters/characters_live.ex @@ -64,9 +64,22 @@ defmodule WandererAppWeb.CharactersLive do @impl true def handle_event("delete", %{"character_id" => character_id}, socket) do - socket.assigns.characters - |> Enum.find(&(&1.id == character_id)) - |> WandererApp.Api.Character.mark_as_deleted!() + WandererApp.Character.TrackerManager.stop_tracking(character_id) + + {:ok, map_user_settings} = WandererApp.Api.MapCharacterSettings.tracked_by_character(%{character_id: character_id}) + + map_user_settings + |> Enum.each(fn settings -> + settings + |> WandererApp.Api.MapCharacterSettings.untrack() + end) + + {:ok, updated_character} = + socket.assigns.characters + |> Enum.find(&(&1.id == character_id)) + |> WandererApp.Api.Character.mark_as_deleted() + + WandererApp.Character.update_character(character_id, updated_character) {:ok, characters} = WandererApp.Api.Character.active_by_user(%{user_id: socket.assigns.user_id}) diff --git a/lib/wanderer_app_web/live/characters/characters_live.html.heex b/lib/wanderer_app_web/live/characters/characters_live.html.heex index b56d73b9..1666b147 100644 --- a/lib/wanderer_app_web/live/characters/characters_live.html.heex +++ b/lib/wanderer_app_web/live/characters/characters_live.html.heex @@ -79,7 +79,7 @@
Enum.sort_by(& &1.name, :asc)} class="card rounded-none bg-gradient-to-l from-stone-950 to-stone-900 hover:text-white transform transition duration-500" >
diff --git a/lib/wanderer_app_web/live/map/event_handlers/map_activity_event_handler.ex b/lib/wanderer_app_web/live/map/event_handlers/map_activity_event_handler.ex index 45a022a5..e25d2190 100644 --- a/lib/wanderer_app_web/live/map/event_handlers/map_activity_event_handler.ex +++ b/lib/wanderer_app_web/live/map/event_handlers/map_activity_event_handler.ex @@ -74,12 +74,12 @@ defmodule WandererAppWeb.MapActivityEventHandler do } end) - {:activity_data, summarized_result} + {:character_activity_data, summarized_result} rescue e -> Logger.error("Error processing character activity: #{inspect(e)}") Logger.error("#{Exception.format_stacktrace()}") - {:activity_data, []} + {:character_activity_data, []} end end) diff --git a/lib/wanderer_app_web/live/map/event_handlers/map_characters_event_handler.ex b/lib/wanderer_app_web/live/map/event_handlers/map_characters_event_handler.ex index 9a612664..f6b0b8d2 100644 --- a/lib/wanderer_app_web/live/map/event_handlers/map_characters_event_handler.ex +++ b/lib/wanderer_app_web/live/map/event_handlers/map_characters_event_handler.ex @@ -240,12 +240,19 @@ defmodule WandererAppWeb.MapCharactersEventHandler do {:ok, tracking_data} = WandererApp.Character.TrackingUtils.build_tracking_data(map_id, current_user_id) - {:ok, main_character_id} = + {main_character_id, main_character_eve_id} = WandererApp.Character.TrackingUtils.get_main_character( map_user_settings, current_user_characters, current_user_characters ) + |> case do + {:ok, main_character} when not is_nil(main_character) -> + {main_character.id, main_character.eve_id} + + _ -> + {nil, nil} + end Process.send_after(self(), %{event: :refresh_user_characters}, 50) @@ -254,7 +261,7 @@ defmodule WandererAppWeb.MapCharactersEventHandler do |> assign( map_user_settings: map_user_settings, main_character_id: main_character_id, - main_character_eve_id: character_eve_id + main_character_eve_id: main_character_eve_id )} end diff --git a/lib/wanderer_app_web/live/map/event_handlers/map_core_event_handler.ex b/lib/wanderer_app_web/live/map/event_handlers/map_core_event_handler.ex index fe0ea226..60680949 100644 --- a/lib/wanderer_app_web/live/map/event_handlers/map_core_event_handler.ex +++ b/lib/wanderer_app_web/live/map/event_handlers/map_core_event_handler.ex @@ -335,12 +335,20 @@ defmodule WandererAppWeb.MapCoreEventHandler do only_tracked_characters ) - {:ok, main_character} = + + {main_character_id, main_character_eve_id} = WandererApp.Character.TrackingUtils.get_main_character( map_user_settings, current_user_characters, available_map_characters ) + |> case do + {:ok, main_character} when not is_nil(main_character) -> + {main_character.id, main_character.eve_id} + + _ -> + {nil, nil} + end following_character_eve_id = case map_user_settings do nil -> nil @@ -351,8 +359,8 @@ defmodule WandererAppWeb.MapCoreEventHandler do %{ user_permissions: user_permissions, map_user_settings: map_user_settings, - main_character_id: main_character.id, - main_character_eve_id: main_character.eve_id, + main_character_id: main_character_id, + main_character_eve_id: main_character_eve_id, following_character_eve_id: following_character_eve_id, tracked_characters: tracked_data.tracked_characters, all_character_tracked?: tracked_data.all_tracked?, diff --git a/lib/wanderer_app_web/live/map/event_handlers/map_kills_event_handler.ex b/lib/wanderer_app_web/live/map/event_handlers/map_kills_event_handler.ex index 52e0eac0..f03ca754 100644 --- a/lib/wanderer_app_web/live/map/event_handlers/map_kills_event_handler.ex +++ b/lib/wanderer_app_web/live/map/event_handlers/map_kills_event_handler.ex @@ -45,12 +45,20 @@ defmodule WandererAppWeb.MapKillsEventHandler do ) end - def handle_server_event(%{event: :detailed_kills_updated, payload: payload}, socket) do - socket - |> MapEventHandler.push_map_event( - "detailed_kills_updated", - payload - ) + def handle_server_event(%{event: :detailed_kills_updated, payload: payload}, %{ + assigns: %{ + map_id: map_id + } + } = socket) do + case WandererApp.Map.is_subscription_active?(map_id) do + {:ok, true} -> + socket + |> MapEventHandler.push_map_event( + "detailed_kills_updated", + payload + ) + _ -> socket + end end def handle_server_event( diff --git a/lib/wanderer_app_web/live/map/map_event_handler.ex b/lib/wanderer_app_web/live/map/map_event_handler.ex index 2a132fec..dbb08c81 100644 --- a/lib/wanderer_app_web/live/map/map_event_handler.ex +++ b/lib/wanderer_app_web/live/map/map_event_handler.ex @@ -173,28 +173,10 @@ defmodule WandererAppWeb.MapEventHandler do when event_name in @map_signatures_events, do: MapSignaturesEventHandler.handle_server_event(event, socket) - def handle_event( - %{ - assigns: %{ - is_subscription_active?: true - } - } = socket, - %{event: event_name} = event - ) + def handle_event(socket, %{event: event_name} = event) when event_name in @map_kills_events, do: MapKillsEventHandler.handle_server_event(event, socket) - def handle_event( - %{ - assigns: %{ - is_subscription_active?: false - } - } = socket, - %{event: event_name} = _event - ) - when event_name in @map_kills_events, - do: socket - def handle_event(socket, {ref, result}) when is_reference(ref) do Process.demonitor(ref, [:flush]) @@ -203,12 +185,6 @@ defmodule WandererAppWeb.MapEventHandler do Process.send_after(self(), map_error, 100) socket - {:activity_data, activity_data} -> - MapActivityEventHandler.handle_server_event( - %{event: :character_activity_data, payload: activity_data}, - socket - ) - {event, payload} -> Process.send_after( self(), @@ -227,11 +203,6 @@ defmodule WandererAppWeb.MapEventHandler do def handle_event(socket, {:DOWN, ref, :process, _pid, reason}) when is_reference(ref) do # Task failed, log the error and update the client Logger.error("Task failed: #{inspect(reason)}") - - MapActivityEventHandler.handle_server_event( - %{event: :character_activity_data, payload: []}, - socket - ) end def handle_event(socket, event),