diff --git a/.meteor/packages b/.meteor/packages index ff3104c..bb09bc7 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -54,3 +54,4 @@ nspangler:autoreconnect quave:synced-cron # lmachens:kadira nimble:restivus@0.8.12 +underscore@1.6.4 diff --git a/.meteor/versions b/.meteor/versions index 509413d..08a35df 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -120,7 +120,7 @@ themeteorchef:bert@1.1.0 tmeasday:check-npm-versions@0.3.2 tracker@1.3.4 typescript@5.6.3 -underscore@1.6.2 +underscore@1.6.4 url@1.3.5 vjrj:piwik@0.3.1 webapp@2.0.4 diff --git a/imports/startup/server/accounts/oauth.js b/imports/startup/server/accounts/oauth.js index 545519a..bc541b4 100644 --- a/imports/startup/server/accounts/oauth.js +++ b/imports/startup/server/accounts/oauth.js @@ -4,10 +4,12 @@ import { ServiceConfiguration } from 'meteor/service-configuration'; const OAuthSettings = Meteor.settings.private.OAuth; if (OAuthSettings) { - Object.keys(OAuthSettings).forEach((service) => { - ServiceConfiguration.configurations.upsert( + // Meteor 3: sync Mongo write-methods are gone on the server; use *Async. + // Top-level await is supported in eager server modules. + for (const service of Object.keys(OAuthSettings)) { + await ServiceConfiguration.configurations.upsertAsync( { service }, { $set: OAuthSettings[service] }, ); - }); + } } diff --git a/imports/startup/server/email.js b/imports/startup/server/email.js index 42752cd..8caf2f3 100644 --- a/imports/startup/server/email.js +++ b/imports/startup/server/email.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; import nodemailer from 'nodemailer'; -import { MailTime } from 'meteor/ostrio:mailer'; +import MailTime from 'meteor/ostrio:mailer'; import i18n from 'i18next'; import isMaster from './isMaster'; @@ -48,7 +48,8 @@ if (isMailServerMaster) { concatDelimiter: hr + '

{{{subject}}}

