Looking for help migrating packages to Meteor 3.0

I don’t have anything to do with that, so the only thing I could do is annoy other people about it. I think Meteor Software manages those repositories and has the option to publish those packages.

I understand, thanks! I will first attempt to find an active maintainer outside Meteor Compat.

:alarm_clock: :alarm_clock::alarm_clock: Time for some new updates

  • Instead of migrating xolvio:cleaner, I opted to pull out the resetDatabase function and asyncify it. Here’s the code for it, in case someone needs it:
export const resetDatabase = async function (options = {}) {
    if (process.env.NODE_ENV !== "development") {
        throw new Error(
            "resetDatabase is not allowed outside of a development mode. " +
                "Aborting."
        );
    }

    let excludedCollections = ["system.indexes"];
    if (options.excludedCollections) {
        excludedCollections = excludedCollections.concat(
            options.excludedCollections
        );
    }

    const db =
        options.db || MongoInternals.defaultRemoteCollectionDriver().mongo.db;
    const collections = await db.collections();

    const appCollections = _.reject(collections, function (col) {
        return (
            col.collectionName.indexOf("velocity") === 0 ||
            excludedCollections.indexOf(col.collectionName) !== -1
        );
    });

    for await (const col of appCollections) {
        await col.deleteMany({});
    }
};

Please start out trying the beta packages and report any problems you find.

1 Like

@harry97 Thanks for mentioning :wink: Got a local copy of an async version of meteor-push running on 2.14 with no async warnings.

BTW @harry97 I even forgot the Beta code of meteor-push was already updated with async functions a couple of months back :joy:

Yeah, that saves us a great chunk of time already :laughing: couldn’t you say that earlier.

EDIT: Can you start a PR with that branch and release a beta version to atmosphere so we can test things out?

I wrote a blogpost about my latest OSS endeavors regarding Meteor 3.0 packages migration.

Thanks to Daniel & Trusted Care I was able to migrate many packages to async that we use in our application:

3 Likes

Hello guys, long time no see. There has not been much going on lately but there’re few things I’d like to draw your attention to:

  • Async migration by harryadel · Pull Request #112 · msavin/SteveJobs · GitHub - I’ve been working on updating this package, please give it a go and let me know if you run into any issues.
  • Add Meteor 3.0 Compatibility by harryadel · Pull Request #1 · itgenio/meteor-persistent-session · GitHub - If you’ve been using any of Cult of Coders Persistent Session, then I’d recommend that you switch over to @afrokick fork, they’ve already solved most of the conflicts and only needed a little push.
  • Simple Schema Async Compatibility - As it currently stands, simple schema isn’t async friendly as nearly all the computed fields/values can’t run async operations. I’ve tried to get my hands dirty with it but any simple async change bubbles up and forces you to modify the entire package. It’s not a simple task and requires time which I’m unable to dedicate right now. @jkuester will be able to dedicate time for it in the near future so please if anyone has sometime let us know so we can coordinate it. Sames goes for Autoform, it also needs some serious work. Simple Schema / Autoform / Collection 2 - the trifecta, all work in harmony and currently only collection2 has been migrated to async.
2 Likes

I never wanted to comment on this, but for what it’s worth, here is my opinion: schema checks, whether in Meteor/MongoDB or any other system, should not involve async calls to HTTP endpoints or to the database. Just think about a schema check on an array of items, what if you have a custom function hitting the database for each item? In 12 years working with Meteor it has not occurred to me that one could/should be going for this kind of approach. Gee, Simple Schema, while great, is enough of a slow hog as it is.

I personally see it as a great ergonomic adage, made possible back in the day because of the synchronous isomorphic code / Fibers everywhere / “so why not” kind of thinking. Which, I assume, led many to use this pattern. But maybe it’s one of those things that should now be left behind.

While I can see why and where it would be useful, it looks like an antipattern and maybe it should be highlighted as such; if these async calls are indeed required, maybe they actually belong to a different layer (authorisation, for instance). But that is just me, and likely I don’t have the full perspective on why this is a good idea.

Anyway, a more useful question is: would some extra sponsorship/funding help move things forward, whatever the decision regarding Simple Schema?

2 Likes

Deciding to move a “validation” to another part of your code because it is async or not is not really about being good pattern or anti pattern or good thinking - in simple terms, it is called a tool/library/framework limitation.

[Addendum]

I should have made it clear that my point was in reference to using Simple Schema in conjunction with Collection2. In this case, I stand by what I said: it is an antipattern to make async calls while schema checking a document about to be inserted or modified in said MongoDB. If you can point me to a database system allowing this pattern as standard, I will stand corrected.

The rest of use cases, where Simple Schema is used for validating method arguments and other such use cases, yes, I have no comment there, though personally I avoid that too.

Nothing changes the fact that Collection2 is now being held back unnecessarily.

1 Like

Not sure if this was intended as a reply to my post. If so, I asked for an example of “a database system”. Collection2 + SimplSchema was (and still is) meant to fulfil the role of schema enforcement in the context of database operations. Allowing async calls in this context is simply handing over a big footgun to users, some of whom won’t have a second thought about race conditions and other such troublesome concepts.

Again, these are tools/libraries. It depends on developers how they will use or mis-use a tool. I can use it differently on how you can use it.

How it works is simple as indicated in the example of an async validator posted above. But I will repeat the example here:

