Compare commits

...

2 commits

Author SHA1 Message Date
03082a8d55 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.
2026-07-28 07:49:05 +02:00
e5f7a0f4be fix(maps): entregar el mapa solo cuando tiene tamano real (MapReady)
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).
2026-07-28 07:46:19 +02:00
3 changed files with 57 additions and 10 deletions

View file

@ -138,15 +138,13 @@ services:
restart: unless-stopped restart: unless-stopped
logging: *default-logging logging: *default-logging
# Importador NASA FIRMS → escribe activefires en ESTE mongo (no en prod), alimentando el # Importador NASA FIRMS → escribe activefires en ESTE mongo (NUNCA en prod), alimentando al
# matcher en shadow. No arranca con `up` (profile "importer"): lo dispara un systemd timer # matcher en shadow. Proceso de larga vida: hace su ciclo cada INTERVAL_MINUTES (15, igual
# del host cada 15 min con `docker compose run --rm importer`. # que el cron de shiva), no hace falta timer del host.
# NOTA: requiere crear su Dockerfile en fires-csv-mongo-import/ (fase-3 §2). Hasta entonces, # El JWT de Earthdata va en secrets/importer.staging.env, nunca en la imagen ni en el repo.
# este servicio queda declarado pero su build context debe completarse.
importer: importer:
profiles: ["importer"]
build: build:
context: ../todos-contra-el-fuego/fires-csv-mongo-import context: ../todos-contra-el-fuego/nasa-importer
image: tcef-nasa-importer:local image: tcef-nasa-importer:local
container_name: tcef-staging-importer container_name: tcef-staging-importer
depends_on: depends_on:
@ -154,10 +152,19 @@ services:
condition: service_completed_successfully condition: service_completed_successfully
environment: environment:
MONGO_URL: mongodb://mongo:27017/fuegos?replicaSet=rs0 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 logging: *default-logging
volumes: volumes:
mongo-data: mongo-data:
redis-data: redis-data:
nodered-data: nodered-data:
importer-data:

View file

@ -8,8 +8,28 @@ import { useMap, useMapEvents } from 'react-leaflet';
export const MapReady = ({ onReady }) => { export const MapReady = ({ onReady }) => {
const map = useMap(); const map = useMap();
useEffect(() => { useEffect(() => {
if (onReady) onReady(map); if (!onReady) return undefined;
// run once per map instance 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 }, [map]); // eslint-disable-line react-hooks/exhaustive-deps
return null; return null;
}; };

View file

@ -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