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

ah-mongoose-transactions

v1.0.0

Published

Atomicity and Transactions for mongoose

Downloads

7

Readme

travis dm version GitHub stars GitHub forks mongoose-transactions

Introduction

Atomicity and Transactions for mongoose

A transaction is a sequential group of database manipulation operations, which is performed as if it were one single work unit. In other words, a transaction will never be complete unless each individual operation within the group is successful. If any operation within the transaction fails, the entire transaction will fail.

With this module, you can :

Practically, you will club many MongoDB queries into a group and you will execute all of them together as a part of a transaction.

Getting started

Install module:

$ npm i mongoose-transactions

Install and save module in your project:

$ npm i -S mongoose-transactions

API

Create new instance:

const Transaction = require("mongoose-transactions");

const transaction = new Transaction();

Add an operation:

/**
 * Create the insert transaction and rollback states.
 * @param modelName - The string containing the mongoose model name.
 * @param data - The object containing data to insert into mongoose model.
 * @returns id - The id of the object to insert.
 */
const id = transaction.insert("modelName", object);
/**
 * Create the findOneAndUpdate transaction and rollback states.
 * @param modelName - The string containing the mongoose model name.
 * @param findId - The id of the object to update.
 * @param dataObj - The object containing data to update into mongoose model.
 * @param options - The update operation options object as { new: true }
 */
transaction.update("modelName", id, object, options);
/**
 * Create the remove transaction and rollback states.
 * @param modelName - The string containing the mongoose model name.
 * @param findObj - The object containing data to find mongoose collection.
 */
transaction.remove("modelName", id);

Run operations:

/**
 * Run the operations and check errors.
 * @returns Array of objects - The objects returned by operations
 *          Error - The error object containing:
 *                  data - the input data of operation
 *                  error - the error returned by the operation
 *                  executedTransactions - the number of executed operations
 *                  remainingTransactions - the number of the not executed operations
 */
transaction.run(); // return Promise

Rollback operations:

/**
 * Rollback the executed operations if any error occurred.
 * @param   stepNumber - (optional) the number of the operation to rollback - default to length of
 *                            operation successfully runned
 * @returns Array of objects - The objects returned by rollback operations
 *          Error - The error object containing:
 *                  data - the input data of operation
 *                  error - the error returned by the operation
 *                  executedTransactions - the number of rollbacked operations
 *                  remainingTransactions - the number of the not rollbacked operations
 */
transaction.rollback(); // return Promise

Clean operations:

/**
 * Clean the transactions object to begin a new transaction on the same instance.
 */
transaction.clean(); // clean the prevoious operation

Full example:

const Transaction = require("mongoose-transactions");
const transaction = new Transaction();

const person = "Person"; // the name of the registered schema

const jonathanObject = {
  age: 18,
  name: "Jonathan"
};
const aliceObject = {
  age: 23,
  name: "Alice"
};

async function start() {
  try {
    const jonathanId = transaction.insert(person, jonathanObject);
    transaction.update(person, jonathanId, aliceObject);
    transaction.remove(person, "fakeId"); // this operation fail
    const final = await transaction.run();
    // expect(final[0].name).toBe('Jonathan')
  } catch (error) {
    console.error(error);
    const rollbackObj = await transaction.rollback().catch(console.error);
    transaction.clean();
    //  expect(rollbacks[0].name).toBe('Alice')
    //  expect(rollbacks[0].age).toBe(aliceObject.age)
    //  expect(rollbacks[1].name).toBe('Jonathan')
    //  expect(rollbacks[1].age).toBe(bobObject.age)
  }
}

start();

Operation Object

You can get the operations object by calling getOperations method.

/**
 * Get transaction operations array from transaction object or collection on db.
 * @param transactionId - Optional. If the transaction id is passed return the elements of the transaction id
 *                                  else return the elements of current transaction (default null).
 */
const operations = transaction.getOperations();

For debug purposes you can inspect the array of transaction operation object that is designed like this:

// console.log(operations)
[
  {
    /** The transaction type to run */
    type: string, // 'insert', 'update', 'remove'
    /** The transaction type to execute for rollback */
    rollbackType: string, // 'remove', 'update', 'insert'
    /** The mongoose model instance */
    model: any, // compiled mongoose model
    /** The mongoose model name */
    modelName: string, // 'Person'
    /** The mongoose model instance before transaction if exists */
    oldModel: any, // model used for rollback
    /** The id of the object */
    findId: any,
    /** The data */
    data: any,
    /** options configuration query */
    options: any,
    /** The current status of the operation */
    status: Status
  }
];

/** The operations possible states are: */
Status = ["Pending", "Success", "Error", "Rollback", "ErrorRollback"];

The status is automatically updated, so you can check the current status of your transaction operations every time you need

Using database to save transactions

Create new transaction instance with the ability to store and load transaction object to/form database.

const useDB = true;
const transaction = new Transaction(useDB);

First of all you need to get the actual transaction id, you can use the id to load the transaction object from database.

/**
 * If the instance is db true, return the actual or new transaction id.
 * @throws Error - Throws error if the instance is not a db instance.
 */
const transId = await transaction.getTransactionId();

You can load a transaction object from database with the loadDbTransaction fuction.

/**
 * Load transaction from transaction collection on db.
 * @param transactionId - The id of the transaction to load.
 * @trows Error - Throws error if the transaction is not found
 */
await transaction.loadDbTransaction(transId);

You can save the operations object on database by calling saveOperations method.

/**
 * Save transaction operations array on db.
 * @throws Error - Throws error if the instance is not a db instance.
 * @return transactionId - The transaction id on database
 */
const transId = await transaction.saveOperations();

Full example:

const Transaction = require("mongoose-transactions");
const useDB = true;
const transaction = new Transaction(useDB);

const person: string = "Person";

const tonyObject: any = {
  age: 28,
  name: "Tony"
};

const nicolaObject: any = {
  age: 32,
  name: "Nicola"
};

async function start() {
  // create operation on transaction instance
  const id = transaction.insert(person, tonyObject);
  transaction.update(person, id, nicolaObject, { new: true });

  // get and save created operation, saveOperations method  return the transaction id saved on database
  const operations = transaction.getOperations();
  const transId = await transaction.saveOperations();

  // create a new transaction instance
  const newTransaction = new Transaction(true);

  // load the saved operations in the new transaction instance using the transId
  await newTransaction.loadDbTransaction(transId);

  // if you need you can get the operations object
  const newOperations = newTransaction.getOperations();

  // finally run and rollback
  try {
    const final = await newTransaction.run();
  } catch (err) {
    const rolled = await newTransaction.rollback();
  }
}

start();

More examples

See tests folder for more examples

Feel free to open issues, fork project, and collaborate with us!

Contribute

Clone repository locally and install dependencies:

$ git clone https://github.com/daton89-topperblues/mongoose-transactions.git
$ cd mongoose-transactions
$ npm i

Fork project and open pull request

Currently development runs with:

Node.js v8.1.4

Mongoose v4.11.1

Typescript v2.4.1

Jest v20.0.4

Changelog

1.1.0 add transaction persistence

1.0.4 fix exports default error

Contributors

@topperblues Nicola Bonavita

@daton89 Toni D'Angelo