【问题标题】:mongoose model has no access to connections in-progress transactions猫鼬模型无法访问正在进行的事务的连接
【发布时间】:2019-07-13 02:38:48
【问题描述】:

在我当前的 express 应用程序中,我想使用 mongodb 多文档事务的新功能。

首先要指出我如何连接和处理模型

我的 app.js(服务器)首先使用 db.connect() 连接到数据库。

我需要我的 db.index 文件中的所有模型。由于模型将使用相同的 mongoose 引用启动,因此我假设未来对不同路由中的模型的需求指向已连接且相同的连接。如果我对这些假设中的任何一个有误,请纠正我。

我将连接引用保存在状态对象中,并在以后的事务需要时返回它

./db/index.ts

const fs       = require('fs');
const path     = require('path');
const mongoose = require('mongoose');

const state = {
 connection = null,
}

// require all models
const modelFiles = fs.readdirSync(path.join(__dirname, 'models'));
modelFiles
.filter(fn => fn.endsWith('.js') && fn !== 'index.js')
.forEach(fn => require(path.join(__dirname, 'models', fn)));

const connect = async () => {
  state.connection = await mongoose.connect(.....);
  return;
}

const get = () => state.connection; 

module.exports = {
 connect,
 get,
}

我的模型文件包含我所需的架构

./db/models/example.model.ts

const mongoose   = require('mongoose');
const Schema     = mongoose.Schema;
const ExampleSchema = new Schema({...);

const ExampleModel = mongoose.model('Example', ExampleSchema);
module.exports  = ExampleModel;

现在是我尝试进行基本交易的路线。 F

./routes/item.route.ts

const ExampleModel = require('../db/models/example.model');

router.post('/changeQty', async (req,res,next) => {

  const connection = db.get().connection;
  const session = await connection.startSession(); // works fine

  // start a transaction
  session.startTransaction(); // also fine

  const {someData} = req.body.data;

  try{

     // jsut looping that data and preparing the promises
     let promiseArr = [];
     someData.forEach(data => {
        // !!! THIS TRHOWS ERROR !!!
        let p = ExampleModel.findOneAndUpdate(
          {_id : data.id},
          {$incr : {qty : data.qty}},
          {new : true, runValidators : true}
        ).session(session).exec();
        promiseArr.push(p);
     })        

     // running the promises parallel
     await Promise.all(promiseArr);

     await session.commitTransaction();

    return res.status(..)....;

  }catch(err){
     await session.abortTransaction();
    // MongoError : Given transaction number 1 does not match any in-progress transactions.
    return res.status(500).json({err : err}); 
  }finally{
    session.endSession();
  }

})

但我总是收到以下错误,这可能与我的模型的连接参考有关。我假设他们无权访问启动会话的连接,因此他们不知道会话。

MongoError:给定的交易编号 1 与任何正在进行的交易不匹配 交易。

也许我需要使用直接连接引用在 db.connect 中启动模型?

某处出现了很大的错误,希望您能引导我走上正确的道路。感谢您的帮助,在此先感谢

【问题讨论】:

    标签: mongodb express mongoose transactions


    【解决方案1】:

    这是因为您正在并行执行操作:

    所以你有一堆竞争条件。只需使用async/await

    让您的生活更轻松。

    let p = await ExampleModel.findOneAndUpdate(
                  {_id : data.id},
                  {$incr : {qty : data.qty}},
                  {new : true, runValidators : true}
                ).session(session).exec();
    

    参考:https://github.com/Automattic/mongoose/issues/7311

    如果这不起作用,请尝试一一执行承诺,而不是 promise.all()

    【讨论】:

    • 我希望这能解决它,认为错误信息可能具有误导性。以后试试,谢谢
    • 我很高兴它有帮助。不要忘记让我知道该问题是否已解决。快乐编码
    • 之前的错误信息似乎是一条红鲱鱼。这更有可能是 TransientTransactionError。谢谢,问题解决了!
    猜你喜欢
    • 2021-10-01
    • 2022-12-11
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多