', // Start each concatenated email with it's own subject /* eslint-enable */ // concatThrottling: 30, - template: MailTime.Template // Use default template + // Mail-Time 2.x removed the static MailTime.Template; omitting `template` + // uses the built-in default ('{{{html}}}'). (debt: richer wrapper template) }); } else { console.log('I\'m a mail client'); diff --git a/imports/startup/server/facts.js b/imports/startup/server/facts.js index 0c75843..02781f7 100644 --- a/imports/startup/server/facts.js +++ b/imports/startup/server/facts.js @@ -2,8 +2,4 @@ import { Roles } from 'meteor/alanning:roles'; import { Meteor } from 'meteor/meteor'; -Facts.setUserIdFilter((userId) => { - const user = Meteor.users.findOne(userId); - // console.log(`User roles: ${user.roles}`); - return Roles.userIsInRole(userId, ['admin']); -}); +Facts.setUserIdFilter(userId => Roles.userIsInRole(userId, ['admin'])); diff --git a/imports/startup/server/fibers.js b/imports/startup/server/fibers.js deleted file mode 100644 index ff96265..0000000 --- a/imports/startup/server/fibers.js +++ /dev/null @@ -1,7 +0,0 @@ -// Workaround for: https://github.com/meteor/meteor/issues/9796 -// https://github.com/meteor/meteor/issues/9796#issuecomment-381676326 -// https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129 - -import Fiber from 'fibers'; - -Fiber.poolSize = 1e9; diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index 52d2b81..0e69fa7 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -1,6 +1,5 @@ import './ravenLogger'; import './catchExceptions'; -import './fibers'; import './i18n'; import './accounts'; import './api'; diff --git a/imports/startup/server/migrations.js b/imports/startup/server/migrations.js index 746a894..92301ad 100644 --- a/imports/startup/server/migrations.js +++ b/imports/startup/server/migrations.js @@ -14,7 +14,7 @@ import Notifications from '/imports/api/Notifications/Notifications'; import ActiveFiresUnion from '/imports/api/ActiveFiresUnion/ActiveFiresUnion'; import { Mongo } from 'meteor/mongo'; -Meteor.startup(() => { +Meteor.startup(async () => { // https://github.com/percolatestudio/meteor-migrations Migrations.config({ @@ -255,7 +255,12 @@ Meteor.startup(() => { }); // Set createdAt in users & subs - Migrations.migrateTo('latest'); + // Meteor 3: migrateTo is async now. + // NOTE: the individual up() bodies below still use SYNC Mongo — they only run + // on a DB whose migration version is behind. Production data is restored from + // rsmain already at the latest version, so they never execute. If migrations + // must ever run on a truly-fresh DB, their up() bodies need async conversion. + await Migrations.migrateTo('latest'); // Migrations.migrateTo('14,rerun'); }); diff --git a/imports/startup/server/subsUnion.js b/imports/startup/server/subsUnion.js index 2643359..0c78331 100644 --- a/imports/startup/server/subsUnion.js +++ b/imports/startup/server/subsUnion.js @@ -11,7 +11,7 @@ import { isMailServerMaster } from '/imports/startup/server/email'; // sudo apt-get install libcairo2-dev libjpeg-dev libgif-dev -Meteor.startup(() => { +Meteor.startup(async () => { if (!isMailServerMaster) { console.log('We only process subsUnion in master'); return; @@ -35,8 +35,8 @@ Meteor.startup(() => { const noNoisy = sub => sub; - const process = (isPublic) => { - const subscribers = Subscriptions.find().fetch(); + const process = async (isPublic) => { + const subscribers = await Subscriptions.find().fetchAsync(); const result = calcUnion(L, subscribers, isPublic ? addNoisy : noNoisy, true); const union = result[0]; const bounds = result[1]; @@ -74,9 +74,9 @@ Meteor.startup(() => { }; // FIXME, take care of object size: // https://stackoverflow.com/questions/10827812/what-is-the-length-maximum-for-a-string-data-type-in-mongodb-used-with-ruby - SiteSettings.upsert({ name: `subs-${publicl}-union` }, unionSet, { multi: false }); - SiteSettings.upsert({ name: `subs-${publicl}-union-bounds` }, boundsSet, { multi: false }); - SiteSettings.upsert({ name: 'subs-union-count' }, sizeSet, { multi: false }); + await SiteSettings.upsertAsync({ name: `subs-${publicl}-union` }, unionSet, { multi: false }); + await SiteSettings.upsertAsync({ name: `subs-${publicl}-union-bounds` }, boundsSet, { multi: false }); + await SiteSettings.upsertAsync({ name: 'subs-union-count' }, sizeSet, { multi: false }); if (debug) console.log(`${Publicl} subscription union calculated`); } else { console.log('Subscription union failed!'); @@ -84,40 +84,39 @@ Meteor.startup(() => { }; // At startup, we check if it's necessary to calc subscriptions union again - const currentUnion = SiteSettings.findOne({ name: 'subs-public-union' }); - const lastSubs = Subscriptions.findOne({}, { sort: { updatedAt: -1 } }); - const countUnionSubs = SiteSettings.findOne({ name: 'subs-union-count' }); - const countSubs = Subscriptions.find({}).count(); + const currentUnion = await SiteSettings.findOneAsync({ name: 'subs-public-union' }); + const lastSubs = await Subscriptions.findOneAsync({}, { sort: { updatedAt: -1 } }); + const countUnionSubs = await SiteSettings.findOneAsync({ name: 'subs-union-count' }); + const countSubs = await Subscriptions.find({}).countAsync(); if (currentUnion && lastSubs) { const lastUnionUpdated = currentUnion.updatedAt; const lastSubsUpdated = lastSubs.updatedAt; if (lastUnionUpdated > lastSubsUpdated || !countUnionSubs || countSubs !== countUnionSubs.value) { console.log('Subs union outdated'); - process(true); - process(false); + await process(true); + await process(false); } else { console.log('Subs union up-to-date'); } } - Subscriptions.find({ createdAt: { $gt: new Date() } }).observe({ - added: function newSubAdded() { // doc) { + const recreate = async () => { await process(true); await process(false); }; + + await Subscriptions.find({ createdAt: { $gt: new Date() } }).observeAsync({ + added: async function newSubAdded() { // doc) { if (debug) console.log('Subs added so recreate union'); - process(true); - process(false); + await recreate(); } }); - Subscriptions.find().observe({ - changed: function subsChanged() { // updatedDoc, oldDoc) { + await Subscriptions.find().observeAsync({ + changed: async function subsChanged() { // updatedDoc, oldDoc) { if (debug) console.log('Subs changed so recreate union'); - process(true); - process(false); + await recreate(); }, - removed: function subsRemoved() { // oldDoc) { + removed: async function subsRemoved() { // oldDoc) { if (debug) console.log('Subs removed so recreate union'); - process(true); - process(false); + await recreate(); } }); });