diff --git a/config/dev.exs b/config/dev.exs index 447f039e..7b18a442 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -63,6 +63,7 @@ config :wanderer_app, WandererAppWeb.Endpoint, ] config :wanderer_app, + environment: :dev, dev_routes: true # Do not include metadata nor timestamps in development logs diff --git a/config/runtime.exs b/config/runtime.exs index 2bc57bc5..ae4bd887 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -127,6 +127,7 @@ restrict_acls_creation = |> String.to_existing_atom() config :wanderer_app, + environment: config_env(), web_app_url: web_app_url, git_sha: System.get_env("GIT_SHA", "111"), custom_route_base_url: System.get_env("CUSTOM_ROUTE_BASE_URL"), diff --git a/lib/wanderer_app/map/map_manager.ex b/lib/wanderer_app/map/map_manager.ex index 0ca6d96b..0801765c 100644 --- a/lib/wanderer_app/map/map_manager.ex +++ b/lib/wanderer_app/map/map_manager.ex @@ -9,6 +9,8 @@ defmodule WandererApp.Map.Manager do alias WandererApp.Map.Server + @environment Application.compile_env(:wanderer_app, :environment) + @maps_start_chunk_size 20 @maps_start_interval 500 @maps_queue :maps_queue @@ -19,7 +21,7 @@ defmodule WandererApp.Map.Manager do # Test-aware async task runner defp safe_async_task(fun) do - if Mix.env() == :test do + if @environment == :test do # In tests, run synchronously to avoid database ownership issues try do fun.() @@ -139,7 +141,7 @@ defmodule WandererApp.Map.Manager do WandererApp.Queue.clear(@maps_queue) - if Mix.env() == :test do + if @environment == :test do # In tests, run synchronously to avoid database ownership issues Logger.debug(fn -> "Starting maps synchronously in test mode" end) diff --git a/lib/wanderer_app/map/map_pool.ex b/lib/wanderer_app/map/map_pool.ex index 285fc25f..b174b70d 100644 --- a/lib/wanderer_app/map/map_pool.ex +++ b/lib/wanderer_app/map/map_pool.ex @@ -20,16 +20,18 @@ defmodule WandererApp.Map.MapPool do @garbage_collection_interval :timer.hours(4) # Use very long timeouts in test environment to prevent background tasks from running during tests # This avoids database connection ownership errors when tests finish before async tasks complete - @systems_cleanup_timeout if Mix.env() == :test, + @environment Application.compile_env(:wanderer_app, :environment) + + @systems_cleanup_timeout if @environment == :test, do: :timer.hours(24), else: :timer.minutes(30) - @characters_cleanup_timeout if Mix.env() == :test, + @characters_cleanup_timeout if @environment == :test, do: :timer.hours(24), else: :timer.minutes(5) - @connections_cleanup_timeout if Mix.env() == :test, + @connections_cleanup_timeout if @environment == :test, do: :timer.hours(24), else: :timer.minutes(5) - @backup_state_timeout if Mix.env() == :test, + @backup_state_timeout if @environment == :test, do: :timer.hours(24), else: :timer.minutes(1) diff --git a/lib/wanderer_app/map/server/map_server_impl.ex b/lib/wanderer_app/map/server/map_server_impl.ex index 440da936..9eb36fa4 100644 --- a/lib/wanderer_app/map/server/map_server_impl.ex +++ b/lib/wanderer_app/map/server/map_server_impl.ex @@ -45,12 +45,6 @@ defmodule WandererApp.Map.Server.Impl do } |> new() - # In test mode, give the test setup time to grant database access - # This is necessary for async tests where the sandbox needs to allow this process - if Mix.env() == :test do - Process.sleep(150) - end - # Parallelize database queries for faster initialization start_time = System.monotonic_time(:millisecond) @@ -314,56 +308,12 @@ defmodule WandererApp.Map.Server.Impl do end) # Create map state with retry logic for test scenarios - create_map_state_with_retry( - %{ - map_id: map_id, - systems_last_activity: systems_last_activity, - connections_eol_time: connections_eol_time, - connections_start_time: connections_start_time - }, - 3 - ) - end - - # Helper to create map state with retry logic for async tests - defp create_map_state_with_retry(attrs, retries_left) when retries_left > 0 do - case WandererApp.Api.MapState.create(attrs) do - {:ok, map_state} = result -> - result - - {:error, %Ash.Error.Invalid{errors: errors}} = error -> - # Check if it's a foreign key constraint error - has_fkey_error = - Enum.any?(errors, fn - %Ash.Error.Changes.InvalidAttribute{private_vars: private_vars} -> - Enum.any?(private_vars, fn - {:constraint_type, :foreign_key} -> true - _ -> false - end) - - _ -> - false - end) - - if has_fkey_error and retries_left > 1 do - # In test environments with async tests, the parent map might not be - # visible yet due to sandbox timing. Brief retry with exponential backoff. - sleep_time = (4 - retries_left) * 15 + 10 - Process.sleep(sleep_time) - create_map_state_with_retry(attrs, retries_left - 1) - else - # Return error if not a foreign key issue or out of retries - error - end - - error -> - error - end - end - - defp create_map_state_with_retry(attrs, 0) do - # Final attempt without retry - WandererApp.Api.MapState.create(attrs) + WandererApp.Api.MapState.create(%{ + map_id: map_id, + systems_last_activity: systems_last_activity, + connections_eol_time: connections_eol_time, + connections_start_time: connections_start_time + }) end def handle_event({:update_characters, map_id} = event) do diff --git a/lib/wanderer_app/task_wrapper.ex b/lib/wanderer_app/task_wrapper.ex index 8f4a0220..bf4f841a 100644 --- a/lib/wanderer_app/task_wrapper.ex +++ b/lib/wanderer_app/task_wrapper.ex @@ -1,6 +1,8 @@ defmodule WandererApp.TaskWrapper do + @environment Application.compile_env(:wanderer_app, :environment) + def start_link(module, func, args) do - if Mix.env() == :test do + if @environment == :test do apply(module, func, args) else Task.start_link(module, func, args)