【问题标题】:How to use MongoDB 4.0 Multi-document ACID transactions with Meteor 1.8如何在 Meteor 1.8 中使用 MongoDB 4.0 多文档 ACID 事务
【发布时间】:2019-02-13 21:20:04
【问题描述】:

一直在尝试这样做:https://github.com/meteor/meteor/blob/3051150f2f5ae953f391802e73682fba613b3d46/packages/mongo/mongo_livedata_tests.js#L3431-L3487

但遇到很多错误,例如:

UnhandledPromiseRejectionWarning: MongoError: Given transaction number 5 不匹配任何正在进行的事务。

我正在使用以下代码:

collection.js 包含以下帮助函数,用于在其他地方的事务中包装 db 命令(这都是在服务器端):

const { client } = MongoInternals.defaultRemoteCollectionDriver().mongo;

export const RunInMongoTx = async function(func) {
      try {
        const session = await client.startSession();
        session.startTransaction();
        options = { session };

        func(options);

        session.commitTransaction();
      } catch (error) {
        session.abortTransaction();
        throw error;
      }
    };

在其他文件中,然后我导入该函数并使用它:

import {RunInMongoTx} from "./collections";

Meteor.methods({
  "ShiftRequests.setAsDidNotTurnUp": sr => {
    const job = Jobs.findOne({ _id: sr.jobId });
    if (job.poster != Meteor.userId()) {
      throw new Meteor.Error(
        "not-job-poster",
        "Only poster can setAsDidNotTurnUp"
      );
    }

    RunInMongoTx(async options => {
      res = await EmployerFeedbacks.rawCollection().remove(
        {
          jobId: job._id,
          workerId: sr.workerId
        },
        options
      );

      res = await ShiftRequests.rawCollection().update(
        { _id: sr._id },
        { $set: { didNotTurnUp: true } },
        options
      );
    });
  }
});

【问题讨论】:

  • rawCollection 调用不是 Meteor 环境的一部分。我总是使用Meteor.bindEnvironment 将这些外部调用与 Meteor 环境绑定。这会让你更进一步吗?

标签: mongodb meteor


【解决方案1】:

我认为您的问题是您在没有等待的情况下调用 RunInMongoTx 函数。

const { client } = MongoInternals.defaultRemoteCollectionDriver().mongo;

export const RunInMongoTx = async function(func) {
      try {
        const session = await client.startSession();
        session.startTransaction();
        options = { session };

        await func(options);

        session.commitTransaction();
      } catch (error) {
        session.abortTransaction();
        throw error;
      }
    };
import {RunInMongoTx} from "./collections";

Meteor.methods({
  "ShiftRequests.setAsDidNotTurnUp": async sr => {
    const job = Jobs.findOne({ _id: sr.jobId });
    if (job.poster != Meteor.userId()) {
      throw new Meteor.Error(
        "not-job-poster",
        "Only poster can setAsDidNotTurnUp"
      );
    }

    await RunInMongoTx(async options => {
      res = await EmployerFeedbacks.rawCollection().remove(
        {
          jobId: job._id,
          workerId: sr.workerId
        },
        options
      );

      res = await ShiftRequests.rawCollection().update(
        { _id: sr._id },
        { $set: { didNotTurnUp: true } },
        options
      );
    });
  }
});

让我知道这是否有效。

【讨论】:

  • 我做了这些改变。现在没有错误,但不幸的是,写入也不会发生在 Mongo 上。这与 Meteor Fibers 的工作方式及其与等待/异步的交互有关吗?因为 Meteor 在 Meteor.methods 内部使用了 Fibers 来模拟同步代码执行
  • 对不起,我认为它正在工作 - 我正在使用 redis-oplog 和 rawCollection 会绕过 redis-oplog 使用的钩子,因此我没有看到应用程序中发生的数据更改 - 给我几分钟当我使用外部工具监控实际的 MongoDB 数据库时,会尽快回复您
  • 是的,这个解决方案有效 - 非常感谢 :) 我需要阅读更多关于 async/await 的内容!
  • 太棒了,我也使用 redis-oplog,你说得对,它错过了这种操作。有一种方法可以使用另一个名为 oplogtoredis github.com/tulip/oplogtoredis 的程序自动完成此操作
  • 本页底部提供了将 rawCollection 与 redis-oplog 结合使用的具体指导:github.com/cult-of-coders/redis-oplog/blob/master/docs/…
猜你喜欢
  • 2019-03-11
  • 2019-05-28
  • 2020-12-26
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多