From feaf66fe342bb78db6babe1bb37b0be490daea46 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 14 Jul 2026 06:52:08 +0200 Subject: [PATCH] meteor3: web Fires publications to async (findOneAsync/countAsync/awaited firesUnion) fireFromId, fireFromAlertId, fireFromActiveId and fireFromHash now use the async collection APIs and async publish handlers (so try/catch catches rejections). falsePositivesMyloc/industriesMyloc/comments.forReference are cursor-only and needed no change. Verified over raw DDP against the seeded dev Mongo 7; REST smoke stays byte-identical (12/12). --- UPGRADE.md | 16 +++++++++++++--- imports/api/Fires/server/publications.js | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index c6fb301..bad25c8 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -224,10 +224,20 @@ MONGO_CONTAINER=tcef-mongo7 MONGO_SHELL=mongosh MONGO_PORT=27019 ./smoke/smoke.s - **fixtures.js / sitemaps.js** disabled (sync-only `@cleverbeagle/seeder` / pre-0.9 `gadicohen:sitemaps`) — not on the REST path. Debt. +### Web-UI async migration (beyond the REST contract) +- ✅ **Fires publications → async** (`fireFromId`, `fireFromAlertId`, + `fireFromActiveId`, `fireFromHash`): `findOne`→`findOneAsync`, + `count()`→`countAsync()`, `firesUnion` awaited, handlers `async` so the + try/catch actually catches rejections. Verified over raw DDP (all subs + `ready`, docs flow; fire + falsePositives docs delivered for the seeded + fire). `falsePositivesMyloc` / `industriesMyloc` / `comments.forReference` + needed **no change** — they return bare `find()` cursors (still sync-safe on + Meteor 3). `subscriptions.*` methods were already `*Async`. +- Note: the module-level `new Counter(...)` (natestrauser:publish-performant-counts) + behind `falsePositivesTotal` boots fine; the publication itself is unused by + the current UI — watch it if re-enabled. + ### Still TODO before the web (not just REST) is fully deployable on 3.x -- Web publications (`fireFromId`, `fireFromAlertId`, `falsePositivesMyloc`, - `industriesMyloc`) + remaining methods (comments, `subscriptions.remove`) → - `*Async` (not exercised by the smoke). - **React 16 → 18** render root + verify ancient react-* libs. - Re-enable dev fixtures / sitemaps / email default template with async ports. - SCSS `@import`→`@use`, `lighten`/`darken`→`color.adjust` (dart-sass deprecations). diff --git a/imports/api/Fires/server/publications.js b/imports/api/Fires/server/publications.js index 9641f6e..2f56979 100644 --- a/imports/api/Fires/server/publications.js +++ b/imports/api/Fires/server/publications.js @@ -76,14 +76,14 @@ const findOrCreateFire = async (obj) => { return findFire(obj); }; -Meteor.publish('fireFromAlertId', function fireFromAlertId(_id) { +Meteor.publish('fireFromAlertId', async function fireFromAlertId(_id) { try { check(_id, String); // console.log(`Looking for alert fire ${_id}`); - const fire = FireAlertsCollection.findOne(new Meteor.Collection.ObjectID(_id)); + const fire = await FireAlertsCollection.findOneAsync(new Meteor.Collection.ObjectID(_id)); if (fire) { // console.info(`Active fire found: ${_id}`); - return findOrCreateFire(fixConfidence(fire)); + return await findOrCreateFire(fixConfidence(fire)); } console.info(`Alert fire not found: ${_id}`); // Not found in active fires! @@ -94,14 +94,14 @@ Meteor.publish('fireFromAlertId', function fireFromAlertId(_id) { } }); -Meteor.publish('fireFromActiveId', function fireFromActiveId(_id) { +Meteor.publish('fireFromActiveId', async function fireFromActiveId(_id) { try { check(_id, String); // console.log(`Looking for active fire ${_id}`); - const fire = ActiveFiresCollection.findOne(new Meteor.Collection.ObjectID(_id)); + const fire = await ActiveFiresCollection.findOneAsync(new Meteor.Collection.ObjectID(_id)); if (fire) { // console.info(`Active fire found: ${_id}`); - return findOrCreateFire(fixConfidence(fire)); + return await findOrCreateFire(fixConfidence(fire)); } console.info(`Active fire not found: ${_id}`); // Not found in active fires! @@ -112,14 +112,14 @@ Meteor.publish('fireFromActiveId', function fireFromActiveId(_id) { } }); -Meteor.publish('fireFromId', function fireFromId(_id) { +Meteor.publish('fireFromId', async function fireFromId(_id) { try { check(_id, String); // console.log(`Looking for archive fire ${_id}`); const fire = FiresCollection.find(new Meteor.Collection.ObjectID(_id)); - if (fire.count() !== 0) { + if (await fire.countAsync() !== 0) { // console.info(`Archive fire found: ${_id}`); - const union = firesUnion(fire); + const union = await firesUnion(fire); const falsePos = whichAreFalsePositives(FalsePositives, union); const industries = whichAreFalsePositives(Industries, union); return [fire, falsePos, industries]; @@ -163,11 +163,11 @@ export async function fireFromHash(fireEnc, params) { * return fire; */ } -Meteor.publish('fireFromHash', function fireFromHashFunc(fireEnc, params) { +Meteor.publish('fireFromHash', async function fireFromHashFunc(fireEnc, params) { check(fireEnc, String); check(params, Object); try { - return fireFromHash(fireEnc, params); + return await fireFromHash(fireEnc, params); } catch (e) { console.warn(e); logUrl(fireEnc, params);