npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dyna-mongo-db

v2.0.9

Published

The dyna-mongo-db, upgrade database, collection and dynamic collections

Downloads

58

Readme

Dyna Mongo DB - Upgrade Mechanism

Full version of the DynaMongoDb config

interface IDynaMongoDBConfig {
  connectionString: string;
  databaseName: string;
  upgradeDatabase?: IDatabaseUpgrade[];
  upgradeCollections?: ICollectionsUpgrades;
  onUpgradeError?: (collectionName: string, version: number, error: any) => void;
}
  • upgradeDatabase: To upgrade a whole database.
  • upgradeCollections: To upgrade a collection or dynamic collections
  • upgradeDatabase: To catch the Upgrade errors from both of the above methods.

You can use both Database and Collection Upgrades.

Upgrade database

Setup

To make a database upgradable you have to pass the upgradeDatabase on DynaMongoDB instantiation.

const dmdb = new DynaMongoDB({
  connectionString: '<my mongodb connection string>', 
  databaseName: 'happy-cars-production',
  upgradeDatabase, // <-- this one
  onUpgradeError: (collectionName: string, version: number, error: any) => console.error('Upgrade failed on collection', collection, 'version', version, error),
})

This property should be an array of IDatabaseUpgrade which it is:

interface IDatabaseUpgrade {
  version: number;
  title: string;
  description?: string;
  method: (params: { db: Db }) => Promise<void>;
}
  • version: every version should be unique, the version would be non-sequential
  • title: Title of this Upgrade, this is consoled
  • description: (optional) Few words about this Upgrade, not consoled.
  • method: The callback method, a promised one, will perform the Upgrade for this version.

The method should be resolved when all work has been completed.

The method would be rejected if something went completely wrong. If an exception is thrown again, it is assumed as rejected. In this case the method that started the operation (getCollection(), find()) will be rejected. A console.error by default is consoled you will see this error on the server's console.

Example for the upgradeDatabase property:

const upgradeDatabase: IDatabaseUpgrade[] = [
  {
    version: 1,
    title: 'Create users table',
    method: async ({db}) => {
      await db.createCollection('users');
    },
  },
  {
    version: 12,
    title: 'Create Users name indexer',
    method: async ({db}) => {
      const collection = await db.collection('users')
      await collection.createIndex(
        { date: 1 },
        { name: 'name indexer' },
      );
    },
  },
];

NOTE: In the method always await the operations!

NOTE: Do not use the instance of DynaMongoDB (like dmdb) inside the Upgrade Methods!

Lifecycle

The Upgrade methods are running on Database's connect.

Upgrade Collection

Setup

Like the databases, you can Upgrade collections in exactly the same way. You just have to create a dictionary object using the Collection name as key.

For Example:

const dmdb = new DynaMongoDB({
  connectionString: '<my mongodb connection string>', 
  databaseName: 'happy-cars-production',
  upgradeCollections, // <-- this one
  onUpgradeError: (collectionName: string, version: number, error: any) => console.error('Upgrade failed on collection', collection, 'version', version, error),
})

Where collectionUpgrades is:

const collectionUpgrades: ICollectionsUpgrades = {
  "users": { // <-- this is the name of the Collection
    upgrades: [
      {
        version: 1,
        title: 'Creation of the collection',
        method: async ({collectionName, db}) => {
          // Note: Use the `collectionName` of the argument and not hardcoded the `users`!
          await db.createCollection(collectionName);
        },
      },
      {
        version: 2,
        title: 'Add the first doc',
        method: async ({db, collectionName}) => {
          const collection = await db.collection('users')
          await collection.createIndex(
            { loginName: 1 },
            { name: 'Login name indexer' },
          );
        },
      },
    ],
  },
};

NOTE: In the method always await the operations!

NOTE: In the method use always the collectionName that is provided by the argument, to support the Dynamic Collections! For dynamic collections, the collection name will be different.

NOTE: Do not use the instance of DynaMongoDB (like dmdb) inside the Upgrade Methods!

Usage

Then you can use the users collection without even creating it.

const usersCollection = await dmdb.getCollection('users');
usersCollection.insertOne({id: 1, fname: 'John', lname: 'Smith', loginName: 'jsmith'});

Once we have Upgrade methods for the users Collection, we can create dynamic Collections that will use these Upgrades and have the same features!

const usersCollection = await dmdb.getCollection('super-company---users');
// At this point the all upgrades of the `"users"` Collection have been applied.
usersCollection.insertOne({id: 1, fname: 'John', lname: 'Smith', loginName: 'jsmith'});

Lifecycle

The Upgrade operation for a collection is taking part on the first use of the Collection after DB's connection.

If you re-connect to DB, the Upgrade operation will take part on first use of the Collection again.

If an Upgrade version fails, it will be retried on the next Collection's usage.

If you add on runtime Upgrade methods (for development or testing) you should re-connect to DB.

Upgrade Dynamic Connections (the three dashes ---)

Dynamic Collection is a Collection with a name that ends with ---<name>.

Imagine that there is an Upgrade for the Collection with the name users. If you create a Collection with the name super-company---users, then this Collection is called dynamic since the Upgrade methods of the users Collection will be applied on it.

Also, it is not needed to have a collection with an exact name. For instance, it is not required to have a Collection with the name users. You can have Collections that are ending with ---users, and the Upgrades will be applied on them.

On the other hand, if there are no Upgrades for the users Collection, nothing will happen, no errors. At a later time, if you create Upgrades the users, they will be applied to users and all Collections ending with -- users.

Error handling

The Upgrade methods (like the old SQL migration scripts) should not fail.

The Upgrade Fails will bubble up to any DB method of Dyna Mongo DB. This is normal. The same happens for any kind of error, network error, disk error, anything. The error would be something temporary or... permanent. Deal with it.

To catch the Upgrade Fails use the onUpgradeError callback.

Upgrade methods

You don’t need to use these upgrade methods except if you want to upgrade the database or collections on Application’s upgrade time.

upgradeDatabase(): Promise

It runs the needed Upgrade Methods to Upgrade the database

upgradeCollection(collectionName: string): Promise

It runs the needed Upgrade Methods to Upgrade the collection and the dynamic collections of this collectionName

Upgrade methods error handling

If an error occurs, the Promised methods will be fulfilled with rejection of the error.

Return interface or the upgrade methods

On success Upgrade, the following object is resolved.

interface IUpgradeCollectionResults {
  initialVersion: number | null;
  upgradeToVersion: number | null;
  hasUpgrades: boolean | null;
  plannedUpgrades: number;
  appliedUpgrades: number;
}

Test/Debug upgrade methods

You can use the upgrade methods to see if the methods are compatible with a production db (with a copy of production db of course).

If you want to change the Upgrade version of the database, you can change it on dyna-mongo-db--upgrade-manager collection.

For the Database Upgrade version, the collection name is @@dyna-mongo-db--database.

There is a debug method to change the version number programmatically:

_debug_changeVersion(collectionName: string, version: number): Promise<void>

Technical info

The Dyna Mongo DB keeps the versions on dyna-mongo-db--upgrade-manager collection. Do not drop this Collection.

Sum up

  • Upgrades are just Promised methods.
  • Inside these methods, we have only the instance of the MongoDB db.
  • Through the db instance, we create the Collections and anything needed.
  • The Dyna Mondo DB takes care when to run these Upgrade Methods.
  • The same Upgrade methods applied to Dynamic Collections