Skip to content

Mongo-transactions

  • Who maintains the package - Jam

这是个什么包?

¥What is this package?

jam:mongo-transactions 让你能够在 Meteor 应用中轻松使用 Mongo 事务。以下是一些这样做的好处:

¥jam:mongo-transactions enables an easy way to work with Mongo Transactions in Meteor apps. Here are a few of the benefits:

  • 使用你熟悉的标准 Meteor 集合方法进行写入。你无需担心使用 rawCollection(),但如果你需要特定的 rawCollection() 方法,你仍然可以使用它。

    ¥Write with the standard Meteor collection methods you're accustomed to. You don't need to worry about using rawCollection(), though if you need a particular rawCollection() method, you can still use it.

  • 你无需担心传递 session。此软件包会为你处理这些操作。

    ¥You don't need to worry about passing session around. This package takes care of that for you.

  • 由于这是一个底层解决方案,ID 生成功能可以正常工作。

    ¥Because it's a low-level solution, ID generation works as expected.

  • 与其他自动验证数据库写入的软件包(例如 jam:easy-schemaaldeed:collection2)开箱即用。

    ¥Works out-of-the-box with other packages that automatically validate on DB writes, like jam:easy-schema and aldeed:collection2.

  • 一个简单的 API 可供使用。Mongo 使用两个事务 API(回调 API 和核心 API)使事情变得复杂。此包默认使用 Mongo 推荐的回调 API,但允许你通过传入 autoRetry: false 来使用核心 API。

    ¥One simple API to use. Mongo has made things complicated with two APIs for Transactions, the Callback API and the Core API. This package defaults to using the Callback API as recommended by Mongo, but allows you to use the Core API by passing in autoRetry: false.

  • 可同构使用。

    ¥Can be used isomorphically.

  • 兼容 Meteor 2.8.1 及更高版本,并支持 Meteor 3.0+

    ¥Compatible with Meteor 2.8.1 and up, including support for Meteor 3.0+

重要提示:此包要求你使用 v2.8.1 中引入的基于 Promise 的 *Async Meteor 集合方法,但从技术上讲,只要你不使用回调,它就可以使用不带 *Async 后缀的旧语法。它不涵盖使用 Meteor 集合方法的回调。

¥Important: This package expects that you'll use the promise-based *Async Meteor collection methods introduced in v2.8.1 though it will technically work with the older syntax without the *Async suffix as long as you don't use callbacks. It does not cover using callbacks with Meteor collection methods.

如何下载?

¥How to download it?

将软件包添加到你的应用

¥Add the package to your app

bash
meteor add jam:mongo-transactions

来源

¥Sources

如何使用?

¥How to use it?

创建事务

¥Create a Transaction

注意:无需将 session 传递给 *Async 集合方法。此包会为你处理这些问题。

¥Note: there's no need to pass session into the *Async collection methods. This package handles that for you.

js
import { Mongo } from 'meteor/mongo';

async function purchase(purchaseData) {
  try {
    const { invoiceId } = await Mongo.withTransaction(async () => {
      const invoiceId = await Invoices.insertAsync(purchaseData);
      const changeQuantity = await Items.updateAsync(purchaseData.itemId, { $set: {...} });
      return { invoiceId, changeQuantity } // you can return whatever you'd like
    });
    return invoiceId;
  } catch (error) {
    // something went wrong with the transaction and it could not be automatically retried
    // handle the error as you see fit
  }
}

传递事务选项

¥Passing Transaction options

如果你想自定义事务的运行方式,请将事务选项作为第二个参数传入,例如:

¥If you want to customize how the Transaction runs, pass in the Transaction options as the second argument, for example:

js
await Mongo.withTransaction(async () => {
  ...
}, { writeConcern: { w: 1 } });

有关事务选项的更多信息,请参阅 Mongo Node API 文档

¥Refer to the Mongo Node API docs for more information about Transaction options.

防止事务失败时自动重试

¥Preventing automatic retries if the Transaction fails

大多数情况下,你需要默认行为,即在出现 TransientTransactionErrorUnknownTransactionCommitResult 提交错误时自动重试事务。但如果你不想这样做,只需像这样传入 { autoRetry: false }

¥Most of the time, you'll want the default behavior where the Transaction is automatically retried for a TransientTransactionError or UnknownTransactionCommitResult commit error. But if you don't want that behavior, simply pass in { autoRetry: false } like this:

js
await Mongo.withTransaction(async () => {
  ...
}, { autoRetry: false });

设置 { autoRetry: false } 意味着将使用 Transactions Core API 而不是 Callback API,并且你将负责处理所有错误。你可以阅读更多关于 Mongo 文档 的差异的信息。

¥Setting { autoRetry: false }, means the Transactions Core API will be used rather than the Callback API and you'll be responsible for handling all errors. You can read more about the differences in the Mongo Docs.

确定你是否处于事务

¥Determine if you're in a Transaction

要确定代码当前是否在事务中运行,请使用:

¥To determine if the code is currently running in a Transaction, use:

js
Mongo.inTransaction(); // returns true or false

使用 Isomorphically 实现乐观 UI

¥Using Isomorphically for Optimistic UI

你可以为 Optimistic UI 同构地编写 Mongo.withTransactionMongo.inTransaction,但请注意,事务实际上只会在服务器上执行。

¥You can write Mongo.withTransaction and Mongo.inTransaction isomorphically for Optimistic UI however note that the Transaction will only truly be performed on the server.

与任何同构代码一样,你应该意识到它可能会失败,因为操作在客户端无法成功,但在服务器上可以成功。例如,假设你在事务中使用 .find,而客户端上的 Minimongo 没有该特定数据,则客户端将失败,但服务器仍然应该成功。你可以使用 if (Meteor.isServer) 封装特定的服务器专用代码,但在这种情况下,你可能希望避免使用同构代码,并确保整个事务代码仅在服务器上运行。

¥As with any isomorphic code, you should be aware that it may fail because the operation can't succeed on the client but will succeed on the server. For example, let's say you're using .find within the Transaction and Minimongo on the client doesn't have that particular data, the client will fail but the server should still succeed. You can wrap specific server-only code with if (Meteor.isServer), but in these cases, you'll likely want to avoid isomorphic code and make sure the entire Transaction code only runs on the server.

使用 Mongo Atlas 作为数据库?

¥Using Mongo Atlas as your DB?

重要提示:根据我的经验,你必须使用付费套餐才能使事务与 Meteor 正常工作。免费套餐不会跟踪事务的 oplog。因此,如果你要在生产环境中尝试此操作,请务必使用付费套餐。

¥Important: In my experience, you must use a paid tier for Transactions to work as expected with Meteor. The free tier would not tail the oplog for Transactions. So if you're trying this out in production, be sure to use a paid tier.