UPDATE
After some suggestions I modifies the code like this:
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
}
But that gives me another error:
{
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)
Btw.: I also refactored that code without using mongoose
(I just used the standard mongodb
client for nodejs
and I am still getting those errors.
I am using mongoose
transactions because of my problem referred to in this question.
However, my problem is, that my implementation of Promise.all()
doesn't seem to work with mongoose
transactions. The issue probably comes from using multiple Schemas
with one session
or creating an array of documents. (But I am really not sure)
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
}
I am getting errors, that the validation of Schema3
failed for some required paths. Even though payload
is found when console.log it.
{ 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' }
When refactoring the code without using mongoose
transactions, everything works just fine:
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
}
For situations that require atomicity of reads and writes to multiple documents (in a single or multiple collections), MongoDB supports multi-document transactions. With distributed transactions, transactions can be used across multiple operations, collections, databases, documents, and shards.
Having no transaction is a trade-off to allow MongoDB to be scalable. The purpose of a transaction is to make sure that the whole database stays consistent while multiple operations take place. But in contrary to most relational databases, MongoDB isn't designed to run on a single host.
Performance Scale After evaluating multiple technology options, AHL used MongoDB to replace its relational and specialised 'tick' databases. MongoDB supports 250 million ticks per second, at 40x lower cost than the legacy technologies it replaced.
I contacted the MongoDB Support and it turned out that this is a known issue:
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.
So the issue occurs because I am using the free tier. But the bug will hopefully be fixed with the MongoDB 4.0.5 release.
UPDATE
As my database runs now on version 4.0.5, the problem is fixed. So it wasn't necessarily a issue with the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With