mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-10 09:45:43 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbadfc4ac4 | ||
|
|
3d88ae4452 | ||
|
|
6d99c54af7 | ||
|
|
2b7901e9a8 | ||
|
|
fb06dd1dbc | ||
|
|
f8ba36b8be | ||
|
|
5bf9d99b3d | ||
|
|
7cad05342a |
27
CHANGELOG.md
27
CHANGELOG.md
@@ -2,6 +2,33 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.62.4](https://github.com/wanderer-industries/wanderer/compare/v1.62.3...v1.62.4) (2025-05-10)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed map characters got untracked
|
||||
|
||||
## [v1.62.3](https://github.com/wanderer-industries/wanderer/compare/v1.62.2...v1.62.3) (2025-05-08)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed map characters got untracked
|
||||
|
||||
## [v1.62.2](https://github.com/wanderer-industries/wanderer/compare/v1.62.1...v1.62.2) (2025-05-05)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed audit export API
|
||||
|
||||
## [v1.62.1](https://github.com/wanderer-industries/wanderer/compare/v1.62.0...v1.62.1) (2025-05-05)
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ defmodule WandererApp.Character.Tracker do
|
||||
status: binary()
|
||||
}
|
||||
|
||||
@online_error_timeout :timer.minutes(2)
|
||||
@online_error_timeout :timer.minutes(5)
|
||||
@forbidden_ttl :timer.minutes(1)
|
||||
@pubsub_client Application.compile_env(:wanderer_app, :pubsub_client)
|
||||
|
||||
@@ -49,7 +49,7 @@ defmodule WandererApp.Character.Tracker do
|
||||
|> new()
|
||||
end
|
||||
|
||||
def update_track_settings(character_id, track_settings) do
|
||||
def update_settings(character_id, track_settings) do
|
||||
{:ok, character_state} = WandererApp.Character.get_character_state(character_id)
|
||||
|
||||
{:ok,
|
||||
@@ -494,7 +494,7 @@ defmodule WandererApp.Character.Tracker do
|
||||
state,
|
||||
location
|
||||
) do
|
||||
location = get_location(location)
|
||||
location = get_location(location)
|
||||
|
||||
if not is_location_started?(character_id) do
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:start_solar_system_id", nil)
|
||||
@@ -544,14 +544,18 @@ defmodule WandererApp.Character.Tracker do
|
||||
)
|
||||
|
||||
defp is_location_updated?(
|
||||
%{solar_system_id: new_solar_system_id, station_id: new_station_id, structure_id: new_structure_id} = _location,
|
||||
%{
|
||||
solar_system_id: new_solar_system_id,
|
||||
station_id: new_station_id,
|
||||
structure_id: new_structure_id
|
||||
} = _location,
|
||||
solar_system_id,
|
||||
structure_id,
|
||||
station_id
|
||||
),
|
||||
do:
|
||||
solar_system_id != new_solar_system_id ||
|
||||
solar_system_id != new_solar_system_id ||
|
||||
solar_system_id != new_solar_system_id ||
|
||||
structure_id != new_structure_id ||
|
||||
station_id != new_station_id
|
||||
|
||||
@@ -724,14 +728,7 @@ defmodule WandererApp.Character.Tracker do
|
||||
)
|
||||
end
|
||||
|
||||
WandererApp.Character.update_character(character_id, %{online: false})
|
||||
|
||||
%{
|
||||
state
|
||||
| track_ship: false,
|
||||
track_online: false,
|
||||
track_location: false
|
||||
}
|
||||
state
|
||||
end
|
||||
|
||||
defp maybe_stop_tracking(
|
||||
|
||||
@@ -31,9 +31,7 @@ defmodule WandererApp.Character.TrackerManager do
|
||||
def init(args) do
|
||||
Logger.info("#{__MODULE__} started")
|
||||
|
||||
{:ok, tracked_characters} = WandererApp.Cache.lookup("tracked_characters", [])
|
||||
|
||||
{:ok, Impl.init(args |> Keyword.merge(characters: tracked_characters)), {:continue, :start}}
|
||||
{:ok, Impl.init(args), {:continue, :start}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
||||
@@ -32,71 +32,65 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
|> new()
|
||||
end
|
||||
|
||||
def start(%{opts: opts} = state) do
|
||||
opts[:characters]
|
||||
|> Enum.reduce(state, fn character_id, acc ->
|
||||
start_tracking(acc, character_id, %{})
|
||||
def start(state) do
|
||||
{:ok, tracked_characters} = WandererApp.Cache.lookup("tracked_characters", [])
|
||||
|
||||
tracked_characters
|
||||
|> Enum.each(fn character_id ->
|
||||
start_tracking(state, character_id, %{})
|
||||
end)
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def start_tracking(%__MODULE__{characters: characters} = state, character_id, opts) do
|
||||
case Enum.member?(characters, character_id) do
|
||||
true ->
|
||||
state
|
||||
def start_tracking(state, character_id, opts) do
|
||||
with {:ok, characters} <- WandererApp.Cache.lookup("tracked_characters", []),
|
||||
false <- Enum.member?(characters, character_id) do
|
||||
Logger.debug(fn -> "Start character tracker: #{inspect(character_id)}" end)
|
||||
|
||||
false ->
|
||||
Logger.debug(fn -> "Start character tracker: #{inspect(character_id)}" end)
|
||||
tracked_characters = [character_id | characters] |> Enum.uniq()
|
||||
WandererApp.Cache.insert("tracked_characters", tracked_characters)
|
||||
|
||||
WandererApp.TaskWrapper.start_link(WandererApp.Character, :update_character_state, [
|
||||
character_id,
|
||||
%{opts: opts}
|
||||
])
|
||||
WandererApp.Character.TrackerPoolDynamicSupervisor.start_tracking(character_id)
|
||||
|
||||
tracked_characters = [character_id | state.characters] |> Enum.uniq()
|
||||
WandererApp.Cache.insert("tracked_characters", tracked_characters)
|
||||
|
||||
WandererApp.Character.TrackerPoolDynamicSupervisor.start_tracking(character_id)
|
||||
|
||||
%{state | characters: tracked_characters}
|
||||
WandererApp.TaskWrapper.start_link(WandererApp.Character, :update_character_state, [
|
||||
character_id,
|
||||
%{opts: opts}
|
||||
])
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def stop_tracking(%__MODULE__{characters: characters} = state, character_id) do
|
||||
case Enum.member?(characters, character_id) do
|
||||
true ->
|
||||
{:ok, character_state} = WandererApp.Character.get_character_state(character_id, false)
|
||||
def stop_tracking(state, character_id) do
|
||||
with {:ok, characters} <- WandererApp.Cache.lookup("tracked_characters", []),
|
||||
true <- Enum.member?(characters, character_id),
|
||||
{:ok, %{start_time: start_time}} <-
|
||||
WandererApp.Character.get_character_state(character_id, false) do
|
||||
Logger.debug(fn -> "Shutting down character tracker: #{inspect(character_id)}" end)
|
||||
|
||||
case character_state do
|
||||
nil ->
|
||||
state
|
||||
WandererApp.Cache.delete("character:#{character_id}:last_active_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:location_started")
|
||||
WandererApp.Cache.delete("character:#{character_id}:start_solar_system_id")
|
||||
WandererApp.Character.delete_character_state(character_id)
|
||||
|
||||
%{start_time: start_time} ->
|
||||
duration = DateTime.diff(DateTime.utc_now(), start_time, :second)
|
||||
tracked_characters =
|
||||
characters |> Enum.reject(fn c_id -> c_id == character_id end)
|
||||
|
||||
:telemetry.execute([:wanderer_app, :character, :tracker, :running], %{
|
||||
duration: duration
|
||||
})
|
||||
WandererApp.Cache.insert("tracked_characters", tracked_characters)
|
||||
|
||||
:telemetry.execute([:wanderer_app, :character, :tracker, :stopped], %{count: 1})
|
||||
Logger.debug(fn -> "Shutting down character tracker: #{inspect(character_id)}" end)
|
||||
WandererApp.Character.TrackerPoolDynamicSupervisor.stop_tracking(character_id)
|
||||
|
||||
WandererApp.Cache.delete("character:#{character_id}:location_started")
|
||||
WandererApp.Cache.delete("character:#{character_id}:start_solar_system_id")
|
||||
WandererApp.Character.delete_character_state(character_id)
|
||||
duration = DateTime.diff(DateTime.utc_now(), start_time, :second)
|
||||
|
||||
tracked_characters =
|
||||
state.characters |> Enum.reject(fn c_id -> c_id == character_id end)
|
||||
:telemetry.execute([:wanderer_app, :character, :tracker, :running], %{
|
||||
duration: duration
|
||||
})
|
||||
|
||||
WandererApp.Cache.insert("tracked_characters", tracked_characters)
|
||||
|
||||
WandererApp.Character.TrackerPoolDynamicSupervisor.stop_tracking(character_id)
|
||||
|
||||
%{state | characters: tracked_characters}
|
||||
end
|
||||
|
||||
false ->
|
||||
state
|
||||
:telemetry.execute([:wanderer_app, :character, :tracker, :stopped], %{count: 1})
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def update_track_settings(
|
||||
@@ -118,7 +112,7 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
)
|
||||
|
||||
{:ok, character_state} =
|
||||
WandererApp.Character.Tracker.update_track_settings(character_id, track_settings)
|
||||
WandererApp.Character.Tracker.update_settings(character_id, track_settings)
|
||||
|
||||
WandererApp.Character.update_character_state(character_id, character_state)
|
||||
else
|
||||
@@ -135,12 +129,12 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
end
|
||||
|
||||
def get_characters(
|
||||
%{
|
||||
characters: characters
|
||||
} = state,
|
||||
state,
|
||||
_opts \\ []
|
||||
),
|
||||
do: {characters, state}
|
||||
) do
|
||||
{:ok, characters} = WandererApp.Cache.lookup("tracked_characters", [])
|
||||
{characters, state}
|
||||
end
|
||||
|
||||
def handle_event({ref, result}, state) do
|
||||
Process.demonitor(ref, [:flush])
|
||||
@@ -163,13 +157,12 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
|
||||
def handle_info(
|
||||
:garbage_collect,
|
||||
%{
|
||||
characters: characters
|
||||
} =
|
||||
state
|
||||
state
|
||||
) do
|
||||
Process.send_after(self(), :garbage_collect, @garbage_collection_interval)
|
||||
|
||||
{:ok, characters} = WandererApp.Cache.lookup("tracked_characters", [])
|
||||
|
||||
characters
|
||||
|> Task.async_stream(
|
||||
fn character_id ->
|
||||
@@ -213,15 +206,15 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
WandererApp.Cache.get_and_remove!("character_untrack_queue", [])
|
||||
|> Task.async_stream(
|
||||
fn {map_id, character_id} ->
|
||||
WandererApp.Cache.delete("map_#{map_id}:character_#{character_id}:tracked")
|
||||
if not character_is_present(map_id, character_id) do
|
||||
{:ok, character_state} =
|
||||
WandererApp.Character.Tracker.update_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: false
|
||||
})
|
||||
|
||||
{:ok, character_state} =
|
||||
WandererApp.Character.Tracker.update_track_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: false
|
||||
})
|
||||
|
||||
WandererApp.Character.update_character_state(character_id, character_state)
|
||||
WandererApp.Character.update_character_state(character_id, character_state)
|
||||
end
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
on_timeout: :kill_task,
|
||||
@@ -233,21 +226,23 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
end
|
||||
|
||||
def handle_info({:stop_track, character_id}, state) do
|
||||
WandererApp.Cache.has_key?("character:#{character_id}:is_stop_tracking")
|
||||
|> case do
|
||||
false ->
|
||||
WandererApp.Cache.insert("character:#{character_id}:is_stop_tracking", true)
|
||||
Logger.debug(fn -> "Stopping character tracker: #{inspect(character_id)}" end)
|
||||
state = state |> stop_tracking(character_id)
|
||||
WandererApp.Cache.delete("character:#{character_id}:is_stop_tracking")
|
||||
|
||||
state
|
||||
|
||||
_ ->
|
||||
state
|
||||
if not WandererApp.Cache.has_key?("character:#{character_id}:is_stop_tracking") do
|
||||
WandererApp.Cache.insert("character:#{character_id}:is_stop_tracking", true)
|
||||
Logger.debug(fn -> "Stopping character tracker: #{inspect(character_id)}" end)
|
||||
stop_tracking(state, character_id)
|
||||
WandererApp.Cache.delete("character:#{character_id}:is_stop_tracking")
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def handle_info(_event, state),
|
||||
do: state
|
||||
|
||||
defp character_is_present(map_id, character_id) do
|
||||
{:ok, presence_character_ids} =
|
||||
WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", [])
|
||||
|
||||
Enum.member?(presence_character_ids, character_id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -167,10 +167,18 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
|
||||
def handle_info(
|
||||
:update_online,
|
||||
state
|
||||
%{
|
||||
characters: characters
|
||||
} =
|
||||
state
|
||||
) do
|
||||
Process.send_after(self(), :update_online, @update_online_interval)
|
||||
|
||||
characters
|
||||
|> Enum.each(fn character_id ->
|
||||
WandererApp.Character.update_character(character_id, %{online: false})
|
||||
end)
|
||||
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ defmodule WandererApp.Character.TrackingUtils do
|
||||
{:ok, updated_settings} =
|
||||
WandererApp.MapCharacterSettingsRepo.untrack(existing_settings)
|
||||
|
||||
:ok = untrack_characters([character], map_id, caller_pid)
|
||||
:ok = untrack([character], map_id, caller_pid)
|
||||
:ok = remove_characters([character], map_id)
|
||||
{:ok, updated_settings}
|
||||
else
|
||||
@@ -131,7 +131,7 @@ defmodule WandererApp.Character.TrackingUtils do
|
||||
{:ok, %{tracked: false} = existing_settings} ->
|
||||
if track do
|
||||
{:ok, updated_settings} = WandererApp.MapCharacterSettingsRepo.track(existing_settings)
|
||||
:ok = track_characters([character], map_id, true, caller_pid)
|
||||
:ok = track([character], map_id, true, caller_pid)
|
||||
:ok = add_characters([character], map_id, true)
|
||||
{:ok, updated_settings}
|
||||
else
|
||||
@@ -148,7 +148,7 @@ defmodule WandererApp.Character.TrackingUtils do
|
||||
tracked: true
|
||||
})
|
||||
|
||||
:ok = track_characters([character], map_id, true, caller_pid)
|
||||
:ok = track([character], map_id, true, caller_pid)
|
||||
:ok = add_characters([character], map_id, true)
|
||||
{:ok, settings}
|
||||
else
|
||||
@@ -161,25 +161,23 @@ defmodule WandererApp.Character.TrackingUtils do
|
||||
end
|
||||
|
||||
# Helper functions for character tracking
|
||||
def track_characters(_, _, false, _), do: :ok
|
||||
def track_characters([], _map_id, _is_track_character?, _), do: :ok
|
||||
def track(_, _, false, _), do: :ok
|
||||
def track([], _map_id, _is_track_character?, _), do: :ok
|
||||
|
||||
def track_characters([character | characters], map_id, true, caller_pid) do
|
||||
def track([character | characters], map_id, true, caller_pid) do
|
||||
with :ok <- track_character(character, map_id, caller_pid) do
|
||||
track_characters(characters, map_id, true, caller_pid)
|
||||
track(characters, map_id, true, caller_pid)
|
||||
end
|
||||
end
|
||||
|
||||
def track_character(
|
||||
%{
|
||||
id: character_id,
|
||||
eve_id: eve_id,
|
||||
corporation_id: corporation_id,
|
||||
alliance_id: alliance_id
|
||||
},
|
||||
map_id,
|
||||
caller_pid
|
||||
) do
|
||||
defp track_character(
|
||||
%{
|
||||
id: character_id,
|
||||
eve_id: eve_id
|
||||
},
|
||||
map_id,
|
||||
caller_pid
|
||||
) do
|
||||
with false <- is_nil(caller_pid) do
|
||||
WandererAppWeb.Presence.track(caller_pid, map_id, character_id, %{})
|
||||
|
||||
@@ -202,20 +200,17 @@ defmodule WandererApp.Character.TrackingUtils do
|
||||
end
|
||||
end
|
||||
|
||||
def untrack_characters(characters, map_id, caller_pid) do
|
||||
def untrack(characters, map_id, caller_pid) do
|
||||
with false <- is_nil(caller_pid) do
|
||||
character_ids = characters |> Enum.map(& &1.id)
|
||||
|
||||
characters
|
||||
|> Enum.each(fn character ->
|
||||
WandererAppWeb.Presence.untrack(caller_pid, map_id, character.id)
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"#{inspect(caller_pid)}_map_#{map_id}:character_#{character.id}:tracked",
|
||||
false
|
||||
)
|
||||
|
||||
:ok = Phoenix.PubSub.unsubscribe(WandererApp.PubSub, "character:#{character.eve_id}")
|
||||
end)
|
||||
|
||||
WandererApp.Map.Server.untrack_characters(map_id, character_ids)
|
||||
|
||||
:ok
|
||||
else
|
||||
true ->
|
||||
|
||||
@@ -32,7 +32,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
}
|
||||
|
||||
@cache_opts [cache: true]
|
||||
@retry_opts [max_retries: 1, retry_log_level: :warning]
|
||||
@retry_opts [max_retries: 0, retry_log_level: :warning]
|
||||
@timeout_opts [pool_timeout: 15_000, receive_timeout: :timer.seconds(30)]
|
||||
@api_retry_count 1
|
||||
|
||||
@@ -490,7 +490,11 @@ 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) |> Keyword.merge(@timeout_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}
|
||||
|
||||
@@ -335,7 +335,7 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
|
||||
defp handle_tracking_event({:track_characters, map_characters, track_character}, socket, map_id) do
|
||||
:ok =
|
||||
WandererApp.Character.TrackingUtils.track_characters(
|
||||
WandererApp.Character.TrackingUtils.track(
|
||||
map_characters,
|
||||
map_id,
|
||||
track_character,
|
||||
|
||||
@@ -56,18 +56,12 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
|
||||
case track_character do
|
||||
false ->
|
||||
:ok =
|
||||
WandererApp.Character.TrackingUtils.untrack_characters(
|
||||
map_characters,
|
||||
map_id,
|
||||
self()
|
||||
)
|
||||
|
||||
:ok = WandererApp.Character.TrackingUtils.untrack(map_characters, map_id, self())
|
||||
:ok = WandererApp.Character.TrackingUtils.remove_characters(map_characters, map_id)
|
||||
|
||||
_ ->
|
||||
:ok =
|
||||
WandererApp.Character.TrackingUtils.track_characters(
|
||||
WandererApp.Character.TrackingUtils.track(
|
||||
map_characters,
|
||||
map_id,
|
||||
true,
|
||||
|
||||
@@ -291,6 +291,8 @@ defmodule WandererAppWeb.MapEventHandler do
|
||||
|
||||
def push_map_event(socket, _type, _body), do: socket
|
||||
|
||||
def map_ui_character_stat(nil), do: nil
|
||||
|
||||
def map_ui_character_stat(character),
|
||||
do:
|
||||
character
|
||||
|
||||
Reference in New Issue
Block a user