https://www.npmjs.com/package/mongoose-transactions
简介
事务是一组连续的数据库操作操作,它的执行就好像它是一个单一的工作单元。换句话说,除非组中的每个单独操作都成功,否则事务永远不会完成。如果事务中的任何操作失败,则整个事务将失败。
有了这个模块,您可以:实际上,您将把许多MongoDB查询集中到一个组中,并将它们作为事务的一部分一起执行。
安装模块:
$ npm i mongoose-transactions
安装并保存配置:
$ npm i -S mongoose-transactions
API
创建一个新实例:
const Transaction = require("mongoose-transactions");
const transaction = new Transaction();
添加操作:
/**
* 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 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 (操作对象)
您可以通过调用getOperations方法来获取操作对象。
/**
* 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();
出于调试目的,您可以检查设计成这样的transaction operation对象数组
// 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"];
状态会自动更新,因此您可以在每次需要时检查事务操作的当前状态
Using database to save transactions(使用数据库保存事务)
从/向 数据库创建一个新的事务实例 具有存储和加载事务对象的能力
const useDB = true;
const transaction = new Transaction(useDB);
首先,您需要获得实际的事务id,可以使用该id从数据库加载事务对象。
/**
* 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();
可以使用loadDbTransaction函数从数据库加载事务对象:
/**
* 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);
您可以通过调用saveOperations方法在数据库中保存操作对象:
/**
* 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();
完整示例:
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();
网友评论