我正在使用 Mongoose 来管理 MongoDB 集合,其中包含表示事务的嵌入式文档。我需要确保我可以根据特定条件自动更新文档的“锁定”字段。
要求是:
问题是我需要区分文档没有找到是因为:
如何以原子方式实现这一点,确保一次只发生一个操作并正确处理锁定条件?对代码的任何指导或改进将不胜感激。
这是示例代码:
// Schemas
const mongoose = require('mongoose');
const { Schema, model } = mongoose;
const TransactionSchema = new Schema(
{
timestamp: { type: Number, required: true },
lock: { type: String, trim: true, required: true },
},
{ timestamps: true }
);
const DirectorySchema = new Schema(
{
owner: { type: String, trim: true, required: true },
transactions: [TransactionSchema],
},
{ timestamps: true }
);
const DirectoryModel = model('Directory', DirectorySchema);
// Example function
const updateLock = async (req) => {
const initTransaction = {
timestamp: Date.now(),
lock: 'X', // exclusive lock
};
try {
// Check the directory status, if the directory is not busy, then set the exclusive lock
const doc = await DirectoryModel.findOneAndUpdate(
{
owner: req.uid,
_id: req.params.id,
'transactions.lock': { $ne: 'X' }, // check there are no Share Lock or Exclusive lock in the transactions
'transactions.timestamp': { $lte: Date.now() - 300000 }, // prevent deadlock
},
{
$push: { transactions: initTransaction }
},
{
returnOriginal: false,
upsert: false // ensure it doesn't insert a new document if not found
}
).exec();
if (!doc) {
console.log('Document not found or lock condition not met');
} else {
// Manipulate the file in the directory
// do something...
console.log('Document updated:', doc);
}
} catch (error) {
console.error('Error updating lock:', error);
}
};
// Example request object
const req = {
uid: 'user123',
params: { id: 'documentId123' }
};
// Call the function
updateLock(req);
我需要确保操作是原子的,以防止竞争条件,并正确区分由于锁定条件而找不到文档与文档不存在。我怎样才能实现这个目标?
这里的问题是存在三种可能性:
更新运算符 findOneAndUpdate 只有两个原子操作:
对于不使用事务的原子过程,操作员已经设置了限制。因此,需要在该限制内对数据进行建模。该过程还必须被视为一个整体 - 锁定和解锁。
因此可能有两组操作:
第 1 组:
第二组:
通过这种方式,文档的锁定和解锁将是原子的,无需使用事务。
删除的数据需要记录以供将来参考,这可能需要在删除之前完成。