不允许 Mongoose / mongoDB 使用过期的会话
Mongoose / mondoDB Use of expired sessions is not permitted
我正在尝试与 mongoose 进行交易。
当我 运行 代码时,看起来 mongoose 文档甚至在调用 await session.endSession()
之后还记得会话。后来,当我对该文档调用 .save() 时,出现错误“不允许使用过期会话”。
这是演示(只是一个简化的例子):
const MessageSchema = new mongoose.Schema({ text: String }, {strict: 'throw'});
const Message = mongoose.model('Message', MessageSchema);
const session = await mongoose.startSession();
let message;
await session.withTransaction(async () => {
message = (await Message.create([{text: 'My message'}], {session}))[0];
});
await session.endSession();
message.text = 'My message 2';
await message.save();
最后的 .save()
抛出了那个错误。如果你记录 message.$session().hasEnded
你会得到 true。我的期望是,如果会话结束,.save() 最好不要使用它。
我想达到的目标:
使用事务创建一些文档,提交它们,所以它们在数据库中。
稍后,使用数据库中已有的同一文档对其进行一些更改。
我在这里做错了什么?如何防止 .save()
抛出错误并尝试使用过期的会话?
mongoose docs 中的任何地方都没有关于 endSession
的部分,但是正如您自己发现的那样,当调用此函数时,它只会为您的 [=12= 设置一个标志] 对象而不是销毁它。如果它被销毁,您将有另一个错误。
My expectation was that, if session has ended, .save() would be smart not to use it.
事实上,它足够聪明,不会使用它,框架只会通知您您正在尝试非法指令。
What I want to achieve: Create some documents with transaction, commit them, so they are in the database.
这正是您对 withTransaction
调用所做的。 This wrapper 帮助您创建、提交和 abort/retry 以防万一发生不好的事情,所以在那个调用之后,如果一切顺利,您确实成功地在数据库中创建了一个文档。
Later, use that same document, that is already in the database, to make some changes to it.
取决于你所说的“以后”是什么意思。如果它是同一个端点的一部分(而且我不知道为什么你会立即修改该文档而不是首先正确地提交它),那么正如我在评论中所说的那样,移动 endSession
调用很可能解决问题:
const MessageSchema = new mongoose.Schema({ text: String }, {strict: 'throw'});
const Message = mongoose.model('Message', MessageSchema);
const session = await mongoose.startSession();
let message;
await session.withTransaction(async () => {
message = (await Message.create([{text: 'My message'}], {session}))[0];
});
message.text = 'My message 2';
await message.save();
await session.endSession();
如果它是另一个端点的一部分,那么只需像刚才那样进行另一个事务,只是修改文档而不是创建它。或者,如果您根本不需要交易,请使用 findOneAndUpdate
或 findByIdAndUpdate
之类的方法。我认为您似乎对 JS 和 Mongoose 足够熟悉,可以自己完成。
What am I doing wrong here?
基本上,不多。您已经了解结束会话后无法调用 .save()
。
How can I prevent .save()
from throwing an error and trying to use expired session?
你不能。它只是提醒您正在尝试进行非法操作。但是,您可以 try/catch 错误并决定在 catch
子句中对此不做任何处理,或者编写一个 if 语句检查 message.$session().hasEnded
.
我正在尝试与 mongoose 进行交易。
当我 运行 代码时,看起来 mongoose 文档甚至在调用 await session.endSession()
之后还记得会话。后来,当我对该文档调用 .save() 时,出现错误“不允许使用过期会话”。
这是演示(只是一个简化的例子):
const MessageSchema = new mongoose.Schema({ text: String }, {strict: 'throw'});
const Message = mongoose.model('Message', MessageSchema);
const session = await mongoose.startSession();
let message;
await session.withTransaction(async () => {
message = (await Message.create([{text: 'My message'}], {session}))[0];
});
await session.endSession();
message.text = 'My message 2';
await message.save();
最后的 .save()
抛出了那个错误。如果你记录 message.$session().hasEnded
你会得到 true。我的期望是,如果会话结束,.save() 最好不要使用它。
我想达到的目标: 使用事务创建一些文档,提交它们,所以它们在数据库中。
稍后,使用数据库中已有的同一文档对其进行一些更改。
我在这里做错了什么?如何防止 .save()
抛出错误并尝试使用过期的会话?
mongoose docs 中的任何地方都没有关于 endSession
的部分,但是正如您自己发现的那样,当调用此函数时,它只会为您的 [=12= 设置一个标志] 对象而不是销毁它。如果它被销毁,您将有另一个错误。
My expectation was that, if session has ended, .save() would be smart not to use it.
事实上,它足够聪明,不会使用它,框架只会通知您您正在尝试非法指令。
What I want to achieve: Create some documents with transaction, commit them, so they are in the database.
这正是您对 withTransaction
调用所做的。 This wrapper 帮助您创建、提交和 abort/retry 以防万一发生不好的事情,所以在那个调用之后,如果一切顺利,您确实成功地在数据库中创建了一个文档。
Later, use that same document, that is already in the database, to make some changes to it.
取决于你所说的“以后”是什么意思。如果它是同一个端点的一部分(而且我不知道为什么你会立即修改该文档而不是首先正确地提交它),那么正如我在评论中所说的那样,移动 endSession
调用很可能解决问题:
const MessageSchema = new mongoose.Schema({ text: String }, {strict: 'throw'});
const Message = mongoose.model('Message', MessageSchema);
const session = await mongoose.startSession();
let message;
await session.withTransaction(async () => {
message = (await Message.create([{text: 'My message'}], {session}))[0];
});
message.text = 'My message 2';
await message.save();
await session.endSession();
如果它是另一个端点的一部分,那么只需像刚才那样进行另一个事务,只是修改文档而不是创建它。或者,如果您根本不需要交易,请使用 findOneAndUpdate
或 findByIdAndUpdate
之类的方法。我认为您似乎对 JS 和 Mongoose 足够熟悉,可以自己完成。
What am I doing wrong here?
基本上,不多。您已经了解结束会话后无法调用 .save()
。
How can I prevent
.save()
from throwing an error and trying to use expired session?
你不能。它只是提醒您正在尝试进行非法操作。但是,您可以 try/catch 错误并决定在 catch
子句中对此不做任何处理,或者编写一个 if 语句检查 message.$session().hasEnded
.