Last active
September 21, 2021 13:49
-
-
Save drenther/23b9a4c9591ce2b19309e11a747d6624 to your computer and use it in GitHub Desktop.
A gettings started example for mongoose transactions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const mongoose = require('mongoose'); | |
// the run-rs command will by default start the replica sets on the following ports | |
const dbUri = 'mongodb://localhost:27017,localhost:27018,localhost:27019/example'; | |
async function init() { | |
// connecting the DB | |
await mongoose.connect(dbUri, { replicaSet: 'rs' }); | |
// a simple mongoose model | |
const User = mongoose.model('User', new mongoose.Schema({ | |
accountId: String, name: String, balance: Number | |
)}; | |
User.createCollection(); | |
// creating two users | |
await User.create([ | |
{ accountId: 'ACC001', name: 'John', balance: 50.00 }, | |
{ accountId: 'ACC002', name: 'Jane', balance: 50.00 } | |
]); | |
} | |
module.exports = init; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const mongoose = require('mongoose'); | |
// for currency calculation handling | |
const $ = require('currency.js'); | |
const init = require('./init'); | |
async function handleMoneyTransfer(senderAccountId, receiveAccountId, amount) { | |
// connect the DB and get the User Model | |
const User = await init(); | |
const session = await mongoose.startSession(); | |
session.startTransaction(); | |
try { | |
// always pass session to find queries when the data is needed for the transaction session | |
const sender = await User.findOne({ accountId: senderAccountId }).session(session); | |
// calculate the updated sender balance | |
sender.balance = $(sender.balance).subtract(amount); | |
// if funds are insufficient, the transfer cannot be processed | |
if (sender.balance < 0) { | |
throw new Error(`User - ${sender.name} has insufficient funds`); | |
} | |
// save the sender updated balance | |
// do not pass the session here | |
// mongoose uses the associated session here from the find query return | |
// more about the associated session ($session) later on | |
await sender.save(); | |
const receiver = await User.findOne({ accountId: receiverAccountId }).session(session); | |
receive.balance = $(receiver.balance).add(amount); | |
await receiver.save(); | |
// commit the changes if everything was successful | |
await session.commitTransaction(); | |
} catch (error) { | |
// if anything fails above just rollback the changes here | |
// this will rollback any changes made in the database | |
await session.abortTransaction(); | |
// logging the error | |
console.error(error); | |
// rethrow the error | |
throw error; | |
} finally { | |
// ending the session | |
session.endSession(); | |
} | |
} |
Yea, thanks for pointing it out.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There an
async
missing in the handleMoneyTransfer function.