E.g.
When inserting a new document to Collection A, it requires a referenceId from Collection B. Therefore, it is required that the referenceId must exist before inserting.

There are multiple ways to do this just like:

  1. Adding a check everytime an insert/update is done
  2. Add it in a shared insert/update function
  3. Add it in the schema validation

Since you are looking for something built-in, you can do the example above in Oracle DB using a foreign key constraint: constraint

Don’t get me wrong, I understand all the benefits you have listed. But…

Oh, there is no shortage in the Meteor ecosystem of such examples, with insecure and autopublish being just a couple that come to mind. The result is that the internet is full of complaints of Meteor being insecure :man_shrugging:

I am more than familiar with the concept.

My point was that, since async custom validator functions in SimplSchema make it difficult to update Collection2, maybe it’s a good idea to at least park the attempt for now. Your suggestion in the other thread, to have a preliminary release, is spot on.

Here’s our current use case and let me know how you’d handle it:

We use a (reactive) AutoForm form where a user can be assigned to an organization based on a certain criteria.

allowedValues() {
            // we don't want to show ourselves and no other satellite pharmacies.
            const query = { isSatelliteOf: { $exists: false } }
            if (Meteor.isClient && getCurrentlyEditedInstitutionId())
               query._id = { $ne: getCurrentlyEditedInstitutionId() }

            return _.map(
               Collections.Institutions.find(query, {
                  sort: { name: 1 },
                  fields: { _id: true }
               }).fetch(),
               "_id"
            )
         },
         autoform: {
            options() {
               // we don't want to show ourselves and no other satellite pharmacies.
               const query = { isSatelliteOf: { $exists: false } }
               if (Meteor.isClient && getCurrentlyEditedInstitutionId())
                  query._id = { $ne: getCurrentlyEditedInstitutionId() }

               return _.map(
                  Collections.Institutions.find(query, {
                     sort: { name: 1 },
                     fields: { _id: 1, name: 1 }
                  }).fetch(),
                  (institution) => {
                     return {
                        label: institution.name,
                        value: institution._id
                     }
                  }
               )
            }
         }```

I will be honest - we never used this kind of approach other than exclusively on the client.

At illustreets, we created a wrapper around SimplSchema that allows returning static schemas, or even building them on the fly and passing any arguments that may need to be dynamic, at run time (and yeah, many times from some async call - we had hundreds of those even before the Fibers crisis). Example:

import { IlluSchemas } from 'meteor/illustreets:schemas';

// a static schema
IlluSchemas.addSchema('CreateVisArgs', {
  sourceSlug: {
    label: 'Data source',
    type: String,
  },
  filter: {
    type: String,
    optional: true,
    autoform: {
      type: 'hidden',
      label: false,
    },
  },
});
// then somewhere else...
IlluSchemas.validate('CreateVisArgs', someObject);

// creates schema on-the-fly
export function getColumnsSchema(columns, prop, aliases) {
  const fields = {};
  columns.forEach((col) => {
    fields[col.name] = {
      type: Boolean,
      label: aliases[col.name],
      optional: true,
      autoform: {
        id: `${col.name}_${prop}`,
        defaultValue() {
          return col[prop];
        },
      },
    };
  });
  return IlluSchemas.getSchema(fields);
}
// then elsewhere, on client...
const columns = Collection.findOne({ ... })?.columns;
// ... prop, aliases
getColumnsSchema(columns, prop, aliases).validate(someObject);

// on server...
const columns = (await Collection.findOne({ ... }))?.columns;
// ... prop, aliases
getColumnsSchema(columns, prop, aliases).validate(someObject);

This approach gives us the flexibility to still cache and reuse fields and entire schemas, and a few other features.

I don’t mind mixing up minimongo with SimplSchema on the client, given that minimongo is also a client construct, an in-memory structure instantiated just for the current user, at the end of the day. Also, I allow the client to be messy, cause most frontend stuff ends up messy somehow. But the server is a different beast. MongoDB is shared among multiple users, processes, and workers.

Also, the client part of your code really does not even need the Meteor.isClient check. The autoform block only runs on client, unless you are really trying something unholy. At illustreets we have multiple schemas with autoform blocks that are being populated just like that, used in common server/client code. But if we needed a shared allowedValues field with values from Mongo, we would generate the schema on the fly via IlluSchemas with allowedValues containing just an array of values passed as argument.

Oh, and here is a very recent comment from the creator of SimplSchema about the perils of trying to make allowedValues (and I assume other functions) async: AutoValue using async functions · Issue #484 · longshotlabs/simpl-schema · GitHub. Nearly impossible. It will simply mess up client side validations.

[EDIT]
I should add, obviously dynamic schemas like I describe above won’t work with Collection2, but for the cases where we need something like in your example, we run a validation in the services layer, just before inserting/updating the document. Collection2 would use a static version of the schema, to ensure the document has the expected structure.

These pull requests have now all been merged. Many thanks to @storyteller and @denyhs!
CC @harry97 @sabativi @filipenevola

Correction: the changes for tmeasday:publish-counts have been approved, but the PR is not yet merged.

2 Likes

Super glad you followed up on the request. Great work :clap: :clap:

You’re one of the very people who actually chipped in :sweat_smile:

2 Likes

This one also merged recently thanks to @grubba & @denyhs

2 Likes