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

mongoose-transact

v0.0.2

Published

A mongoose schema for mongo transactions

Downloads

87

Readme

mongoose-transact

NPM Package Build Status Coverage Status

A transaction system for mongoose

You probably shouldn't use this

To begin, if you are considering using this, then you are probably doing something wrong. Transactions were excluded from MongoDB for a reason. They are slow by nature, and create a need for a locking mechanism for all documents affected. However, sometimes you will find yourself painted into a corner, and will need a quick solution.

If you want to use this in your application, first consider that there might be a way to model things so that you do not need transactions. MongoDB embedded documents can be used to solve many problems. Storing a complete copy of a document in another document may seem wasteful, but storage is cheap. Raw performance at the expense of storage space is a good tradeoff.

Before using mongoose-transact

If you decide to use mongoose-transact in your application anyway, there are some things to be aware of:

  • You need to be very aware of how your application updates and removes documents in the collections that you will modify with mongoose-transact. You can continue to create new documents in these collections with mongoose new and save, but otherwise, all updates and removes for that collection need to be changed to use mongoose-transact, even if they only modify one document. This guarantees that any pending transactions for that document will be able to be completed or rolled back to the correct state.

  • You will be trading write performance for a guaranteed state. Expect things to be at least 5x slower.

  • Creating more than one transaction (with new Transaction()) that modifies a specific document will fail. The helper method .create() will allow you to request multiple transactions that affect a document, but since only one can be saved at a time, it will keep retrying the additional transactions until a timeout is reached and timeout error is sent. The timeout is 5 seconds by default, but can be overridden.

How to use mongoose-transact

Transactions will either be completed, meaning that all changes in the transaction are persisted, or all changes will be reverted if any single change encounters an error. If all changes in the transaction complete without error, then the error in the callback will be null. Otherwise, if the changes in the transaction encounter an error and the documents have to be reverted, the error in the callback will not be null, and your application can handle the problem or alert the admin of the issue.

Creating a transaction

Transaction.create(data, callback)
Transaction.create(data, timeout, callback)

  • timeout (optional) is in seconds
  • callback responds with error or null

###All transactions require the following fields:

  • app (String): this is the name of your application, server hostname, etc
  • changes (Array): this is the array of changes to include in the transaction

An example data object to insert 2 documents, that credit and debit user accounts:

  • insert requires coll, act, docId, data

{
  "app": "MyAppName",
  "changes": [
    {
      "coll": "MyCollectionName",
      "act": "insert",
      "docId": ObjectID("MyObjectID1"),
      "data": {"amount": 5, "whatever": "your document contains"},
    },
    {
      "coll": "MyCollectionName",
      "act": "insert",
      "docId": ObjectID("MyObjectID2"),
      "data": {"amount": -5, "whatever": "your document contains"},
    }
  ]
}

An example data object to remove 2 documents:

  • remove requires coll, act, docId

{
  "app": "MyAppName",
  "changes": [
    {
      "coll": "MyCollectionName",
      "act": "remove",
      "docId": ObjectID("MyObjectID1")    },
    {
      "coll": "MyCollectionName",
      "act": "remove",
      "docId": ObjectID("MyObjectID2")    }
  ]
}

An example data object to update 2 documents:

  • update requires coll, act, docId, and at least one of the 4 following:
  • inc (Object): an object of field names and value to increment
  • push (Object): an object in the format { to: "fieldname", data: "whatever datatype you want to push", v: 4}. Only to and data are required. v is the document's __v version field to make sure things havent changed since your request*
  • pull (Object): an object in the format { from: "fieldname", data: "whatever datatype you want to pull", v: 4}. Only from and data are required. v is the document's __v version field to make sure things havent changed since your request*
  • data (Object): An object containing just the fields and values you want to update with Mongo's $set operator.

{
  "app": "MyAppName",
  "changes": [
    {
      "coll": "MyCollectionName",
      "act": "update",
      "docId": ObjectID("MyObjectID1"),
      "data": {"whatever": "your document contains"},
    },
    {
      "coll": "MyCollectionName",
      "act": "update",
      "docId": ObjectID("MyObjectID2"),
      "data": {"whatever": "your document contains"},
    }
  ]
}

Additional info

  • You can mix and match the actions, to insert and remove, insert and update, etc.
  • You can modify more than 2 documents.  
     

##Cleaning up after a system restart If a transaction is left in an incomplete state due to a system restart, there is a method for finding and reverting those transactions:

cleanupOldJobs(expiredDate, app, callback)
This static method allows you to provide a timestamp to compare to the transaction's lastModifiedDate, and if the last modification was older than the expiredDate, it reverts the transaction.

The app field can be set to null to find transactions for any app, or it can be specified to allow you to cleanup only transactions for that app name.

##Testing

From within the directory containing this source:

npm install && npm test

##Fork it! Pull requests, issues, and feedback are welcome.