diff --git a/Dockerfile b/Dockerfile index e4dd0d2..e0e4a4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,7 +54,7 @@ RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen ENV LANG="en_US.UTF-8" LANGUAGE="en_US:en" LC_ALL="en_US.UTF-8" # Set deployment timestamp to current time during build -ENV DEPLOYED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ") +RUN date -u +"%Y-%m-%dT%H:%M:%SZ" > /app/deployed_at.txt # Set working directory WORKDIR "/app" diff --git a/lib/aprs/release.ex b/lib/aprs/release.ex index 83db4c5..be87f3c 100644 --- a/lib/aprs/release.ex +++ b/lib/aprs/release.ex @@ -6,11 +6,13 @@ defmodule Aprs.Release do @app :aprs def migrate do - load_app() + # Initialize deployment timestamp first + deployed_at = init() + require Logger + Logger.info("Deployment timestamp: #{deployed_at}") - for repo <- repos() do - {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true)) - end + # Run migrations + {:ok, _, _} = Ecto.Migrator.with_repo(Aprs.Repo, &Ecto.Migrator.run(&1, :up, all: true)) end def rollback(repo, version) do @@ -25,4 +27,39 @@ defmodule Aprs.Release do defp load_app do Application.load(@app) end + + @doc """ + Initialize release-specific configuration. + This is called during application startup. + """ + def init do + # Read deployment timestamp from file + deployed_at = read_deployment_timestamp() + + # Add to application config + Application.put_env(:aprs, :deployed_at, deployed_at) + + deployed_at + end + + @doc """ + Get the deployment timestamp. + """ + def deployed_at do + Application.get_env(:aprs, :deployed_at) || DateTime.utc_now() + end + + defp read_deployment_timestamp do + case File.read("/app/deployed_at.txt") do + {:ok, timestamp} -> + case DateTime.from_iso8601(String.trim(timestamp)) do + {:ok, datetime, _} -> datetime + _ -> DateTime.utc_now() + end + + _ -> + # Fallback to current time if file doesn't exist + DateTime.utc_now() + end + end end diff --git a/lib/aprs_web/live/map_live/index.ex b/lib/aprs_web/live/map_live/index.ex index ba1f8ba..b62f2a1 100644 --- a/lib/aprs_web/live/map_live/index.ex +++ b/lib/aprs_web/live/map_live/index.ex @@ -26,19 +26,8 @@ defmodule AprsWeb.MapLive.Index do Process.send_after(self(), :cleanup_old_packets, 60_000) end - # Get deployment timestamp from environment variable or use current time as fallback - deployed_at = - case System.get_env("DEPLOYED_AT") do - nil -> - # Fallback to current time if not set - DateTime.utc_now() - - timestamp when is_binary(timestamp) -> - case DateTime.from_iso8601(timestamp) do - {:ok, datetime, _} -> datetime - _ -> DateTime.utc_now() - end - end + # Get deployment timestamp from config (set during application startup) + deployed_at = Aprs.Release.deployed_at() one_hour_ago = DateTime.add(DateTime.utc_now(), -3600, :second) @@ -154,14 +143,18 @@ defmodule AprsWeb.MapLive.Index do @impl true def handle_event("bounds_changed", %{"bounds" => bounds}, socket) do - Logger.debug("handle_event bounds_changed: #{inspect(bounds)} vs current #{inspect(socket.assigns.map_bounds)}") + Logger.debug( + "handle_event bounds_changed: #{inspect(bounds)} vs current #{inspect(socket.assigns.map_bounds)}" + ) handle_bounds_update(bounds, socket) end @impl true def handle_event("update_bounds", %{"bounds" => bounds}, socket) do - Logger.debug("handle_event update_bounds: #{inspect(bounds)} vs current #{inspect(socket.assigns.map_bounds)}") + Logger.debug( + "handle_event update_bounds: #{inspect(bounds)} vs current #{inspect(socket.assigns.map_bounds)}" + ) handle_bounds_update(bounds, socket) end @@ -325,7 +318,9 @@ defmodule AprsWeb.MapLive.Index do west: bounds["west"] } - Logger.debug("handle_bounds_update: new #{inspect(map_bounds)} vs current #{inspect(socket.assigns.map_bounds)}") + Logger.debug( + "handle_bounds_update: new #{inspect(map_bounds)} vs current #{inspect(socket.assigns.map_bounds)}" + ) # Validate bounds to prevent invalid coordinates if map_bounds.north > 90 or map_bounds.south < -90 or @@ -351,7 +346,9 @@ defmodule AprsWeb.MapLive.Index do @spec process_bounds_update(map(), Socket.t()) :: Socket.t() defp process_bounds_update(map_bounds, socket) do - Logger.debug("process_bounds_update: Loading historical packets for bounds #{inspect(map_bounds)}") + Logger.debug( + "process_bounds_update: Loading historical packets for bounds #{inspect(map_bounds)}" + ) # Remove out-of-bounds packets and markers immediately new_visible_packets = @@ -385,22 +382,30 @@ defmodule AprsWeb.MapLive.Index do end @impl true - def handle_info({:process_bounds_update, map_bounds}, socket), do: handle_info_process_bounds_update(map_bounds, socket) + def handle_info({:process_bounds_update, map_bounds}, socket), + do: handle_info_process_bounds_update(map_bounds, socket) - def handle_info({:delayed_zoom, %{lat: lat, lng: lng}}, socket), do: handle_info_delayed_zoom(lat, lng, socket) + def handle_info({:delayed_zoom, %{lat: lat, lng: lng}}, socket), + do: handle_info_delayed_zoom(lat, lng, socket) - def handle_info({:ip_location, %{lat: lat, lng: lng}}, socket), do: handle_info_ip_location(lat, lng, socket) + def handle_info({:ip_location, %{lat: lat, lng: lng}}, socket), + do: handle_info_ip_location(lat, lng, socket) def handle_info(:initialize_replay, socket), do: handle_info_initialize_replay(socket) def handle_info(:cleanup_old_packets, socket), do: handle_cleanup_old_packets(socket) - def handle_info(:reload_historical_packets, socket), do: handle_reload_historical_packets(socket) + def handle_info(:reload_historical_packets, socket), + do: handle_reload_historical_packets(socket) - def handle_info({:postgres_packet, packet}, socket), do: handle_info_postgres_packet(packet, socket) + def handle_info({:postgres_packet, packet}, socket), + do: handle_info_postgres_packet(packet, socket) - def handle_info(%Phoenix.Socket.Broadcast{topic: "aprs_messages", event: "packet", payload: packet}, socket), - do: handle_info({:postgres_packet, packet}, socket) + def handle_info( + %Phoenix.Socket.Broadcast{topic: "aprs_messages", event: "packet", payload: packet}, + socket + ), + do: handle_info({:postgres_packet, packet}, socket) # Private handler functions for each message type @@ -748,7 +753,7 @@ defmodule AprsWeb.MapLive.Index do

APRS.me

- + - +
@@ -804,7 +809,7 @@ defmodule AprsWeb.MapLive.Index do
- +
- +
- +
<.link @@ -948,7 +953,7 @@ defmodule AprsWeb.MapLive.Index do View Bad Packets
- +