From 8ddcb8000f9db2d06867e7003ec6878f50249fae Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 27 Jul 2025 12:20:23 -0500 Subject: [PATCH] Fix Leaflet library loading race condition and enable Redis-free development MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix race condition in map bundle loading by waiting for script to load before initializing map - Ensure Leaflet is properly exposed as window.L in map bundle - Add Leaflet availability check in map initialization function - Disable Exq background jobs in development environment to remove Redis dependency - Remove invalid TelemetryMetricsPrometheus plug from endpoint - Application now starts successfully without Redis in development mode 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- assets/js/app.js | 52 ++++++++++++++++++++++++++++------- assets/js/map-bundle-entry.js | 5 ++++ assets/js/map.ts | 11 ++++++++ config/dev.exs | 5 ++++ lib/aprsme_web/endpoint.ex | 3 -- 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 684d0c4..283e16b 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -129,11 +129,27 @@ let Hooks = {}; Hooks.APRSMap = { ...MapAPRSMap, mounted() { - if (window.VendorLoader) { - window.VendorLoader.loadMap(); - } - if (MapAPRSMap.mounted) { - MapAPRSMap.mounted.call(this); + const self = this; + if (window.VendorLoader && !window.mapBundleLoaded) { + // Load map bundle and wait for it to complete + const script = document.createElement('script'); + script.src = window.VendorLoader.mapBundleUrl; + script.onload = () => { + window.mapBundleLoaded = true; + // Now call the original mounted function + if (MapAPRSMap.mounted) { + MapAPRSMap.mounted.call(self); + } + }; + script.onerror = () => { + console.error("Failed to load map bundle"); + }; + document.head.appendChild(script); + } else { + // Map bundle already loaded, proceed immediately + if (MapAPRSMap.mounted) { + MapAPRSMap.mounted.call(this); + } } } }; @@ -141,11 +157,27 @@ Hooks.APRSMap = { Hooks.InfoMap = { ...InfoMap, mounted() { - if (window.VendorLoader) { - window.VendorLoader.loadMap(); - } - if (InfoMap.mounted) { - InfoMap.mounted.call(this); + const self = this; + if (window.VendorLoader && !window.mapBundleLoaded) { + // Load map bundle and wait for it to complete + const script = document.createElement('script'); + script.src = window.VendorLoader.mapBundleUrl; + script.onload = () => { + window.mapBundleLoaded = true; + // Now call the original mounted function + if (InfoMap.mounted) { + InfoMap.mounted.call(self); + } + }; + script.onerror = () => { + console.error("Failed to load map bundle"); + }; + document.head.appendChild(script); + } else { + // Map bundle already loaded, proceed immediately + if (InfoMap.mounted) { + InfoMap.mounted.call(this); + } } } }; diff --git a/assets/js/map-bundle-entry.js b/assets/js/map-bundle-entry.js index e261e20..5bda1cb 100644 --- a/assets/js/map-bundle-entry.js +++ b/assets/js/map-bundle-entry.js @@ -2,5 +2,10 @@ import "../vendor/js/leaflet-minimal.js"; import "../vendor/js/plugins-optimized.js"; +// Ensure Leaflet is available as window.L (standard convention) +if (window.leaflet && !window.L) { + window.L = window.leaflet; +} + // Mark bundle as loaded window.mapBundleLoaded = true; \ No newline at end of file diff --git a/assets/js/map.ts b/assets/js/map.ts index 2d97fbe..d55fa02 100644 --- a/assets/js/map.ts +++ b/assets/js/map.ts @@ -157,6 +157,17 @@ let MapAPRSMap = { initializeMap(initialCenter: CenterData, initialZoom: number) { const self = this as unknown as LiveViewHookContext; + + // Check if Leaflet is still available + if (typeof window.L === "undefined") { + console.error("Leaflet library not loaded!"); + self.handleFatalError("Leaflet library not available"); + return; + } + + // Create a local reference to Leaflet for this function + const L = window.L; + // Ensure the element and its parent exist if (!self.el || !self.el.parentNode) { console.warn("Map element or parent not found, retrying..."); diff --git a/config/dev.exs b/config/dev.exs index 37809d2..b634f5e 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -72,6 +72,11 @@ config :aprsme, AprsmeWeb.Endpoint, # Run `mix help phx.gen.cert` for more information. config :aprsme, dev_routes: true +# Disable Exq in development (no Redis required) +# Jobs that would normally run in the background will be skipped +config :exq, + start_on_application: false + # Mailer configuration for development # Using Swoosh.Adapters.Local from config.exs which stores emails locally # Access sent emails at http://localhost:4000/dev/mailbox diff --git a/lib/aprsme_web/endpoint.ex b/lib/aprsme_web/endpoint.ex index 0b1628c..a394415 100644 --- a/lib/aprsme_web/endpoint.ex +++ b/lib/aprsme_web/endpoint.ex @@ -56,8 +56,5 @@ defmodule AprsmeWeb.Endpoint do # Health check endpoint plug AprsmeWeb.Plugs.HealthCheck - # Prometheus metrics endpoint - plug TelemetryMetricsPrometheus - plug AprsmeWeb.Router end