From 4eb4a03e5940c2968ca32093a48b67b6ddd3edbf Mon Sep 17 00:00:00 2001 From: CI Date: Thu, 22 May 2025 09:45:26 +0000 Subject: [PATCH 01/14] chore: release version v1.65.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ mix.exs | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 525eeb75..03001732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ +## [v1.65.0](https://github.com/wanderer-industries/wanderer/compare/v1.64.8...v1.65.0) (2025-05-22) + + + + +### Features: + +* default connections from c1 holes to medium size + +* support german and french signatures + +* improve signature undo process + +### Bug Fixes: + +* remove required id field from character schema + +* update openapi spec response types + +* fix issue with connection generation between k-space + +* Signature: Fixed signatures updates + +* update openapi spec for other apis + ## [v1.64.8](https://github.com/wanderer-industries/wanderer/compare/v1.64.7...v1.64.8) (2025-05-20) diff --git a/mix.exs b/mix.exs index e5303a9a..cbeaaa32 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.64.8" + @version "1.65.0" def project do [ From 197f5b583fc3c46564abad8d08a38791c53fe595 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Thu, 22 May 2025 11:52:20 +0200 Subject: [PATCH 02/14] fix(Core): Added unsync map events timeout handling (force page refresh if outdated map events found) --- lib/wanderer_app_web/live/map/map_live.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wanderer_app_web/live/map/map_live.ex b/lib/wanderer_app_web/live/map/map_live.ex index 3d429283..7e4627ae 100644 --- a/lib/wanderer_app_web/live/map/map_live.ex +++ b/lib/wanderer_app_web/live/map/map_live.ex @@ -4,7 +4,7 @@ defmodule WandererAppWeb.MapLive do require Logger - @server_event_unsync_timeout :timer.minutes(5) + @server_event_unsync_timeout :timer.minutes(2) @impl true def mount(%{"slug" => map_slug} = _params, _session, socket) when is_connected?(socket) do From a4a34c8ba717d6880f1a1d8d91df3c1675e6fd4f Mon Sep 17 00:00:00 2001 From: CI Date: Thu, 22 May 2025 11:47:01 +0000 Subject: [PATCH 03/14] chore: release version v1.65.1 --- CHANGELOG.md | 9 +++++++++ mix.exs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03001732..84174af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ +## [v1.65.1](https://github.com/wanderer-industries/wanderer/compare/v1.65.0...v1.65.1) (2025-05-22) + + + + +### Bug Fixes: + +* Core: Added unsync map events timeout handling (force page refresh if outdated map events found) + ## [v1.65.0](https://github.com/wanderer-industries/wanderer/compare/v1.64.8...v1.65.0) (2025-05-22) diff --git a/mix.exs b/mix.exs index cbeaaa32..1d7c1ca4 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.0" + @version "1.65.1" def project do [ From af2bfd4d598648ba9d170e651cfc2fcb193c41b6 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Fri, 23 May 2025 17:24:30 +0200 Subject: [PATCH 04/14] fix(Signature): Fixed signature updates --- .../widgets/SystemSignatures/helpers/getState.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts index 189780a4..b4ea3466 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/helpers/getState.ts @@ -1,14 +1,15 @@ import { UNKNOWN_SIGNATURE_NAME } from '@/hooks/Mapper/helpers'; -import { SystemSignature } from '@/hooks/Mapper/types'; +import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types'; export const getState = (_: string[], newSig: SystemSignature) => { let state = -1; - if (!newSig.group) { + if (!newSig.group || newSig.group === SignatureGroup.CosmicSignature) { state = 0; } else if (!newSig.name || newSig.name === '' || newSig.name === UNKNOWN_SIGNATURE_NAME) { state = 1; } else if (newSig.name !== '') { state = 2; } + return state; }; From dd5fd114d2ab3813551ba291b9d6900494fcbe32 Mon Sep 17 00:00:00 2001 From: CI Date: Fri, 23 May 2025 15:33:00 +0000 Subject: [PATCH 05/14] chore: release version v1.65.2 --- CHANGELOG.md | 9 +++++++++ mix.exs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84174af5..abc814ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ +## [v1.65.2](https://github.com/wanderer-industries/wanderer/compare/v1.65.1...v1.65.2) (2025-05-23) + + + + +### Bug Fixes: + +* Signature: Fixed signature updates + ## [v1.65.1](https://github.com/wanderer-industries/wanderer/compare/v1.65.0...v1.65.1) (2025-05-22) diff --git a/mix.exs b/mix.exs index 1d7c1ca4..3a27493b 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.1" + @version "1.65.2" def project do [ From 0b7e0b9cd07528378039c98b8a31c1516e182934 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Fri, 23 May 2025 20:06:17 +0200 Subject: [PATCH 06/14] fix(Signature): Fixed signature clenup --- lib/wanderer_app/map/server/map_server_impl.ex | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/wanderer_app/map/server/map_server_impl.ex b/lib/wanderer_app/map/server/map_server_impl.ex index bdcd483d..2a8ca6e2 100644 --- a/lib/wanderer_app/map/server/map_server_impl.ex +++ b/lib/wanderer_app/map/server/map_server_impl.ex @@ -93,7 +93,6 @@ defmodule WandererApp.Map.Server.Impl do Process.send_after(self(), :cleanup_connections, 5_000) Process.send_after(self(), :cleanup_systems, 10_000) Process.send_after(self(), :cleanup_characters, :timer.minutes(5)) - Process.send_after(self(), :cleanup_signatures, :timer.minutes(30)) Process.send_after(self(), :backup_state, @backup_state_timeout) WandererApp.Cache.insert("map_#{map_id}:started", true) @@ -312,11 +311,6 @@ defmodule WandererApp.Map.Server.Impl do state end - def handle_event(:cleanup_signatures, state) do - Process.send_after(self(), :cleanup_signatures, :timer.minutes(30)) - state |> SignaturesImpl.cleanup_signatures() - end - def handle_event(msg, state) do Logger.warning("Unhandled event: #{inspect(msg)}") From 3670ef40a34dc97ce991d430107a0a1cebca8283 Mon Sep 17 00:00:00 2001 From: CI Date: Fri, 23 May 2025 18:29:03 +0000 Subject: [PATCH 07/14] chore: release version v1.65.3 --- CHANGELOG.md | 9 +++++++++ mix.exs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abc814ab..2fcf76f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ +## [v1.65.3](https://github.com/wanderer-industries/wanderer/compare/v1.65.2...v1.65.3) (2025-05-23) + + + + +### Bug Fixes: + +* Signature: Fixed signature clenup + ## [v1.65.2](https://github.com/wanderer-industries/wanderer/compare/v1.65.1...v1.65.2) (2025-05-23) diff --git a/mix.exs b/mix.exs index 3a27493b..f4e8a375 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.2" + @version "1.65.3" def project do [ From 94c89e03250cc1e1bd08e118ac529ffa2ff7aaa5 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Sat, 24 May 2025 19:18:50 +0200 Subject: [PATCH 08/14] fix(Signature): Force signature update even if there are no any changes --- .../hooks/useSystemSignaturesData.ts | 2 +- lib/wanderer_app/api/map_system_signature.ex | 53 +++-- .../map/server/map_server_signatures_impl.ex | 40 +++- ...0250524170825_add_sig_update_forced_at.exs | 21 ++ .../20250524170825.json | 207 ++++++++++++++++++ 5 files changed, 294 insertions(+), 29 deletions(-) create mode 100644 priv/repo/migrations/20250524170825_add_sig_update_forced_at.exs create mode 100644 priv/resource_snapshots/repo/map_system_signatures_v1/20250524170825.json diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/hooks/useSystemSignaturesData.ts b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/hooks/useSystemSignaturesData.ts index 5f05a3fc..3aeddcb1 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/hooks/useSystemSignaturesData.ts +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/hooks/useSystemSignaturesData.ts @@ -70,7 +70,7 @@ export const useSystemSignaturesData = ({ ? signaturesRef.current.filter(sig => !sig.pendingDeletion) : signaturesRef.current.filter(sig => !sig.pendingDeletion || !sig.pendingAddition); - const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, true); + const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, false); if (removed.length > 0) { await processRemovedSignatures(removed, added, updated); diff --git a/lib/wanderer_app/api/map_system_signature.ex b/lib/wanderer_app/api/map_system_signature.ex index 1925307a..2c1e642e 100644 --- a/lib/wanderer_app/api/map_system_signature.ex +++ b/lib/wanderer_app/api/map_system_signature.ex @@ -25,9 +25,18 @@ defmodule WandererApp.Api.MapSystemSignature do define(:by_system_id, action: :by_system_id, args: [:system_id]) define(:by_system_id_all, action: :by_system_id_all, args: [:system_id]) - define(:by_system_id_and_eve_ids, action: :by_system_id_and_eve_ids, args: [:system_id, :eve_ids]) + + define(:by_system_id_and_eve_ids, + action: :by_system_id_and_eve_ids, + args: [:system_id, :eve_ids] + ) + define(:by_linked_system_id, action: :by_linked_system_id, args: [:linked_system_id]) - define(:by_deleted_and_updated_before!, action: :by_deleted_and_updated_before, args: [:deleted, :updated_before]) + + define(:by_deleted_and_updated_before!, + action: :by_deleted_and_updated_before, + args: [:deleted, :updated_before] + ) end actions do @@ -88,7 +97,8 @@ defmodule WandererApp.Api.MapSystemSignature do :group, :type, :custom_info, - :deleted + :deleted, + :update_forced_at ] primary? true @@ -177,6 +187,10 @@ defmodule WandererApp.Api.MapSystemSignature do default false end + attribute :update_forced_at, :utc_datetime do + allow_nil? true + end + create_timestamp(:inserted_at) update_timestamp(:updated_at) end @@ -192,21 +206,20 @@ defmodule WandererApp.Api.MapSystemSignature do end @derive {Jason.Encoder, - only: [ - :id, - :system_id, - :eve_id, - :character_eve_id, - :name, - :description, - :type, - :linked_system_id, - :kind, - :group, - :custom_info, - :deleted, - :inserted_at, - :updated_at - ] - } + only: [ + :id, + :system_id, + :eve_id, + :character_eve_id, + :name, + :description, + :type, + :linked_system_id, + :kind, + :group, + :custom_info, + :deleted, + :inserted_at, + :updated_at + ]} end diff --git a/lib/wanderer_app/map/server/map_server_signatures_impl.ex b/lib/wanderer_app/map/server/map_server_signatures_impl.ex index 7792e5e1..0a610abe 100644 --- a/lib/wanderer_app/map/server/map_server_signatures_impl.ex +++ b/lib/wanderer_app/map/server/map_server_signatures_impl.ex @@ -25,7 +25,10 @@ defmodule WandererApp.Map.Server.SignaturesImpl do ) when not is_nil(char_id) do with {:ok, system} <- - MapSystem.read_by_map_and_solar_system(%{map_id: map_id, solar_system_id: system_solar_id}), + MapSystem.read_by_map_and_solar_system(%{ + map_id: map_id, + solar_system_id: system_solar_id + }), {:ok, %{eve_id: char_eve_id}} <- Character.get_character(char_id) do do_update_signatures( state, @@ -84,9 +87,11 @@ defmodule WandererApp.Map.Server.SignaturesImpl do # 3. Additions & restorations added_eve_ids = Enum.map(added_sigs, & &1.eve_id) - existing_index = MapSystemSignature.by_system_id_all!(system.id) - |> Enum.filter(&(&1.eve_id in added_eve_ids)) - |> Map.new(&{&1.eve_id, &1}) + + existing_index = + MapSystemSignature.by_system_id_all!(system.id) + |> Enum.filter(&(&1.eve_id in added_eve_ids)) + |> Map.new(&{&1.eve_id, &1}) added_sigs |> Enum.each(fn sig -> @@ -97,7 +102,16 @@ defmodule WandererApp.Map.Server.SignaturesImpl do %MapSystemSignature{deleted: true} = deleted_sig -> MapSystemSignature.update!( deleted_sig, - Map.take(sig, [:name, :description, :kind, :group, :type, :custom_info, :deleted]) + Map.take(sig, [ + :name, + :description, + :kind, + :group, + :type, + :custom_info, + :deleted, + :update_forced_at + ]) ) _ -> @@ -107,7 +121,12 @@ defmodule WandererApp.Map.Server.SignaturesImpl do # 4. Activity tracking if added_ids != [] do - track_activity(:signatures_added, state.map_id, system.solar_system_id, user_id, character_eve_id, + track_activity( + :signatures_added, + state.map_id, + system.solar_system_id, + user_id, + character_eve_id, added_ids ) end @@ -152,8 +171,13 @@ defmodule WandererApp.Map.Server.SignaturesImpl do defp apply_update_signature(%MapSystemSignature{} = existing, update_params) when not is_nil(update_params) do - case MapSystemSignature.update(existing, update_params) do - {:ok, _} -> :ok + case MapSystemSignature.update( + existing, + update_params |> Map.put(:update_forced_at, DateTime.utc_now()) + ) do + {:ok, _updated} -> + :ok + {:error, reason} -> Logger.error("Failed to update signature #{existing.id}: #{inspect(reason)}") end diff --git a/priv/repo/migrations/20250524170825_add_sig_update_forced_at.exs b/priv/repo/migrations/20250524170825_add_sig_update_forced_at.exs new file mode 100644 index 00000000..772d7dee --- /dev/null +++ b/priv/repo/migrations/20250524170825_add_sig_update_forced_at.exs @@ -0,0 +1,21 @@ +defmodule WandererApp.Repo.Migrations.AddSigUpdateForcedAt do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + alter table(:map_system_signatures_v1) do + add :update_forced_at, :utc_datetime + end + end + + def down do + alter table(:map_system_signatures_v1) do + remove :update_forced_at + end + end +end diff --git a/priv/resource_snapshots/repo/map_system_signatures_v1/20250524170825.json b/priv/resource_snapshots/repo/map_system_signatures_v1/20250524170825.json new file mode 100644 index 00000000..634c58a4 --- /dev/null +++ b/priv/resource_snapshots/repo/map_system_signatures_v1/20250524170825.json @@ -0,0 +1,207 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "eve_id", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "character_eve_id", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "name", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "description", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "type", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "linked_system_id", + "type": "bigint" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "kind", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "group", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "custom_info", + "type": "text" + }, + { + "allow_nil?": false, + "default": "false", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "deleted", + "type": "boolean" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "update_forced_at", + "type": "utc_datetime" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "map_system_signatures_v1_system_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "map_system_v1" + }, + "size": null, + "source": "system_id", + "type": "uuid" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "915C0896211ECCB6C38871664117E7D470C794825536E7F0887DC5B92681F17B", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "map_system_signatures_v1_uniq_system_eve_id_index", + "keys": [ + { + "type": "atom", + "value": "system_id" + }, + { + "type": "atom", + "value": "eve_id" + } + ], + "name": "uniq_system_eve_id", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.WandererApp.Repo", + "schema": null, + "table": "map_system_signatures_v1" +} \ No newline at end of file From 40672f6a475fefd7b707e2ff7aba93ae3692c288 Mon Sep 17 00:00:00 2001 From: CI Date: Sat, 24 May 2025 17:30:03 +0000 Subject: [PATCH 09/14] chore: release version v1.65.4 --- CHANGELOG.md | 9 +++++++++ mix.exs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fcf76f7..924edff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ +## [v1.65.4](https://github.com/wanderer-industries/wanderer/compare/v1.65.3...v1.65.4) (2025-05-24) + + + + +### Bug Fixes: + +* Signature: Force signature update even if there are no any changes + ## [v1.65.3](https://github.com/wanderer-industries/wanderer/compare/v1.65.2...v1.65.3) (2025-05-23) diff --git a/mix.exs b/mix.exs index f4e8a375..c9841709 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.3" + @version "1.65.4" def project do [ From 2af562e3137356bbfeb8ed6f1f6cc562f5c759ca Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Sun, 25 May 2025 09:41:33 +0200 Subject: [PATCH 10/14] fix(Signature): Update restored signature character --- lib/wanderer_app/map/server/map_server_signatures_impl.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/wanderer_app/map/server/map_server_signatures_impl.ex b/lib/wanderer_app/map/server/map_server_signatures_impl.ex index 0a610abe..6a0b2b76 100644 --- a/lib/wanderer_app/map/server/map_server_signatures_impl.ex +++ b/lib/wanderer_app/map/server/map_server_signatures_impl.ex @@ -108,6 +108,7 @@ defmodule WandererApp.Map.Server.SignaturesImpl do :kind, :group, :type, + :character_eve_id, :custom_info, :deleted, :update_forced_at From 3e9241892edd53e13bcd974184bc75f6164e14c5 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Mon, 26 May 2025 01:41:21 +0200 Subject: [PATCH 11/14] fix(Core): Fixed map character tracking issues --- .../api/map_character_settings.ex | 45 ++++++++++++---- .../character/tracker_manager_impl.ex | 2 +- lib/wanderer_app/character/tracking_utils.ex | 31 +++++------ .../map/server/map_server_characters_impl.ex | 54 ++++++++++++------- .../map/server/map_server_impl.ex | 8 --- .../map_character_settings_repo.ex | 5 +- .../characters/characters_tracking_live.ex | 2 + .../map_characters_event_handler.ex | 13 +++-- .../event_handlers/map_core_event_handler.ex | 8 --- .../live/map/map_characters_live.ex | 6 +-- .../live/map/map_event_handler.ex | 3 +- 11 files changed, 102 insertions(+), 75 deletions(-) diff --git a/lib/wanderer_app/api/map_character_settings.ex b/lib/wanderer_app/api/map_character_settings.ex index b84e0268..099e9e2a 100644 --- a/lib/wanderer_app/api/map_character_settings.ex +++ b/lib/wanderer_app/api/map_character_settings.ex @@ -5,15 +5,16 @@ defmodule WandererApp.Api.MapCharacterSettings do domain: WandererApp.Api, data_layer: AshPostgres.DataLayer - @derive {Jason.Encoder, only: [ - :id, - :map_id, - :character_id, - :tracked, - :followed, - :inserted_at, - :updated_at - ]} + @derive {Jason.Encoder, + only: [ + :id, + :map_id, + :character_id, + :tracked, + :followed, + :inserted_at, + :updated_at + ]} postgres do repo(WandererApp.Repo) @@ -44,7 +45,31 @@ defmodule WandererApp.Api.MapCharacterSettings do :tracked ] - defaults [:create, :read, :update, :destroy] + defaults [:read, :update, :destroy] + + create :create do + primary? true + upsert? true + upsert_identity :uniq_map_character + + upsert_fields [ + :map_id, + :character_id + ] + + accept [ + :map_id, + :character_id, + :tracked, + :followed + ] + + argument :map_id, :uuid, allow_nil?: false + argument :character_id, :uuid, allow_nil?: false + + change manage_relationship(:map_id, :map, on_lookup: :relate, on_no_match: nil) + change manage_relationship(:character_id, :character, on_lookup: :relate, on_no_match: nil) + end read :by_map_filtered do argument(:map_id, :string, allow_nil?: false) diff --git a/lib/wanderer_app/character/tracker_manager_impl.ex b/lib/wanderer_app/character/tracker_manager_impl.ex index 355a10ff..36195e12 100644 --- a/lib/wanderer_app/character/tracker_manager_impl.ex +++ b/lib/wanderer_app/character/tracker_manager_impl.ex @@ -13,7 +13,7 @@ defmodule WandererApp.Character.TrackerManager.Impl do } @garbage_collection_interval :timer.minutes(15) - @untrack_characters_interval :timer.minutes(5) + @untrack_characters_interval :timer.minutes(1) @inactive_character_timeout :timer.minutes(5) @logger Application.compile_env(:wanderer_app, :logger) diff --git a/lib/wanderer_app/character/tracking_utils.ex b/lib/wanderer_app/character/tracking_utils.ex index 6cc4f8db..7d27180f 100644 --- a/lib/wanderer_app/character/tracking_utils.ex +++ b/lib/wanderer_app/character/tracking_utils.ex @@ -121,7 +121,6 @@ defmodule WandererApp.Character.TrackingUtils do WandererApp.MapCharacterSettingsRepo.untrack(existing_settings) :ok = untrack([character], map_id, caller_pid) - :ok = remove_characters([character], map_id) {:ok, updated_settings} else {:ok, existing_settings} @@ -132,7 +131,6 @@ defmodule WandererApp.Character.TrackingUtils do if track do {:ok, updated_settings} = WandererApp.MapCharacterSettingsRepo.track(existing_settings) :ok = track([character], map_id, true, caller_pid) - :ok = add_characters([character], map_id, true) {:ok, updated_settings} else {:ok, existing_settings} @@ -149,7 +147,6 @@ defmodule WandererApp.Character.TrackingUtils do }) :ok = track([character], map_id, true, caller_pid) - :ok = add_characters([character], map_id, true) {:ok, settings} else {:error, "Character settings not found"} @@ -231,15 +228,15 @@ defmodule WandererApp.Character.TrackingUtils do with false <- is_nil(caller_pid) do character_ids = characters |> Enum.map(& &1.id) - characters - |> Enum.each(fn character -> - WandererAppWeb.Presence.update(caller_pid, map_id, character.id, %{ + character_ids + |> Enum.each(fn character_id -> + WandererAppWeb.Presence.update(caller_pid, map_id, character_id, %{ tracked: false, from: DateTime.utc_now() }) end) - WandererApp.Map.Server.untrack_characters(map_id, character_ids) + # WandererApp.Map.Server.untrack_characters(map_id, character_ids) :ok else @@ -249,19 +246,19 @@ defmodule WandererApp.Character.TrackingUtils do end end - def add_characters([], _map_id, _track_character), do: :ok + # def add_characters([], _map_id, _track_character), do: :ok - def add_characters([character | characters], map_id, track_character) do - :ok = WandererApp.Map.Server.add_character(map_id, character, track_character) - add_characters(characters, map_id, track_character) - end + # def add_characters([character | characters], map_id, track_character) do + # :ok = WandererApp.Map.Server.add_character(map_id, character, track_character) + # add_characters(characters, map_id, track_character) + # end - def remove_characters([], _map_id), do: :ok + # def remove_characters([], _map_id), do: :ok - def remove_characters([character | characters], map_id) do - :ok = WandererApp.Map.Server.remove_character(map_id, character.id) - remove_characters(characters, map_id) - end + # def remove_characters([character | characters], map_id) do + # :ok = WandererApp.Map.Server.remove_character(map_id, character.id) + # remove_characters(characters, map_id) + # end def get_main_character( nil, 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 0820fde6..07891cca 100644 --- a/lib/wanderer_app/map/server/map_server_characters_impl.ex +++ b/lib/wanderer_app/map/server/map_server_characters_impl.ex @@ -11,7 +11,7 @@ defmodule WandererApp.Map.Server.CharactersImpl do def add_character(%{map_id: map_id} = state, %{id: character_id} = character, track_character) do Task.start_link(fn -> with :ok <- map_id |> WandererApp.Map.add_character(character), - {:ok, _} <- + {:ok, _settings} <- WandererApp.MapCharacterSettingsRepo.create(%{ character_id: character_id, map_id: map_id, @@ -64,7 +64,9 @@ 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", []) + {: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} = @@ -73,7 +75,11 @@ defmodule WandererApp.Map.Server.CharactersImpl do [] ) - WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", (invalidate_character_ids ++ characters_to_remove) |> Enum.uniq()) + 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 @@ -84,10 +90,15 @@ defmodule WandererApp.Map.Server.CharactersImpl do do: character_ids |> Enum.each(fn character_id -> + # TODO consider storing character data in MapCharacterSettings + # remove_character(map_id, character_id) + WandererApp.Character.TrackerManager.update_track_settings(character_id, %{ map_id: map_id, track: false }) + + Impl.broadcast!(map_id, :untrack_character, character_id) end) def cleanup_characters(map_id, owner_id) do @@ -315,15 +326,18 @@ defmodule WandererApp.Map.Server.CharactersImpl do is_nil(structure_id) and is_nil(station_id) end - defp track_character(map_id, character_id), - do: - WandererApp.Character.TrackerManager.update_track_settings(character_id, %{ - map_id: map_id, - track: true, - track_online: true, - track_location: true, - track_ship: true - }) + defp track_character(map_id, character_id) do + {:ok, character} = WandererApp.Character.get_character(character_id) + add_character(%{map_id: map_id}, character, true) + + WandererApp.Character.TrackerManager.update_track_settings(character_id, %{ + map_id: map_id, + track: true, + track_online: true, + track_location: true, + track_ship: true + }) + end defp maybe_update_online(map_id, character_id) do with {:ok, old_online} <- @@ -394,8 +408,7 @@ defmodule WandererApp.Map.Server.CharactersImpl do {:ok, old_structure_id} = WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:structure_id") - {:ok, - %{solar_system_id: solar_system_id, structure_id: structure_id, station_id: station_id}} = + {:ok, %{solar_system_id: solar_system_id, structure_id: structure_id, station_id: station_id}} = WandererApp.Character.get_character(character_id) WandererApp.Cache.insert( @@ -413,14 +426,15 @@ defmodule WandererApp.Map.Server.CharactersImpl do structure_id ) - if solar_system_id != old_solar_system_id || structure_id != old_structure_id || station_id != old_station_id do + if solar_system_id != old_solar_system_id || structure_id != old_structure_id || + station_id != old_station_id do [ {:character_location, - %{ - solar_system_id: solar_system_id, - structure_id: structure_id, - station_id: station_id - }, %{solar_system_id: old_solar_system_id}} + %{ + solar_system_id: solar_system_id, + structure_id: structure_id, + station_id: station_id + }, %{solar_system_id: old_solar_system_id}} ] else [:skip] diff --git a/lib/wanderer_app/map/server/map_server_impl.ex b/lib/wanderer_app/map/server/map_server_impl.ex index 2a8ca6e2..094b9109 100644 --- a/lib/wanderer_app/map/server/map_server_impl.ex +++ b/lib/wanderer_app/map/server/map_server_impl.ex @@ -451,14 +451,6 @@ defmodule WandererApp.Map.Server.Impl do |> WandererApp.Map.update_subscription_settings!(subscription_settings) |> WandererApp.Map.add_systems!(systems) |> WandererApp.Map.add_connections!(connections) - |> WandererApp.Map.add_characters!(characters) - - character_ids = - map_id - |> WandererApp.Map.get_map!() - |> Map.get(:characters, []) - - WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids) %{state | map: map, map_opts: map_options(options)} end diff --git a/lib/wanderer_app/repositories/map_character_settings_repo.ex b/lib/wanderer_app/repositories/map_character_settings_repo.ex index 26c1f598..a37c0414 100644 --- a/lib/wanderer_app/repositories/map_character_settings_repo.ex +++ b/lib/wanderer_app/repositories/map_character_settings_repo.ex @@ -1,8 +1,9 @@ defmodule WandererApp.MapCharacterSettingsRepo do use WandererApp, :repository - def create(settings), - do: WandererApp.Api.MapCharacterSettings.create(settings) + def create(settings) do + WandererApp.Api.MapCharacterSettings.create(settings) + end def get_tracked_by_map_filtered(map_id, character_ids), do: diff --git a/lib/wanderer_app_web/live/characters/characters_tracking_live.ex b/lib/wanderer_app_web/live/characters/characters_tracking_live.ex index ecf484dc..bb7022a7 100755 --- a/lib/wanderer_app_web/live/characters/characters_tracking_live.ex +++ b/lib/wanderer_app_web/live/characters/characters_tracking_live.ex @@ -91,6 +91,8 @@ defmodule WandererAppWeb.CharactersTrackingLive do character_setting |> WandererApp.MapCharacterSettingsRepo.untrack!() + WandererApp.Map.Server.untrack_characters(selected_map.id, [character_setting.character_id]) + _ -> character_setting |> WandererApp.MapCharacterSettingsRepo.track!() 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 5f192394..69b64df4 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 @@ -32,6 +32,16 @@ defmodule WandererAppWeb.MapCharactersEventHandler do ) end + def handle_server_event(%{event: :untrack_character, payload: character_id}, %{ + assigns: %{ + map_id: map_id + } + } = socket) do + :ok = WandererApp.Character.TrackingUtils.untrack([%{id: character_id}], map_id, self()) + socket + end + + def handle_server_event( %{event: :characters_updated}, %{ @@ -342,9 +352,6 @@ defmodule WandererAppWeb.MapCharactersEventHandler do self() ) - :ok = - WandererApp.Character.TrackingUtils.add_characters(map_characters, map_id, track_character) - socket 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 ad49c239..f8612165 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 @@ -57,7 +57,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do case track_character do false -> :ok = WandererApp.Character.TrackingUtils.untrack(map_characters, map_id, self()) - :ok = WandererApp.Character.TrackingUtils.remove_characters(map_characters, map_id) _ -> :ok = @@ -67,13 +66,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do true, self() ) - - :ok = - WandererApp.Character.TrackingUtils.add_characters( - map_characters, - map_id, - track_character - ) end socket diff --git a/lib/wanderer_app_web/live/map/map_characters_live.ex b/lib/wanderer_app_web/live/map/map_characters_live.ex index 69b8acc8..4ed38963 100755 --- a/lib/wanderer_app_web/live/map/map_characters_live.ex +++ b/lib/wanderer_app_web/live/map/map_characters_live.ex @@ -84,11 +84,7 @@ defmodule WandererAppWeb.MapCharactersLive do character_setting -> case character_setting.tracked do true -> - {:ok, map_character_settings} = - character_setting - |> WandererApp.MapCharacterSettingsRepo.untrack() - - WandererApp.Map.Server.remove_character(map_id, map_character_settings.character_id) + WandererApp.Map.Server.untrack_characters(map_id, [character_setting.character_id]) socket |> put_flash(:info, "Character untracked!") |> load_characters() 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 1b8f94c1..7b9d3983 100644 --- a/lib/wanderer_app_web/live/map/map_event_handler.ex +++ b/lib/wanderer_app_web/live/map/map_event_handler.ex @@ -23,7 +23,8 @@ defmodule WandererAppWeb.MapEventHandler do :characters_updated, :present_characters_updated, :refresh_user_characters, - :show_tracking + :show_tracking, + :untrack_character ] @map_characters_ui_events [ From 2b7abe57740191222c77fbd7b60a89da725ceff5 Mon Sep 17 00:00:00 2001 From: CI Date: Mon, 26 May 2025 00:11:32 +0000 Subject: [PATCH 12/14] chore: release version v1.65.5 --- CHANGELOG.md | 11 +++++++++++ mix.exs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 924edff7..33b362f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ +## [v1.65.5](https://github.com/wanderer-industries/wanderer/compare/v1.65.4...v1.65.5) (2025-05-26) + + + + +### Bug Fixes: + +* Core: Fixed map character tracking issues + +* Signature: Update restored signature character + ## [v1.65.4](https://github.com/wanderer-industries/wanderer/compare/v1.65.3...v1.65.4) (2025-05-24) diff --git a/mix.exs b/mix.exs index c9841709..c79aa122 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.4" + @version "1.65.5" def project do [ From a298152bc8d54ddff52f80326eaee49f61aa783a Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Mon, 26 May 2025 12:09:09 +0200 Subject: [PATCH 13/14] fix(Core): Fixed map character tracking issues --- .../api/map_character_settings.ex | 59 ++++- lib/wanderer_app/character.ex | 60 ++++- .../character/tracker_manager_impl.ex | 14 +- lib/wanderer_app/map.ex | 2 +- .../map/server/map_server_characters_impl.ex | 33 ++- .../map/server/map_server_impl.ex | 8 + .../map_character_settings_repo.ex | 24 ++ ...074425_add_map_character_tracking_info.exs | 31 +++ .../20250526074425.json | 206 ++++++++++++++++++ 9 files changed, 419 insertions(+), 18 deletions(-) create mode 100644 priv/repo/migrations/20250526074425_add_map_character_tracking_info.exs create mode 100644 priv/resource_snapshots/repo/map_character_settings_v1/20250526074425.json diff --git a/lib/wanderer_app/api/map_character_settings.ex b/lib/wanderer_app/api/map_character_settings.ex index 099e9e2a..2bd0a82d 100644 --- a/lib/wanderer_app/api/map_character_settings.ex +++ b/lib/wanderer_app/api/map_character_settings.ex @@ -3,7 +3,8 @@ defmodule WandererApp.Api.MapCharacterSettings do use Ash.Resource, domain: WandererApp.Api, - data_layer: AshPostgres.DataLayer + data_layer: AshPostgres.DataLayer, + extensions: [AshCloak] @derive {Jason.Encoder, only: [ @@ -24,8 +25,10 @@ defmodule WandererApp.Api.MapCharacterSettings do code_interface do define(:create, action: :create) define(:destroy, action: :destroy) + define(:update, action: :update) define(:read_by_map, action: :read_by_map) + define(:read_by_map_and_character, action: :read_by_map_and_character) 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) @@ -45,7 +48,7 @@ defmodule WandererApp.Api.MapCharacterSettings do :tracked ] - defaults [:read, :update, :destroy] + defaults [:read, :destroy] create :create do primary? true @@ -92,6 +95,15 @@ defmodule WandererApp.Api.MapCharacterSettings do filter(expr(map_id == ^arg(:map_id))) end + read :read_by_map_and_character do + get? true + + argument(:map_id, :string, allow_nil?: false) + argument(:character_id, :uuid, allow_nil?: false) + + filter(expr(map_id == ^arg(:map_id) and character_id == ^arg(:character_id))) + end + read :tracked_by_map_all do argument(:map_id, :string, allow_nil?: false) filter(expr(map_id == ^arg(:map_id) and tracked == true)) @@ -102,6 +114,20 @@ defmodule WandererApp.Api.MapCharacterSettings do filter(expr(character_id == ^arg(:character_id) and tracked == true)) end + update :update do + primary? true + require_atomic? false + + accept([ + :ship, + :ship_name, + :ship_item_id, + :solar_system_id, + :structure_id, + :station_id + ]) + end + update :track do accept [:map_id, :character_id] argument :map_id, :string, allow_nil?: false @@ -159,6 +185,28 @@ defmodule WandererApp.Api.MapCharacterSettings do end end + cloak do + vault(WandererApp.Vault) + + attributes([ + :ship, + :ship_name, + :ship_item_id, + :solar_system_id, + :structure_id, + :station_id + ]) + + decrypt_by_default([ + :ship, + :ship_name, + :ship_item_id, + :solar_system_id, + :structure_id, + :station_id + ]) + end + attributes do uuid_primary_key :id @@ -172,6 +220,13 @@ defmodule WandererApp.Api.MapCharacterSettings do allow_nil? true end + attribute :solar_system_id, :integer + attribute :structure_id, :integer + attribute :station_id, :integer + attribute :ship, :integer + attribute :ship_name, :string + attribute :ship_item_id, :integer + create_timestamp(:inserted_at) update_timestamp(:updated_at) end diff --git a/lib/wanderer_app/character.ex b/lib/wanderer_app/character.ex index c36ada5b..8cb1868f 100644 --- a/lib/wanderer_app/character.ex +++ b/lib/wanderer_app/character.ex @@ -7,6 +7,15 @@ defmodule WandererApp.Character do @read_character_wallet_scope "esi-wallet.read_character_wallet.v1" @read_corp_wallet_scope "esi-wallet.read_corporation_wallets.v1" + @default_character_tracking_data %{ + solar_system_id: nil, + structure_id: nil, + station_id: nil, + ship: nil, + ship_name: nil, + ship_item_id: nil + } + @decorate cacheable( cache: WandererApp.Cache, key: "characters-#{character_eve_id}" @@ -45,6 +54,32 @@ defmodule WandererApp.Character do end end + def get_map_character(map_id, character_id) do + case get_character(character_id) do + {:ok, character} -> + {:ok, + character + |> maybe_merge_map_character_settings( + map_id, + WandererApp.Character.TrackerManager.Impl.character_is_present(map_id, character_id) + )} + + _ -> + {:ok, nil} + end + end + + def get_map_character!(map_id, character_id) do + case get_map_character(map_id, character_id) do + {:ok, character} -> + character + + _ -> + Logger.error("Failed to get map character #{map_id} #{character_id}") + nil + end + end + def get_character_eve_ids!(character_ids), do: character_ids @@ -146,7 +181,7 @@ defmodule WandererApp.Character do params: opts[:params] ) do {:ok, result} -> - {:ok, result |> _prepare_search_results()} + {:ok, result |> prepare_search_results()} {:error, error} -> Logger.warning("#{__MODULE__} failed search: #{inspect(error)}") @@ -208,7 +243,28 @@ defmodule WandererApp.Character do end end - defp _prepare_search_results(result) do + defp maybe_merge_map_character_settings(character, map_id, true), do: character + + defp maybe_merge_map_character_settings( + %{id: character_id} = character, + map_id, + _character_is_present + ) do + WandererApp.MapCharacterSettingsRepo.get(map_id, character_id) + |> case do + {:ok, settings} when not is_nil(settings) -> + character + |> Map.put(:online, false) + |> Map.merge(settings) + + _ -> + character + |> Map.put(:online, false) + |> Map.merge(@default_character_tracking_data) + end + end + + defp prepare_search_results(result) do {:ok, characters} = _load_eve_info(Map.get(result, "character"), :get_character_info, &_map_character_info/1) diff --git a/lib/wanderer_app/character/tracker_manager_impl.ex b/lib/wanderer_app/character/tracker_manager_impl.ex index 36195e12..2bdb8165 100644 --- a/lib/wanderer_app/character/tracker_manager_impl.ex +++ b/lib/wanderer_app/character/tracker_manager_impl.ex @@ -220,6 +220,18 @@ defmodule WandererApp.Character.TrackerManager.Impl do track: false }) + {:ok, character} = WandererApp.Character.get_character(character_id) + + {:ok, _updated} = + WandererApp.MapCharacterSettingsRepo.update(map_id, character_id, %{ + ship: character.ship, + ship_name: character.ship_name, + ship_item_id: character.ship_item_id, + solar_system_id: character.solar_system_id, + structure_id: character.structure_id, + station_id: character.station_id + }) + WandererApp.Character.update_character_state(character_id, character_state) end end, @@ -246,7 +258,7 @@ defmodule WandererApp.Character.TrackerManager.Impl do def handle_info(_event, state), do: state - defp character_is_present(map_id, character_id) do + def character_is_present(map_id, character_id) do {:ok, presence_character_ids} = WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", []) diff --git a/lib/wanderer_app/map.ex b/lib/wanderer_app/map.ex index aca75a48..d4c0fb73 100644 --- a/lib/wanderer_app/map.ex +++ b/lib/wanderer_app/map.ex @@ -96,7 +96,7 @@ defmodule WandererApp.Map do map_id |> get_map!() |> Map.get(:characters, []) - |> Enum.map(&WandererApp.Character.get_character!(&1)) + |> Enum.map(fn character_id -> WandererApp.Character.get_map_character!(map_id, character_id) end) def list_systems(map_id), do: {:ok, map_id |> get_map!() |> Map.get(:systems, Map.new()) |> Map.values()} 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 07891cca..f5fee5c1 100644 --- a/lib/wanderer_app/map/server/map_server_characters_impl.ex +++ b/lib/wanderer_app/map/server/map_server_characters_impl.ex @@ -17,13 +17,13 @@ defmodule WandererApp.Map.Server.CharactersImpl do map_id: map_id, tracked: track_character }), - {:ok, character} <- WandererApp.Character.get_character(character_id) do + {:ok, character} <- WandererApp.Character.get_map_character(map_id, character_id) do Impl.broadcast!(map_id, :character_added, character) :telemetry.execute([:wanderer_app, :map, :character, :added], %{count: 1}) :ok else _error -> - {:ok, character} = WandererApp.Character.get_character(character_id) + {:ok, character} = WandererApp.Character.get_map_character(map_id, character_id) Impl.broadcast!(map_id, :character_added, character) :ok end @@ -35,7 +35,7 @@ defmodule WandererApp.Map.Server.CharactersImpl do def remove_character(map_id, character_id) do Task.start_link(fn -> with :ok <- WandererApp.Map.remove_character(map_id, character_id), - {:ok, character} <- WandererApp.Character.get_character(character_id) do + {:ok, character} <- WandererApp.Character.get_map_character(map_id, character_id) do Impl.broadcast!(map_id, :character_removed, character) :telemetry.execute([:wanderer_app, :map, :character, :removed], %{count: 1}) @@ -90,17 +90,26 @@ defmodule WandererApp.Map.Server.CharactersImpl do do: character_ids |> Enum.each(fn character_id -> - # TODO consider storing character data in MapCharacterSettings - # remove_character(map_id, character_id) + if is_character_map_active?(map_id, character_id) do + WandererApp.Character.TrackerManager.update_track_settings(character_id, %{ + map_id: map_id, + track: false + }) - WandererApp.Character.TrackerManager.update_track_settings(character_id, %{ - map_id: map_id, - track: false - }) - - Impl.broadcast!(map_id, :untrack_character, character_id) + Impl.broadcast!(map_id, :untrack_character, character_id) + end end) + def is_character_map_active?(map_id, character_id) do + case WandererApp.Character.get_character_state(character_id) do + {:ok, %{active_maps: active_maps}} -> + map_id in active_maps + + _ -> + false + end + end + def cleanup_characters(map_id, owner_id) do {:ok, invalidate_character_ids} = WandererApp.Cache.lookup( @@ -276,7 +285,7 @@ defmodule WandererApp.Map.Server.CharactersImpl do end defp update_character(map_id, character_id) do - {:ok, character} = WandererApp.Character.get_character(character_id) + {:ok, character} = WandererApp.Character.get_map_character(map_id, character_id) Impl.broadcast!(map_id, :character_updated, character) end diff --git a/lib/wanderer_app/map/server/map_server_impl.ex b/lib/wanderer_app/map/server/map_server_impl.ex index 094b9109..2a8ca6e2 100644 --- a/lib/wanderer_app/map/server/map_server_impl.ex +++ b/lib/wanderer_app/map/server/map_server_impl.ex @@ -451,6 +451,14 @@ defmodule WandererApp.Map.Server.Impl do |> WandererApp.Map.update_subscription_settings!(subscription_settings) |> WandererApp.Map.add_systems!(systems) |> WandererApp.Map.add_connections!(connections) + |> WandererApp.Map.add_characters!(characters) + + character_ids = + map_id + |> WandererApp.Map.get_map!() + |> Map.get(:characters, []) + + WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids) %{state | map: map, map_opts: map_options(options)} end diff --git a/lib/wanderer_app/repositories/map_character_settings_repo.ex b/lib/wanderer_app/repositories/map_character_settings_repo.ex index a37c0414..d26688ce 100644 --- a/lib/wanderer_app/repositories/map_character_settings_repo.ex +++ b/lib/wanderer_app/repositories/map_character_settings_repo.ex @@ -1,10 +1,34 @@ defmodule WandererApp.MapCharacterSettingsRepo do use WandererApp, :repository + def get(map_id, character_id) do + case WandererApp.Api.MapCharacterSettings.read_by_map_and_character(%{ + map_id: map_id, + character_id: character_id + }) do + {:ok, settings} -> + {:ok, settings} + + {:error, reason} -> + {:ok, nil} + end + end + def create(settings) do WandererApp.Api.MapCharacterSettings.create(settings) end + def update(map_id, character_id, updated_settings) do + case get(map_id, character_id) do + {:ok, settings} when not is_nil(settings) -> + settings + |> WandererApp.Api.MapCharacterSettings.update(updated_settings) + + {:error, reason} -> + {:ok, nil} + end + end + def get_tracked_by_map_filtered(map_id, character_ids), do: WandererApp.Api.MapCharacterSettings.tracked_by_map_filtered(%{ diff --git a/priv/repo/migrations/20250526074425_add_map_character_tracking_info.exs b/priv/repo/migrations/20250526074425_add_map_character_tracking_info.exs new file mode 100644 index 00000000..f7922990 --- /dev/null +++ b/priv/repo/migrations/20250526074425_add_map_character_tracking_info.exs @@ -0,0 +1,31 @@ +defmodule WandererApp.Repo.Migrations.AddMapCharacterTrackingInfo do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + alter table(:map_character_settings_v1) do + add :encrypted_ship, :binary + add :encrypted_ship_name, :binary + add :encrypted_ship_item_id, :binary + add :encrypted_solar_system_id, :binary + add :encrypted_structure_id, :binary + add :encrypted_station_id, :binary + end + end + + def down do + alter table(:map_character_settings_v1) do + remove :encrypted_station_id + remove :encrypted_structure_id + remove :encrypted_solar_system_id + remove :encrypted_ship_item_id + remove :encrypted_ship_name + remove :encrypted_ship + end + end +end diff --git a/priv/resource_snapshots/repo/map_character_settings_v1/20250526074425.json b/priv/resource_snapshots/repo/map_character_settings_v1/20250526074425.json new file mode 100644 index 00000000..b49345c1 --- /dev/null +++ b/priv/resource_snapshots/repo/map_character_settings_v1/20250526074425.json @@ -0,0 +1,206 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": true, + "default": "false", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "tracked", + "type": "boolean" + }, + { + "allow_nil?": true, + "default": "false", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "followed", + "type": "boolean" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": true, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "map_character_settings_v1_map_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "maps_v1" + }, + "size": null, + "source": "map_id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": true, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "map_character_settings_v1_character_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "character_v1" + }, + "size": null, + "source": "character_id", + "type": "uuid" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_ship", + "type": "binary" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_ship_name", + "type": "binary" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_ship_item_id", + "type": "binary" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_solar_system_id", + "type": "binary" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_structure_id", + "type": "binary" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "encrypted_station_id", + "type": "binary" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "3F585D1C545A5264AEFA05502C0F625F9B27B15CA36699DCF37E4F834E6339AE", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "map_character_settings_v1_uniq_map_character_index", + "keys": [ + { + "type": "atom", + "value": "map_id" + }, + { + "type": "atom", + "value": "character_id" + } + ], + "name": "uniq_map_character", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.WandererApp.Repo", + "schema": null, + "table": "map_character_settings_v1" +} \ No newline at end of file From 92a9274dce82345762e460e302016e31f44f62ab Mon Sep 17 00:00:00 2001 From: CI Date: Mon, 26 May 2025 10:19:27 +0000 Subject: [PATCH 14/14] chore: release version v1.65.6 --- CHANGELOG.md | 9 +++++++++ mix.exs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33b362f3..bd78f737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ +## [v1.65.6](https://github.com/wanderer-industries/wanderer/compare/v1.65.5...v1.65.6) (2025-05-26) + + + + +### Bug Fixes: + +* Core: Fixed map character tracking issues + ## [v1.65.5](https://github.com/wanderer-industries/wanderer/compare/v1.65.4...v1.65.5) (2025-05-26) diff --git a/mix.exs b/mix.exs index c79aa122..6ab84f7c 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do @source_url "https://github.com/wanderer-industries/wanderer" - @version "1.65.5" + @version "1.65.6" def project do [