From e5f7a0f4be18e3cd1e32b1defea194fce04fc797 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 28 Jul 2026 07:46:19 +0200 Subject: [PATCH 1/2] fix(maps): entregar el mapa solo cuando tiene tamano real (MapReady) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MapReady entregaba el mapa en el useEffect de montaje, cuando el contenedor puede no tener tamano todavia. En FiresMap eso hacia que getBounds() lanzara; el catch solo avisaba ("Failed to set map bounds and scale") y mapSize nunca se seteaba, con lo que la suscripcion de fuegos por viewport NI SE CREABA: loading eterno y tile-pane vacio (0 capas) pese a haber 7470 fuegos. Evidencia: en Meteor.connection._subscriptions solo aparecian activefirestotal, activefiresuniontotal, settings y userData — ninguna por localizacion. Ahora se entrega via map.whenReady() + invalidateSize(), solo cuando getSize() no es 0, con reintento en el evento resize y entrega unica (flag delivered). Toca el componente compartido por todos los mapas: al desplegar hay que re-verificar /fires, /zones, /subscriptions, home y detalle de fuego. SIN DESPLEGAR todavia (la imagen viva es la de 01:33, sin este cambio). --- imports/ui/components/Maps/MapBridge.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/imports/ui/components/Maps/MapBridge.js b/imports/ui/components/Maps/MapBridge.js index ea44ea2..bcfe22e 100644 --- a/imports/ui/components/Maps/MapBridge.js +++ b/imports/ui/components/Maps/MapBridge.js @@ -8,8 +8,28 @@ import { useMap, useMapEvents } from 'react-leaflet'; export const MapReady = ({ onReady }) => { const map = useMap(); useEffect(() => { - if (onReady) onReady(map); - // run once per map instance + if (!onReady) return undefined; + let cancelled = false; + let delivered = false; + // El efecto de montaje puede correr antes de que el contenedor tenga tamaño. + // Si entregamos el mapa entonces, un `getBounds()` del padre lanza y se queda + // sin bounds: en /fires eso dejaba la suscripcion por viewport sin crear y el + // mapa vacio (0 capas) pese a haber 7470 fuegos. Esperamos a que el mapa este + // listo Y tenga tamaño real; entregamos una sola vez. + const deliver = () => { + if (cancelled || delivered) return; + map.invalidateSize(); + const size = map.getSize(); + if (!size || size.x === 0 || size.y === 0) return; + delivered = true; + onReady(map); + }; + map.whenReady(deliver); + map.on('resize', deliver); + return () => { + cancelled = true; + map.off('resize', deliver); + }; }, [map]); // eslint-disable-line react-hooks/exhaustive-deps return null; }; From 03082a8d55496b5ce7cfa3e7c4e4216cd2e1a771 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 28 Jul 2026 07:49:05 +0200 Subject: [PATCH 2/2] staging: conecta el importador NASA reimplementado al stack El servicio `importer` apuntaba a fires-csv-mongo-import/ (el de 2018, sin Dockerfile) y vivia tras el profile "importer", a la espera de un systemd timer que nunca se creo. Ahora apunta a todos-contra-el-fuego/nasa-importer/, arranca con el stack y hace su ciclo cada 15 minutos por si mismo. El JWT de NASA entra por secrets/importer.staging.env (gitignorado); se anade el .example. Volumen importer-data para los CSV descargados: sin el, cada ciclo se creeria que NASA ha publicado datos nuevos y reimportaria siempre. --- docker-compose.staging.yml | 23 +++++++++++++++-------- secrets/importer.staging.env.example | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 secrets/importer.staging.env.example diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index c19ae46..99faf17 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -138,15 +138,13 @@ services: restart: unless-stopped logging: *default-logging - # Importador NASA FIRMS → escribe activefires en ESTE mongo (no en prod), alimentando el - # matcher en shadow. No arranca con `up` (profile "importer"): lo dispara un systemd timer - # del host cada 15 min con `docker compose run --rm importer`. - # NOTA: requiere crear su Dockerfile en fires-csv-mongo-import/ (fase-3 §2). Hasta entonces, - # este servicio queda declarado pero su build context debe completarse. + # Importador NASA FIRMS → escribe activefires en ESTE mongo (NUNCA en prod), alimentando al + # matcher en shadow. Proceso de larga vida: hace su ciclo cada INTERVAL_MINUTES (15, igual + # que el cron de shiva), no hace falta timer del host. + # El JWT de Earthdata va en secrets/importer.staging.env, nunca en la imagen ni en el repo. importer: - profiles: ["importer"] build: - context: ../todos-contra-el-fuego/fires-csv-mongo-import + context: ../todos-contra-el-fuego/nasa-importer image: tcef-nasa-importer:local container_name: tcef-staging-importer depends_on: @@ -154,10 +152,19 @@ services: condition: service_completed_successfully environment: MONGO_URL: mongodb://mongo:27017/fuegos?replicaSet=rs0 - restart: "no" + INTERVAL_MINUTES: "15" + # Reproduce el `when` de producción (acq_time UTC leído como hora local). Ver + # nasa-importer/README.md § "Zona horaria" antes de cambiarlo a UTC. + FIRE_TIME_TZ: Europe/Madrid + env_file: + - ./secrets/importer.staging.env + volumes: + - importer-data:/data + restart: unless-stopped logging: *default-logging volumes: mongo-data: redis-data: nodered-data: + importer-data: diff --git a/secrets/importer.staging.env.example b/secrets/importer.staging.env.example new file mode 100644 index 0000000..ed07625 --- /dev/null +++ b/secrets/importer.staging.env.example @@ -0,0 +1,20 @@ +# Importador NASA FIRMS — STAGING (testfuegos.comunes.org) +# Copiar a secrets/importer.staging.env y rellenar. GITIGNORADO: nunca commitear el real. +# +# El JWT de NASA Earthdata que usa producción está en la rama `shiva-local-changes` del repo +# todos-contra-el-fuego (fires-csv-mongo-import/nasa-https-downloader.sh, línea `KEY=eyJ…`). +# Se genera/renueva en https://urs.earthdata.nasa.gov/profile → "Generate Token". +# Caduca: comprobar el campo `exp` del JWT (payload base64) antes de dar por buena una avería. +NASA_TOKEN=eyJ0eXAiOiJKV1QiLCJvcmlnaW4iOiJFYXJ0aGRhdGEgTG9naW4i... + +# Zona FIRMS a descargar. Producción usa Global. +ZONE=Global + +# Espejos NRT de NASA, en orden de preferencia. +NASA_SERVERS=3,4 + +# Sentry/GlitchTip. Vacío en staging (el GlitchTip de tesla da 502 ahora mismo). +SENTRY_DSN= + +# Guardarraíl: aborta el borrado si un ciclo se llevaría más de este % de `activefires`. +MAX_DELETE_RATIO=0.9