Commit graph

133 commits

Author SHA1 Message Date
570cb49764 fix(subsUnion): drop duplicated programs/server prefix in npm path
All checks were successful
build-image / build (push) Successful in 11m53s
process.cwd() for this process is already /app/programs/server (same
basis WORKER_PATH already relied on), so prefixing 'programs/server/'
again produced .../programs/server/programs/server/npm/node_modules —
still Cannot find module '@turf/circle', just with a longer wrong path.
2026-07-30 09:04:11 +02:00
324936242b fix(subsUnion): resolve turf deps by absolute path, not bare specifier
All checks were successful
build-image / build (push) Successful in 12m9s
The previous side-effect-import fix didn't work: the app's own npm deps
(installed by `meteor build`) live in programs/server/npm/node_modules,
a SIBLING of programs/server/assets, not an ancestor of it. Node's
require() only walks up parent directories looking for node_modules,
so require('@turf/circle') from the worker asset script could never
find it regardless of what gets imported elsewhere in the app — it
kept failing with "Cannot find module '@turf/circle'" even after that
fix was deployed.

calcUnionAsync.js (Meteor-compiled code, which already knows how to
locate the app's npm deps) now resolves the three turf package paths
itself and hands them to the worker via workerData; the worker
requires them by absolute path instead of bare specifier.
2026-07-30 08:48:50 +02:00
50ca9cc6cf fix(subsUnion): stop treating a failed worker call as a valid empty union
All checks were successful
build-image / build (push) Successful in 12m16s
storeUnion checked `typeof union === 'object'` as its "did this work"
guard, but typeof null is also 'object' — so a worker call that failed
(caught upstream, leaving union as its initial null) looked identical
to a legitimate "zero valid subscriptions" result, and got silently
stored as the string "null" instead of being treated as a failure.
This is exactly what corrupted subs-public-union/subs-private-union on
staging just now, while chasing the missing-turf-deps bug.

storeUnion is now only called once calcUnionAsync has actually
resolved; process() and incrementalAdd() catch failures themselves and
skip storing anything, leaving the previous (still valid) union alone.
2026-07-30 08:29:21 +02:00
4879d3482d fix(subsUnion): force-bundle turf deps used only by the worker thread
Some checks failed
build-image / build (push) Has been cancelled
Meteor's build only includes npm packages it sees imported/required
somewhere in its own traced module graph. private/workers/unionWorker.js
is a plain asset (loaded at runtime via new Worker(), never
import/require'd from Meteor-compiled code), so @turf/circle,
@turf/union and @turf/truncate got silently dropped from
programs/server/node_modules — the worker crashed on every call with
"Cannot find module '@turf/circle'", which incrementalAdd/process
swallowed and stored as a "null" union (typeof null === 'object', so
the null-check that guards against failed unions doesn't catch it).
Side-effect imports here force Meteor to bundle them.
2026-07-30 08:27:40 +02:00
110ad66e86 feat(subsUnion): incremental union merge for new subscriptions
All checks were successful
build-image / build (push) Successful in 13m24s
A full recreate() over 7k+ subscriptions takes ~20 minutes even in a
worker thread — fine for not blocking the site, but means a new zone
takes ages to show up on the map. Since union only grows when adding a
circle, a new subscription can just be merged into the union already
stored (one turf.union call) instead of rebuilding the whole chain.

changed/removed still trigger a full recreate() (union can't be
"subtracted" from safely), and incrementalAdd falls back to a full
recreate whenever the stored count isn't exactly one behind what's
expected, rather than risk merging into stale state. Both paths now
share one serialized queue (FIFO for adds, coalesced for recomputes)
so they never race on the same stored union.
2026-07-30 08:07:00 +02:00
fbb746fba2 fix(subsUnion): move geo-union math to a worker thread, not just yields
All checks were successful
build-image / build (push) Successful in 13m13s
The previous fix (yielding to the event loop between turf.union calls)
was not enough: once the merged polygon gets complex with thousands of
subscriptions, a single turf.union call can itself take seconds, and
yielding between iterations doesn't help when one iteration alone
blocks that long. Confirmed in staging: the site was still fully
unresponsive (Cloudflare 524, curl hanging 2+ minutes, healthcheck
failing) while a recompute ran.

Validation/decoration (addNoisy/noNoisy, cheap) stays on the main
thread; the actual circle+union chain now runs in a worker_thread
(private/workers/unionWorker.js, plain CommonJS so meteor build copies
it verbatim instead of compiling it) so the main event loop serving
DDP/HTTP is never blocked by it, regardless of how slow any single
turf call gets.
2026-07-30 07:48:17 +02:00
3d52e2f709 docs(subsUnion): note why legacy telegram subs are skipped, not errors
All checks were successful
build-image / build (push) Successful in 11m55s
2026-07-30 06:58:09 +02:00
b4e5511cd0 fix(subsUnion): stop blocking DDP on subscription union recompute
Every subscription add/change/remove recomputed the full geo union
over all 7k+ subscriptions with a synchronous turf.union chain,
freezing the single Node event loop (and thus DDP/HTTP) for minutes.
The same recompute also runs at startup ("Subs union outdated"),
so every restart froze the site too.

calcUnionAsync yields to the event loop periodically during the
union chain, and subsUnion.js now fires recomputes without blocking
Meteor.startup or the observer callbacks, serializing overlapping
triggers instead of stacking them.
2026-07-30 06:36:37 +02:00
6b6f02d92d quality: web debt batch (tests runner, FireContainer, rate-limit, maps, i18n)
Independent-of-prod quality debt from PENDIENTE.md §2:

- test: migrate broken Jest -> meteortesting:mocha. Tests rewritten to chai +
  Meteor 3 async APIs, moved to test/server/ (server-only). test/server/
  00-setup.test.js re-runs the collection2/accounts init that `meteor test`
  skips (no server/main.js). New comments method + mediaAnalyzers coverage.
  Dropped rest.test.js (removed meteor/http; covered by smoke/). 36 passing.
- fix: scope FireContainer read by the URL _id on the archive route instead of
  a selector-less FiresCollection.findOne() (imports/ui/pages/Fires/Fires.js).
- feat: rate-limit abusable publications via rateLimitSubscriptions (fireFrom*
  and comments.forReference 5/1000ms; geo subs 10/1000ms).
- perf: append loading=async to the Google Maps loader URL (Gkeys.js).
- deps: meteor-accounts-t9n 2.0 -> 2.6 (no gl build -> keep gl->es fallback,
  documented); add 3 missing gl/common.json keys (0 missing now).
- deps: drop jest/babel/enzyme, add chai.
2026-07-21 22:59:06 +02:00
12bdbe8fed deps: i18next 10 -> 23, react-i18next 7 -> 14
Modernizes the whole i18n stack:
- 48 translate([], {wait:true}) / translate() HOCs -> withTranslation()
- react.wait:true -> react.useSuspense:false
- whitelist -> supportedLngs; added compatibilityJSON: 'v3' so our
  natural-language keys + v3 _plural layout keep working (custom
  separators ss/eth/dj preserved)
- backends: xhr -> i18next-http-backend (client), sync-fs ->
  i18next-fs-backend (server); dropped i18next-localstorage-cache
  (was enabled:false); languagedetector 2 -> 8
- ReSendEmail: <Interpolate> (removed in v10) -> <Trans values={{email}}/>,
  dropped the removed bare t export
- saveMissing handler signature (lngs, ns, key, fallbackValue)

Silences the per-component Translate/I18n legacy-context warnings.
Browser-verified es/en switch and <Trans> interpolation on /fires;
REST smoke byte-identical.
2026-07-18 06:28:41 +02:00
62ac2fbd9c sentry: tunnel client events through the app to dodge Cloudflare's 503
GlitchTip is behind Cloudflare, which answers the browser's cross-site ingest
POSTs with 503 (no CORS headers -> 'Failed to fetch'); server-side requests
pass. The browser SDK now posts envelopes same-origin to /sentry-tunnel, and
the server forwards them to GlitchTip:
- imports/startup/server/sentryTunnel.js: WebApp handler that relays the raw
  envelope to <dsn>/api/<project>/envelope/?sentry_key=<key> over IPv4
  (family:4 avoids Happy-Eyeballs picking Cloudflare's unroutable IPv6 on
  IPv4-only hosts). GlitchTip authenticates by the sentry_key query, so the
  key is derived from the DSN and passed explicitly.
- client ravenLogger: tunnel: '/sentry-tunnel'.
Verified: POST /sentry-tunnel -> 200 (envelope reaches GlitchTip).
2026-07-17 18:17:47 +02:00
4ca7e198d3 meteor3: raven -> @sentry/node + @sentry/browser
flowkey:raven (Sentry legacy SDK) is dead on Meteor 3 and, with the old
sentry.comunes.org DSN unreachable, spammed the boot log with 502s on every
exception. Replaced by the modern SDKs (8.x) behind the same ravenLogger.log()
facade so the 6 call sites are unchanged. Empty DSN -> plain console logger
(same behavior as before).

End-to-end verified against a real backend: GlitchTip deployed on aaron
(Sentry-compatible, fits in ~1.5GB vs Sentry's 16GB), fronted at
sentry.comunes.org. A test exception sent from the dev server appeared in
GlitchTip within seconds. REST smoke byte-identical (12/12).
2026-07-16 12:20:02 +02:00
1f1f5c697d meteor3: port all 18 migration up() bodies to async
percolate:migrations 2.0.1 awaits async up(), so historical migrations
now run on Meteor 3: fetchAsync + for..of instead of cursor forEach,
insert/update/remove -> *Async, _ensureIndex -> createIndexAsync,
Accounts.createUser -> createUserAsync, awaited rawCollection indexes.

Verified: empty Mongo 7 DB migrates 0->18 cleanly (indexes + industry
registries created, control unlocked at v18); pre-marking version=18 is
no longer needed (UPGRADE.md updated). REST smoke stays byte-identical.
2026-07-14 11:36:30 +02:00
eb3aec82ae meteor3: purge dead client packages — web UI renders on 3.1
alanning:roles removed (client crashed the whole bundle; plain user.roles
checks instead), selaias:cookie-consent replaced by in-repo React banner,
publish-performant-counts vendored with countAsync, Meteor.autorun dropped
(App)/Tracker.autorun (FiresMap), and the map publications not covered by
the REST smoke (activefiresmyloc, activefiresunionmyloc, fireAlerts,
oauth.verifyConfiguration) converted to async APIs.

Verified in browser: / and /fires render with map + cookie banner, zero
uncaught exceptions. REST smoke byte-identical (12/12).
2026-07-14 11:32:19 +02:00
0ff9848cd4 meteor3: re-enable fixtures and sitemaps with async/Meteor-3 implementations
fixtures: drop @cleverbeagle/seeder (sync Mongo, unmaintained) for a small
idempotent async seeder (same dev accounts). sitemaps: drop dead
gadicohen:sitemaps for a WebApp.connectHandlers /sitemap.xml with the same
static page list (the per-fire section was already disabled). Verified on
dev boot: 6 users ensured, sitemap serving; REST smoke byte-identical.
2026-07-14 07:06:07 +02:00
b37069c3e5 WIP(meteor3): server BOOTS on 3.1 + Mongo 7; restivus async-patched
Major milestone: the Meteor 3.1 server boots and runs against dockerized
MongoDB 7, and the REST framework responds (status/uptime OK).

- collection2 v4: import its eager entry 'meteor/aldeed:collection2/static.js'
  from new eager files server|client/00-collection2-init.js so main.js runs and
  patches attachSchema before collections load (v4 is fully lazy, no main module).
- fixtures.js disabled: @cleverbeagle/seeder uses sync Mongo, no Meteor 3 support
  (dev fixtures, not needed for smoke). Debt.
- sitemaps.js disabled: gadicohen:sitemaps@0.0.17 pre-0.9 API, no 'sitemaps'
  global on Meteor 3. Debt (SEO).
- Vendored restivus patched for async endpoints: route handler is async and
  awaits _callEndpoint; _callEndpoint awaits the action + auth/role checks.

NEXT: Rest.js endpoints + helpers (countRealFires/firesUnion/whichAreFalsePositives/
fireFromHash/subscriptionsInsert/upsertFalsePositive) still use sync Mongo
(.count()/.findOne()/.fetch()/.insert()/.upsert()) -> convert to *Async, then
smoke test against Mongo 7.
2026-07-14 06:11:00 +02:00
25dc1b99c0 WIP(meteor3): boot progresses past linker + several async fixes
Past the client-bundle underscore linker (pin underscore@1.6.4) and now working
through the server async/await migration on Meteor 3.1 + Mongo 7:

- Removed fibers (imports/startup/server/fibers.js + import) — gone in Meteor 3.
- accounts/oauth.js: upsert -> upsertAsync (top-level await).
- migrations.js: startup async + await Migrations.migrateTo (async in 2.x).
  mongo7 marked at version 18 so historical up() bodies (still sync Mongo) don't
  run — prod data restores already-migrated. Documented.
- subsUnion.js: fully async (fetchAsync/findOneAsync/countAsync/upsertAsync,
  observeAsync with async callbacks).
- facts.js: dropped dead sync findOne.
- email.js: ostrio:mailer 2.5 is a default export (was named import); dropped
  removed static MailTime.Template (built-in default '{{{html}}}').

NEXT wall + remaining chain (multi-session):
1. aldeed:collection2@4.2.0 needs simpl-schema 3.x (app has 1.x) -> 'attachSchema
   is not a function'. Requires upgrading npm simpl-schema to 3.x and migrating
   all collection schemas (SimpleSchema.RegEx.Id etc.) across ~8 files.
2. Rest.js + helpers (countRealFires/firesUnion/whichAreFalsePositives/
   fireFromHash/subscriptionsInsert/upsertFalsePositive) -> *Async.
3. Patch vendored restivus to await async endpoint handlers.
4. methods/publications/comments to async; cron SyncedCron(quave)/Facts imports.
5. alanning:roles@1.2.10 + gadicohen:sitemaps@0.0.17 warn incompatible -> bump.
6. React 16 -> 18 render root.

Run with: NODE_OPTIONS='--dns-result-order=ipv4first --no-network-family-autoselection'
MONGO_URL='mongodb://localhost:27019/fuegos?replicaSet=rs0'
2026-07-13 23:46:45 +02:00
cd570b9d9c escala 2+3: Meteor 1.8.3 -> 2.3 (Mongo 3.2 compatible), dead-package remediation
Reaches Meteor 2.3 building + running against Mongo 3.2, REST smoke test
byte-identical to the 1.6.1.1 baseline (all 12 Flutter endpoints green).

Dead/abandoned Atmosphere packages removed or replaced (the upgrade blockers):
- arkham:comments-ui (no Meteor 2.x build; pinned accounts-password@1.x):
  reimplemented the fire-page comments as a React feature:
    imports/api/Comments/ (collection, server methods, publication, media
    analyzers, new-fire-comment email) + imports/ui/components/Comments/CommentsBox.
    Comment text now rendered as safe plain text + image/youtube embed (was
    markdown-to-HTML). Wired into Fires.js; sitemaps.js + migration v11 updated
    to the new collection. Old Blaze/startup comments files deleted.
- nimble:restivus (REST API; pinned accounts-password@1.3.3, CoffeeScript source
  that crashes this build host): vendored as a local package
  packages/nimble-restivus with the .coffee precompiled to plain JS and the
  accounts-password constraint loosened to 2.x. REST behavior unchanged
  (verified by smoke test). This also dropped the entire iron:router stack.
- maximum:server-transform (+ peerlibrary:*, meteorhacks:zones/inject-initial):
  unused; removal broke Meteor.publishTransformed in FalsePositives publications
  -> replaced with plain Meteor.publish (no transform was configured).
- less, markdown (no source files), and the dead test stack
  (meteortesting:mocha, practicalmeteor:chai, xolvio:cleaner) which transitively
  pulled coffeescript@1.0.17 — the build plugin that crashed meteor-tool
  (node_contextify assertion) on this machine. Removing it unblocked the build.
- fourseven:scss 4.5.4 -> 4.14.1 (node-sass 4.5.3 doesn't build on node 12).

npm-mongo driver at 2.3 is 3.9.x — still compatible with the production Mongo
3.2 replica set.
2026-07-13 22:24:09 +02:00
dc8a05a0d4 notif: remove code migrated to tcef-notifications microservice
The push/email notification processing now lives in the tcef-notifications
service (fases 1a-1c). Removed from the web:
- imports/startup/server/notificationsObserver.js (observe Notifications -> processNotif)
- imports/modules/server/notificationsProcess.js (node-gcm push + notif emails)
- the 'Process pending notif' SyncedCron job in cron.js
- node-gcm dependency (dead Google API since jun-2024)

subsUnion.js is KEPT: it feeds the subs-public-union SiteSettings that the REST
API (status/subs-public-union) serves to the Flutter app; it is not part of the
notifications pipeline.

DEPLOY ORDERING (see UPGRADE.md): production must not run this build until the
tcef-notifications service is emitting in prod — otherwise notifications stop.
REST smoke test green (byte-identical).
2026-07-13 19:45:13 +02:00
296dab4f38 smoke: REST API regression harness + baseline snapshots (Meteor 1.6.1.1)
Adds a standalone Node smoke test (smoke/) that exercises every REST endpoint
consumed by the Flutter app against a seeded local dev server and compares
responses to committed snapshots. This is the safety net for the Meteor upgrade:
it must stay byte-identical after every escala.

- smoke/seed.js: deterministic Mongo seed (fixed ObjectIds, geo indexes)
- smoke/run.js: calls endpoints, normalizes volatile fields, diffs snapshots
- smoke/smoke.sh: seed + run wrapper
- smoke/snapshots/: baseline captured on Meteor 1.6.1.1
- IPGeocoder.js: degrade gracefully when MaxMind DB absent (dev boot)
- settings-development.json: dev-only internalApiToken to enable the REST API
- .meteorignore: exclude smoke/ from the Meteor server build
2026-07-13 19:42:55 +02:00
2a31435135 Refactor server startup: elimina segfaults, añade leaflet-workaround
Retira import './segfaults' (workaround de crash obsoleto) y añade
leaflet-workaround.js (shims global window/document/navigator para
render de Leaflet en servidor). Ajustes menores en publications de
FalsePositives y subsUnion.
2026-07-12 23:26:16 +02:00
vjrj
6abe668740 Added fires union (wip) 2018-11-18 11:48:03 +01:00
vjrj
7b5f17fbe8 Added activeFiresUnion (wip) 2018-10-28 20:27:38 +01:00
vjrj
8b598fab7c Disabled fires render 2018-10-15 06:02:05 +02:00
vjrj
cdc3bbdd5b Notif stats to cron process 2018-09-13 10:08:26 +02:00
vjrj
53a7c3be21 Process also pending emailNotifications 2018-09-11 15:27:10 +02:00
vjrj
3d059287ae Notif process also in cron 2018-09-11 14:42:31 +02:00
vjrj
a208eb7ea1 More work with unify, circle/square 2018-09-11 11:40:17 +02:00
Vicente J. Ruiz Jurado
cfe6c2f570 Better mobile notification desc 2018-08-03 09:05:14 +02:00
Vicente J. Ruiz Jurado
20359a79e3 FCM error handling with Meteor.bind 2018-08-03 08:20:20 +02:00
Vicente J. Ruiz Jurado
8780edc832 Correct ObjectId in fcm message 2018-08-03 08:04:43 +02:00
Vicente J. Ruiz Jurado
dc0df7cf32 Master sends only to mobiles 2018-08-02 23:13:15 +02:00
Vicente J. Ruiz Jurado
bf926514c9 Mobile notifications 2018-08-02 12:42:19 +02:00
vjrj
eebbdda064 Rest api updated 2018-06-14 17:55:38 +02:00
vjrj
9dbd97009b Improved rest methods 2018-06-12 10:21:55 +02:00
vjrj
ec0edf4475 More rest methods 2018-06-12 08:05:44 +02:00
vjrj
eefa586007 Return unauth 2018-06-12 06:08:25 +02:00
vjrj
b53e5d0e36 Log ravenLogger enabled/disabled 2018-05-22 18:19:37 +02:00
vjrj
d30385b49e Disable raven when not configured 2018-05-21 17:42:37 +02:00
vjrj
e36dda74db Better api logs 2018-05-21 15:43:07 +02:00
vjrj
f144c986b7 Added fire stats in zone to API 2018-05-20 17:45:25 +02:00
vjrj
22534ddb7e Subs union only in master 2018-05-10 22:39:50 +02:00
vjrj
2d19778553 Fallback moved. Index points to telegran en bot 2018-05-10 09:00:05 +02:00
vjrj
984ce8531d Uptime in status api 2018-05-03 20:32:43 +02:00
vjrj
2d0c8f664b Do subsUnion at startup only if necessary 2018-05-03 16:45:01 +02:00
vjrj
08abdffd69 Added fibers workaround 2018-05-03 02:20:33 +02:00
vjrj
9961e56ddc Removed some coments 2018-05-03 01:37:22 +02:00
vjrj
a118b91b79 Added better server log errors 2018-05-03 01:15:33 +02:00
vjrj
8dc1ec63f2 Added basic rest api 2018-04-12 10:45:20 +02:00
vjrj
09e78a0b8f Segfauls for debug server issues 2018-04-09 19:24:08 +02:00