更新
根据一些建议,我修改如下代码:
const session = await mongoose.startSession()
session.startTransaction()
try {
const udpated = await Schema1.findByIdAndUpdate(
'id', { $set: { /* ... */ } }, { session }
)
const array = await Promise.all(
updated.array.map(async item => {
// change 1
const doc = await Schema2.findById(item.someId).session(session)
const payload = { /* ... */ }
// change 2
return new Schema3(payload).save({ session })
})
)
await session.commitTransaction()
session.endSession()
} catch (err) {
await session.abortTransaction()
session.endSession()
throw err
}
但这给了我另一个错误:
{
MongoError: internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout
at /some-path/node_modules/mongodb-core/lib/connection/pool.js:581:63
at authenticateStragglers (/some-path/node_modules/mongodb-core/lib/connection/pool.js:504:16)
at Connection.messageHandler (/some-path/node_modules/mongodb-core/lib/connection/pool.js:540:5)
at emitMessageHandler (/some-path/node_modules/mongodb-core/lib/connection/connection.js:310:10)
at TLSSocket.<anonymous> (/some-path/node_modules/mongodb-core/lib/connection/connection.js:453:17)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at TLSSocket.Readable.push (_stream_readable.js:208:10)
at TLSWrap.onread (net.js:597:20)
ok: 0,
errmsg: 'internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout',
code: 8000,
codeName: 'AtlasError',
name: 'MongoError',
[Symbol(mongoErrorContextSymbol)]: {} }
× Unexpected error occured MongoError: internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout
at /some-path/node_modules/mongodb-core/lib/connection/pool.js:581:63
at authenticateStragglers (/some-path/node_modules/mongodb-core/lib/connection/pool.js:504:16)
at Connection.messageHandler (/some-path/node_modules/mongodb-core/lib/connection/pool.js:540:5)
at emitMessageHandler (/some-path/node_modules/mongodb-core/lib/connection/connection.js:310:10)
at TLSSocket.<anonymous> (/some-path/node_modules/mongodb-core/lib/connection/connection.js:453:17)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at TLSSocket.Readable.push (_stream_readable.js:208:10)
at TLSWrap.onread (net.js:597:20)
顺便说一句:我还重构了代码而不使用 mongoose
(我只是使用标准的 mongodb
客户端用于 nodejs
并且我仍然得到那些错误。
由于我在 this question 中提到的问题,我正在使用 mongoose
事务.
但是,我的问题是,我的 Promise.all()
实现似乎不适用于 mongoose
事务。问题可能来自使用多个 Schemas
和一个 session
或创建一组文档。 (但我真的不确定)
const session = await mongoose.startSession()
session.startTransaction()
try {
const udpated = await Schema1.findByIdAndUpdate(
'id', { $set: { /* ... */ } }, { session }
)
const array = await Promise.all(
updated.array.map(async item => {
const doc = await Schema2.findById(item.someId)
const payload = { /* ... */ }
return Schema3.createa(payload, { session })
})
)
await session.commitTransaction()
session.endSession()
} catch (err) {
await session.abortTransaction()
session.endSession()
throw err
}
我收到错误,对于某些必需的路径,Schema3
的验证失败。即使 payload
在 console.log 时找到。
{ ValidationError: xxx validation failed: xxx: Path `xxx` is required., xxx: Path `xxx` is required., xxx: Path `xxx` is required.
at ValidationError.inspect (/xxx/node_modules/mongoose/lib/error/validation.js:59:24)
at formatValue (util.js:400:38)
at inspect (util.js:294:10)
at format (util.js:223:18)
at Console.log (console.js:130:21)
at module.exports (xxx.js:228:17)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
errors:
{ xxx:
{ ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
xxx:
{ ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true },
xxx:
{ ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true } },
_message: 'xxx validation failed',
name: 'ValidationError' }
在不使用 mongoose
事务的情况下重构代码时,一切正常:
try {
const udpated = await Schema1.findByIdAndUpdate(
'id', { $set: { /* ... */ } }
)
const array = await Promise.all(
updated.array.map(async item => {
const doc = await Schema2.findById(item.someId)
const payload = { /* ... */ }
return Schema3.createa(payload)
})
)
} catch (err) {
throw err
}
最佳答案
我联系了 MongoDB 支持,结果发现这是一个已知问题:
We are currently aware of an issue with the M0 Free Tier clusters whereby multi-statement transactions timeout with an error. This should be fixed with the rollout of MongoDB version 4.0.5. In the meantime, if you require this feature urgently, I would recommend that you upgrade your cluster to an M10+ cluster.
所以问题出现是因为我使用的是免费套餐。但这个错误有望在 MongoDB 4.0.5 版本中得到修复。
更新
由于我的数据库现在在版本 4.0.5 上运行,因此问题已得到解决。所以不一定是代码的问题。
关于javascript - 多文档事务不使用 MongoDB Atlas,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54003801/