Многодокументные транзакции не работают с использованием MongoDB Atlas - PullRequest
0 голосов
/ 02 января 2019

UPDATE

После некоторых предложений я модифицирую код следующим образом:

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, и я все еще получаю эти ошибки.


Я использую 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 не удалась для некоторых обязательных путей. Несмотря на то, что * console 10 10 найдено payload.

{ 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
}

Ответы [ 3 ]

0 голосов
/ 05 января 2019

Попробуйте добавить .session(session) к каждому запросу

const doc = await Schema2.findById(item.someId).session(session)

https://mongoosejs.com/docs/api.html#query_Query-session

0 голосов
/ 09 января 2019

Я связался со службой поддержки MongoDB, и выяснилось, что это известная проблема:

В настоящее время нам известна проблема с кластерами свободного уровня M0, из-за которой транзакции с несколькими операторами истекают с ошибкой,Это должно быть исправлено с помощью развертывания MongoDB версии 4.0.5.Тем временем, если вам срочно требуется эта функция, я бы порекомендовал обновить ваш кластер до кластера M10 +.

Таким образом, проблема возникает из-за того, что я использую бесплатный уровень.Но, надеюсь, ошибка будет исправлена ​​в выпуске MongoDB 4.0.5.

ОБНОВЛЕНИЕ

Поскольку моя база данных теперь работает в версии 4.0.5, проблема исправлена.Так что это не обязательно проблема с кодом.

0 голосов
/ 03 января 2019

Похоже, вам не хватает опции сеанса в findOne():

const doc = await Schema2.findById(item.someId, null, { session })

См .: https://mongoosejs.com/docs/api.html#model_Model.findOne

...