mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-10-30 14:07:03 +00:00
Compare commits
16 Commits
v1.66.11
...
tracking-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27b5694885 | ||
|
|
4093f28cee | ||
|
|
08aaf2f2dd | ||
|
|
df955ff8b0 | ||
|
|
4dc74022b4 | ||
|
|
c2b7d07208 | ||
|
|
21e76a6f05 | ||
|
|
89c0d6fad6 | ||
|
|
b74d15b1ee | ||
|
|
10313438bf | ||
|
|
a764217948 | ||
|
|
d81d6fb937 | ||
|
|
4c0f7ab7f9 | ||
|
|
1c48945a96 | ||
|
|
850901f62f | ||
|
|
4822854e30 |
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -116,6 +116,7 @@ jobs:
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
|
||||
32
CHANGELOG.md
32
CHANGELOG.md
@@ -2,6 +2,38 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.66.15](https://github.com/wanderer-industries/wanderer/compare/v1.66.14...v1.66.15) (2025-06-07)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Added back arm docker image build
|
||||
|
||||
## [v1.66.14](https://github.com/wanderer-industries/wanderer/compare/v1.66.13...v1.66.14) (2025-06-07)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: fixed online updates
|
||||
|
||||
## [v1.66.13](https://github.com/wanderer-industries/wanderer/compare/v1.66.12...v1.66.13) (2025-06-07)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: fixed location tracking issues
|
||||
|
||||
## [v1.66.12](https://github.com/wanderer-industries/wanderer/compare/v1.66.11...v1.66.12) (2025-06-06)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.66.11](https://github.com/wanderer-industries/wanderer/compare/v1.66.10...v1.66.11) (2025-06-06)
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { useCallback } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useAutoAnimate } from '@formkit/auto-animate/react';
|
||||
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import classes from './Characters.module.scss';
|
||||
import { isDocked } from '@/hooks/Mapper/helpers/isDocked.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
|
||||
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useAutoAnimate } from '@formkit/auto-animate/react';
|
||||
import clsx from 'clsx';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
import classes from './Characters.module.scss';
|
||||
interface CharactersProps {
|
||||
data: CharacterTypeRaw[];
|
||||
}
|
||||
@@ -17,13 +16,22 @@ export const Characters = ({ data }: CharactersProps) => {
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const {
|
||||
outCommand,
|
||||
data: { mainCharacterEveId, followingCharacterEveId },
|
||||
} = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback((character: CharacterTypeRaw) => {
|
||||
const handleSelect = useCallback(async (character: CharacterTypeRaw) => {
|
||||
if (!character) {
|
||||
return;
|
||||
}
|
||||
|
||||
await outCommand({
|
||||
type: OutCommand.startTracking,
|
||||
data: { character_eve_id: character.eve_id },
|
||||
});
|
||||
emitMapEvent({
|
||||
name: Commands.centerSystem,
|
||||
data: character?.location?.solar_system_id?.toString(),
|
||||
data: character.location?.solar_system_id?.toString(),
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -37,14 +45,26 @@ export const Characters = ({ data }: CharactersProps) => {
|
||||
className={clsx(
|
||||
'overflow-hidden relative',
|
||||
'flex w-[35px] h-[35px] rounded-[4px] border-[1px] border-solid bg-transparent cursor-pointer',
|
||||
'transition-colors duration-250',
|
||||
'transition-colors duration-250 hover:bg-stone-300/90',
|
||||
{
|
||||
['border-stone-800/90']: !character.online,
|
||||
['border-lime-600/70']: character.online,
|
||||
},
|
||||
)}
|
||||
title={character.name}
|
||||
title={character.tracking_paused ? `${character.name} - Tracking Paused (click to resume)` : character.name}
|
||||
>
|
||||
{character.tracking_paused && (
|
||||
<>
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[2px] left-[2px] w-[9px] h-[9px]',
|
||||
'text-yellow-500 text-[9px] rounded-[1px] z-10 hover:hidden',
|
||||
'pi',
|
||||
PrimeIcons.PAUSE,
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{mainCharacterEveId === character.eve_id && (
|
||||
<span
|
||||
className={clsx(
|
||||
@@ -55,6 +75,7 @@ export const Characters = ({ data }: CharactersProps) => {
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{followingCharacterEveId === character.eve_id && (
|
||||
<span
|
||||
className={clsx(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import {
|
||||
CommandCharacterAdded,
|
||||
CommandCharacterRemoved,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
CommandCharacterUpdated,
|
||||
CommandPresentCharacters,
|
||||
} from '@/hooks/Mapper/types';
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
export const useCommandsCharacters = () => {
|
||||
const { update } = useMapState();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
|
||||
import { MapData, useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
|
||||
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
|
||||
|
||||
export const useMapInit = () => {
|
||||
const rf = useReactFlow();
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { Characters } from '../characters/Characters';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useMemo } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { sortOnlineFunc } from '@/hooks/Mapper/components/hooks/useGetOwnOnlineCharacters.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
import { Button } from 'primereact/button';
|
||||
import clsx from 'clsx';
|
||||
import { useMemo } from 'react';
|
||||
import { Characters } from '../characters/Characters';
|
||||
|
||||
const Topbar = ({ children }: WithChildren) => {
|
||||
const {
|
||||
data: { characters, userCharacters, pings },
|
||||
data: { characters, userCharacters },
|
||||
} = useMapRootState();
|
||||
|
||||
const charsToShow = useMemo(() => {
|
||||
|
||||
@@ -33,6 +33,7 @@ export type CharacterTypeRaw = {
|
||||
corporation_id: number;
|
||||
corporation_name: string;
|
||||
corporation_ticker: string;
|
||||
tracking_paused: boolean;
|
||||
};
|
||||
|
||||
export interface TrackingCharacter {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
|
||||
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
|
||||
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
|
||||
import { ActivitySummary, CharacterTypeRaw, TrackingCharacter } from '@/hooks/Mapper/types/character.ts';
|
||||
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
|
||||
import { DetailedKill, Kill } from '@/hooks/Mapper/types/kills.ts';
|
||||
import { CommentType, PingData, SystemSignature, UserPermissions } from '@/hooks/Mapper/types';
|
||||
import { ActivitySummary, CharacterTypeRaw, TrackingCharacter } from '@/hooks/Mapper/types/character.ts';
|
||||
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
|
||||
import { DetailedKill, Kill } from '@/hooks/Mapper/types/kills.ts';
|
||||
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
|
||||
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
|
||||
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
|
||||
|
||||
export enum Commands {
|
||||
init = 'init',
|
||||
@@ -260,6 +260,7 @@ export enum OutCommand {
|
||||
updateMainCharacter = 'updateMainCharacter',
|
||||
addPing = 'add_ping',
|
||||
cancelPing = 'cancel_ping',
|
||||
startTracking = 'startTracking',
|
||||
|
||||
// Only UI commands
|
||||
openSettings = 'open_settings',
|
||||
|
||||
@@ -251,13 +251,22 @@ defmodule WandererApp.Character do
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_merge_map_character_settings(character, map_id, true), do: character
|
||||
defp maybe_merge_map_character_settings(%{id: character_id} = character, map_id, true) do
|
||||
{:ok, tracking_paused} =
|
||||
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false)
|
||||
|
||||
character
|
||||
|> Map.merge(%{tracking_paused: tracking_paused})
|
||||
end
|
||||
|
||||
defp maybe_merge_map_character_settings(
|
||||
%{id: character_id} = character,
|
||||
map_id,
|
||||
_character_is_present
|
||||
) do
|
||||
{:ok, tracking_paused} =
|
||||
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false)
|
||||
|
||||
WandererApp.MapCharacterSettingsRepo.get(map_id, character_id)
|
||||
|> case do
|
||||
{:ok, settings} when not is_nil(settings) ->
|
||||
@@ -270,6 +279,7 @@ defmodule WandererApp.Character do
|
||||
|> Map.put(:online, false)
|
||||
|> Map.merge(@default_character_tracking_data)
|
||||
end
|
||||
|> Map.merge(%{tracking_paused: tracking_paused})
|
||||
end
|
||||
|
||||
defp prepare_search_results(result) do
|
||||
|
||||
@@ -33,12 +33,16 @@ defmodule WandererApp.Character.Tracker do
|
||||
status: binary()
|
||||
}
|
||||
|
||||
@pause_tracking_timeout :timer.minutes(10)
|
||||
@online_error_timeout :timer.minutes(1)
|
||||
@pause_tracking_timeout :timer.minutes(60 * 24)
|
||||
@offline_timeout :timer.minutes(5)
|
||||
@online_error_timeout :timer.minutes(2)
|
||||
@ship_error_timeout :timer.minutes(2)
|
||||
@location_error_timeout :timer.minutes(2)
|
||||
@online_forbidden_ttl :timer.seconds(7)
|
||||
@online_limit_ttl :timer.seconds(7)
|
||||
@forbidden_ttl :timer.seconds(5)
|
||||
@limit_ttl :timer.seconds(5)
|
||||
@location_limit_ttl :timer.seconds(1)
|
||||
@pubsub_client Application.compile_env(:wanderer_app, :pubsub_client)
|
||||
|
||||
def new(), do: __struct__()
|
||||
@@ -53,8 +57,37 @@ defmodule WandererApp.Character.Tracker do
|
||||
|> new()
|
||||
end
|
||||
|
||||
def check_online_errors(character_id) do
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
|
||||
def check_offline(character_id) do
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:last_online_time")
|
||||
|> case do
|
||||
nil ->
|
||||
pause_tracking(character_id)
|
||||
:ok
|
||||
|
||||
last_online_time ->
|
||||
duration = DateTime.diff(DateTime.utc_now(), last_online_time, :millisecond)
|
||||
|
||||
if duration >= @offline_timeout do
|
||||
pause_tracking(character_id)
|
||||
|
||||
:ok
|
||||
else
|
||||
:skip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check_online_errors(character_id),
|
||||
do: check_tracking_errors(character_id, "online", @online_error_timeout)
|
||||
|
||||
def check_ship_errors(character_id),
|
||||
do: check_tracking_errors(character_id, "ship", @ship_error_timeout)
|
||||
|
||||
def check_location_errors(character_id),
|
||||
do: check_tracking_errors(character_id, "location", @location_error_timeout)
|
||||
|
||||
defp check_tracking_errors(character_id, type, timeout) do
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:#{type}_error_time")
|
||||
|> case do
|
||||
nil ->
|
||||
:skip
|
||||
@@ -62,34 +95,8 @@ defmodule WandererApp.Character.Tracker do
|
||||
error_time ->
|
||||
duration = DateTime.diff(DateTime.utc_now(), error_time, :millisecond)
|
||||
|
||||
if duration >= @online_error_timeout do
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
|
||||
WandererApp.Character.update_character(character_id, %{online: false})
|
||||
|
||||
WandererApp.Character.update_character_state(character_id, %{
|
||||
is_online: false
|
||||
})
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:tracking_paused",
|
||||
true,
|
||||
ttl: @pause_tracking_timeout
|
||||
)
|
||||
|
||||
{:ok, %{solar_system_id: solar_system_id}} =
|
||||
WandererApp.Character.get_character(character_id)
|
||||
|
||||
{:ok, %{active_maps: active_maps}} =
|
||||
WandererApp.Character.get_character_state(character_id)
|
||||
|
||||
active_maps
|
||||
|> Enum.each(fn map_id ->
|
||||
WandererApp.Cache.put(
|
||||
"map:#{map_id}:character:#{character_id}:start_solar_system_id",
|
||||
solar_system_id
|
||||
)
|
||||
end)
|
||||
if duration >= timeout do
|
||||
pause_tracking(character_id)
|
||||
|
||||
:ok
|
||||
else
|
||||
@@ -98,6 +105,42 @@ defmodule WandererApp.Character.Tracker do
|
||||
end
|
||||
end
|
||||
|
||||
defp pause_tracking(character_id) do
|
||||
if not WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused") do
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:ship_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:location_error_time")
|
||||
WandererApp.Character.update_character(character_id, %{online: false})
|
||||
|
||||
WandererApp.Character.update_character_state(character_id, %{
|
||||
is_online: false
|
||||
})
|
||||
|
||||
Logger.warning("[CharacterTracker] paused for #{character_id}")
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:tracking_paused",
|
||||
true,
|
||||
ttl: @pause_tracking_timeout
|
||||
)
|
||||
|
||||
{:ok, %{solar_system_id: solar_system_id}} =
|
||||
WandererApp.Character.get_character(character_id)
|
||||
|
||||
{:ok, %{active_maps: active_maps}} =
|
||||
WandererApp.Character.get_character_state(character_id)
|
||||
|
||||
active_maps
|
||||
|> Enum.each(fn map_id ->
|
||||
WandererApp.Cache.put(
|
||||
"map:#{map_id}:character:#{character_id}:start_solar_system_id",
|
||||
solar_system_id
|
||||
)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
def update_settings(character_id, track_settings) do
|
||||
{:ok, character_state} = WandererApp.Character.get_character_state(character_id)
|
||||
|
||||
@@ -134,18 +177,19 @@ defmodule WandererApp.Character.Tracker do
|
||||
{:ok, online} ->
|
||||
online = get_online(online)
|
||||
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
|
||||
|
||||
if is_nil(
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
|
||||
) do
|
||||
if online.online == true do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:online_error_time",
|
||||
"character:#{character_id}:last_online_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
else
|
||||
WandererApp.Cache.delete("character:#{character_id}:last_online_time")
|
||||
end
|
||||
|
||||
# WandererApp.Cache.delete("character:#{character_id}:online_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
|
||||
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:ship_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:location_error_time")
|
||||
WandererApp.Cache.delete("character:#{character_id}:info_forbidden")
|
||||
WandererApp.Cache.delete("character:#{character_id}:ship_forbidden")
|
||||
WandererApp.Cache.delete("character:#{character_id}:location_forbidden")
|
||||
@@ -196,15 +240,6 @@ defmodule WandererApp.Character.Tracker do
|
||||
ttl: reset_timeout
|
||||
)
|
||||
|
||||
if is_nil(
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
|
||||
) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:online_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, :skipped}
|
||||
|
||||
{:error, error} ->
|
||||
@@ -239,11 +274,16 @@ defmodule WandererApp.Character.Tracker do
|
||||
|
||||
def update_online(_), do: {:error, :skipped}
|
||||
|
||||
defp get_reset_timeout(%{"x-esi-error-limit-reset" => [reset_seconds]})
|
||||
defp get_reset_timeout(_headers, _default_timeout \\ @limit_ttl)
|
||||
|
||||
defp get_reset_timeout(
|
||||
%{"x-esi-error-limit-remain" => ["0"], "x-esi-error-limit-reset" => [reset_seconds]},
|
||||
_default_timeout
|
||||
)
|
||||
when is_binary(reset_seconds),
|
||||
do: :timer.seconds((reset_seconds |> String.to_integer()) + 1)
|
||||
|
||||
defp get_reset_timeout(_headers), do: @limit_ttl
|
||||
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") ||
|
||||
@@ -346,6 +386,13 @@ defmodule WandererApp.Character.Tracker do
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
|
||||
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:ship_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, error}
|
||||
|
||||
{:error, :error_limited, headers} ->
|
||||
@@ -370,6 +417,13 @@ defmodule WandererApp.Character.Tracker do
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
|
||||
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:ship_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, error}
|
||||
|
||||
_ ->
|
||||
@@ -381,6 +435,13 @@ defmodule WandererApp.Character.Tracker do
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
|
||||
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:ship_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, :skipped}
|
||||
end
|
||||
end
|
||||
@@ -403,8 +464,7 @@ defmodule WandererApp.Character.Tracker do
|
||||
) do
|
||||
case WandererApp.Character.get_character(character_id) do
|
||||
{:ok, %{eve_id: eve_id, access_token: access_token}} when not is_nil(access_token) ->
|
||||
(WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") ||
|
||||
WandererApp.Cache.has_key?("character:#{character_id}:location_forbidden") ||
|
||||
(WandererApp.Cache.has_key?("character:#{character_id}:location_forbidden") ||
|
||||
WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused"))
|
||||
|> case do
|
||||
true ->
|
||||
@@ -424,21 +484,24 @@ defmodule WandererApp.Character.Tracker do
|
||||
{:error, error} when error in [:forbidden, :not_found, :timeout] ->
|
||||
Logger.warning("#{__MODULE__} failed to update_location: #{inspect(error)}")
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:location_forbidden",
|
||||
true,
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
if is_nil(
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
|
||||
) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:location_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, error}
|
||||
{:error, :skipped}
|
||||
|
||||
{:error, :error_limited, headers} ->
|
||||
reset_timeout = get_reset_timeout(headers)
|
||||
|
||||
Logger.warning(
|
||||
"#{__MODULE__} failed to update_location: #{inspect(:error_limited)}"
|
||||
)
|
||||
|
||||
reset_timeout = get_reset_timeout(headers, @location_limit_ttl)
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:location_forbidden",
|
||||
true,
|
||||
@@ -450,22 +513,28 @@ defmodule WandererApp.Character.Tracker do
|
||||
{:error, error} ->
|
||||
Logger.error("#{__MODULE__} failed to update_location: #{inspect(error)}")
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:location_forbidden",
|
||||
true,
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
if is_nil(
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
|
||||
) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:location_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, error}
|
||||
{:error, :skipped}
|
||||
|
||||
_ ->
|
||||
Logger.error("#{__MODULE__} failed to update_location: wrong response")
|
||||
|
||||
WandererApp.Cache.put(
|
||||
"character:#{character_id}:location_forbidden",
|
||||
true,
|
||||
ttl: @forbidden_ttl
|
||||
)
|
||||
if is_nil(
|
||||
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
|
||||
) do
|
||||
WandererApp.Cache.insert(
|
||||
"character:#{character_id}:location_error_time",
|
||||
DateTime.utc_now()
|
||||
)
|
||||
end
|
||||
|
||||
{:error, :skipped}
|
||||
end
|
||||
|
||||
@@ -119,7 +119,6 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
{:ok, character_state} =
|
||||
WandererApp.Character.Tracker.update_settings(character_id, track_settings)
|
||||
|
||||
WandererApp.Cache.delete("character:#{character_id}:tracking_paused")
|
||||
WandererApp.Character.update_character_state(character_id, character_state)
|
||||
else
|
||||
WandererApp.Cache.insert_or_update(
|
||||
|
||||
@@ -16,7 +16,7 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
@registry :tracker_pool_registry
|
||||
@unique_registry :unique_tracker_pool_registry
|
||||
|
||||
@update_location_interval :timer.seconds(2)
|
||||
@update_location_interval :timer.seconds(1)
|
||||
@update_online_interval :timer.seconds(5)
|
||||
@check_online_errors_interval :timer.seconds(30)
|
||||
@update_ship_interval :timer.seconds(2)
|
||||
@@ -24,6 +24,8 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
@update_wallet_interval :timer.minutes(1)
|
||||
@inactive_character_timeout :timer.minutes(5)
|
||||
|
||||
@pause_tracking_timeout :timer.minutes(60 * 24)
|
||||
|
||||
@logger Application.compile_env(:wanderer_app, :logger)
|
||||
|
||||
def new(), do: __struct__()
|
||||
@@ -50,6 +52,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
|
||||
tracked_ids
|
||||
|> Enum.each(fn id ->
|
||||
# WandererApp.Cache.put(
|
||||
# "character:#{id}:tracking_paused",
|
||||
# true,
|
||||
# ttl: @pause_tracking_timeout
|
||||
# )
|
||||
|
||||
Cachex.put(@cache, id, uuid)
|
||||
end)
|
||||
|
||||
@@ -77,6 +85,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
[tracked_id | r_tracked_ids]
|
||||
end)
|
||||
|
||||
# WandererApp.Cache.put(
|
||||
# "character:#{tracked_id}:tracking_paused",
|
||||
# true,
|
||||
# ttl: @pause_tracking_timeout
|
||||
# )
|
||||
|
||||
# Cachex.get_and_update(@cache, :tracked_characters, fn ids ->
|
||||
# {:commit, ids ++ [tracked_id]}
|
||||
# end)
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule WandererApp.Character.TrackerPoolDynamicSupervisor do
|
||||
@cache :tracked_characters
|
||||
@registry :tracker_pool_registry
|
||||
@unique_registry :unique_tracker_pool_registry
|
||||
@tracker_pool_limit 100
|
||||
@tracker_pool_limit 50
|
||||
|
||||
@name __MODULE__
|
||||
|
||||
|
||||
@@ -219,10 +219,12 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
Task.start_link(fn ->
|
||||
character_updates =
|
||||
maybe_update_online(map_id, character_id) ++
|
||||
maybe_update_location(map_id, character_id) ++
|
||||
maybe_update_ship(map_id, character_id) ++
|
||||
maybe_update_alliance(map_id, character_id) ++
|
||||
maybe_update_corporation(map_id, character_id)
|
||||
maybe_update_tracking_status(map_id, character_id)
|
||||
|
||||
maybe_update_location(map_id, character_id) ++
|
||||
maybe_update_ship(map_id, character_id) ++
|
||||
maybe_update_alliance(map_id, character_id) ++
|
||||
maybe_update_corporation(map_id, character_id)
|
||||
|
||||
character_updates
|
||||
|> Enum.filter(fn update -> update != :skip end)
|
||||
@@ -245,6 +247,9 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
{:character_online, _info} ->
|
||||
:broadcast
|
||||
|
||||
{:character_tracking, _info} ->
|
||||
:broadcast
|
||||
|
||||
{:character_alliance, _info} ->
|
||||
WandererApp.Cache.insert_or_update(
|
||||
"map_#{map_id}:invalidate_character_ids",
|
||||
@@ -388,6 +393,33 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_update_tracking_status(map_id, character_id) do
|
||||
with {:ok, old_tracking_paused} <-
|
||||
WandererApp.Cache.lookup(
|
||||
"map:#{map_id}:character:#{character_id}:tracking_paused",
|
||||
false
|
||||
),
|
||||
{:ok, tracking_paused} <-
|
||||
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false) do
|
||||
case old_tracking_paused != tracking_paused do
|
||||
true ->
|
||||
WandererApp.Cache.insert(
|
||||
"map:#{map_id}:character:#{character_id}:tracking_paused",
|
||||
tracking_paused
|
||||
)
|
||||
|
||||
[{:character_tracking, %{tracking_paused: tracking_paused}}]
|
||||
|
||||
_ ->
|
||||
[:skip]
|
||||
end
|
||||
else
|
||||
error ->
|
||||
Logger.error("Failed to update character_tracking: #{inspect(error, pretty: true)}")
|
||||
[:skip]
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_update_ship(map_id, character_id) do
|
||||
with {:ok, old_ship_type_id} <-
|
||||
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:ship_type_id"),
|
||||
|
||||
@@ -32,16 +32,18 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
)
|
||||
end
|
||||
|
||||
def handle_server_event(%{event: :untrack_character, payload: character_id}, %{
|
||||
assigns: %{
|
||||
map_id: map_id
|
||||
}
|
||||
} = socket) do
|
||||
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},
|
||||
%{
|
||||
@@ -276,6 +278,24 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
)}
|
||||
end
|
||||
|
||||
def handle_ui_event(
|
||||
"startTracking",
|
||||
%{"character_eve_id" => character_eve_id},
|
||||
%{
|
||||
assigns: %{
|
||||
map_id: map_id,
|
||||
current_user: %{id: current_user_id}
|
||||
}
|
||||
} = socket
|
||||
)
|
||||
when not is_nil(character_eve_id) do
|
||||
{:ok, character} = WandererApp.Character.get_by_eve_id("#{character_eve_id}")
|
||||
|
||||
WandererApp.Cache.delete("character:#{character.id}:tracking_paused")
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_ui_event(event, body, socket),
|
||||
do: MapCoreEventHandler.handle_ui_event(event, body, socket)
|
||||
|
||||
@@ -295,6 +315,7 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
|> Map.put(:alliance_ticker, Map.get(character, :alliance_ticker, ""))
|
||||
|> Map.put_new(:ship, WandererApp.Character.get_ship(character))
|
||||
|> Map.put_new(:location, get_location(character))
|
||||
|> Map.put_new(:tracking_paused, character |> Map.get(:tracking_paused, false))
|
||||
|
||||
defp get_location(character),
|
||||
do: %{
|
||||
|
||||
@@ -33,7 +33,8 @@ defmodule WandererAppWeb.MapEventHandler do
|
||||
"getCharactersTrackingInfo",
|
||||
"updateCharacterTracking",
|
||||
"updateFollowingCharacter",
|
||||
"updateMainCharacter"
|
||||
"updateMainCharacter",
|
||||
"startTracking"
|
||||
]
|
||||
|
||||
@map_system_events [
|
||||
|
||||
Reference in New Issue
Block a user