Как проверить транзакцию Sequelize и сделать так, чтобы она выглядела красиво

1

Я пытаюсь переучивать NodeJS через пару лет после его сдачи, поэтому я строю небольшой банковский веб-сайт в качестве теста. Я решил использовать Sequelize для своего ORM, но у меня проблемы с отправкой денег между людьми так, как мне нравится. Вот моя первая попытка:

// myUsername - who to take the money from
// sendUsername - who to send the money to
// money - amount of money to be sent from 'myUsername'->'sendUsername'
// Transaction is created to keep a log of banking transactions for record-keeping.
module.exports = (myUsername, sendUsername, money, done) => {
    // Create transaction so that errors will roll back
    connection.transaction(t => {
        return Promise.all([
            User.increment('balance', {
                by: money,
                where: { username: myUsername },
                transaction: t
            }),
            User.increment('balance', {
                by: -money,
                where: { username: sendUsername },
                transaction: t
            }),
            Transaction.create({
                fromUser: myUsername,
                toUser: sendUsername,
                value: money
            }, { transaction: t })
        ]);
    }).then(result => {
        return done(null);
    }).catch(err => {
        return done(err);
    });
};

Это сработало, но оно не подтвердило модель, когда она была увеличена. Я бы хотел, чтобы транзакция завершилась неудачей, когда модель не подтвердила. Моя следующая попытка состояла в том, чтобы перейти к обратным вызовам, показанным здесь (тот же заголовок функции):

connection.transaction(t => {
        // Find the user to take money from
        return User
        .findOne({ where: { username: myUsername } }, { transaction: t })             .then(myUser => {
                    // Decrement money
                    return myUser
                    .decrement('balance', { by: money, transaction: t })
                    .then(myUser => {
                            // Reload model to validate data
                            return myUser.reload(myUser => {
                                    // Validate modified model
                                    return myUser.validate(() => {
                                            // Find user to give money to
                                            return User
                                            .findOne({ where: { username: sendUsername } }, { transaction: t })
                                            .then(sendUser => {
                                                    // Increment balance
                                                    return sendUser
                                                    .increment('balance', { by: money, transaction: t })
                                                    .then(sendUser => {
                                                            // Reload model
                                                            return sendUser.reload(sendUser => {
                                                                    // Validate model
                                                                    return sendUser.validate(() => {
                                                                            // Create a transaction for record-keeping
                                                                            return Transaction
                                                                            .create({
                                                                                    fromUser: myUser.id,
                                                                                    toUser: sendUser.id,
                                                                                    value: money
                                                                            }, { transaction: t });
                                                                    });
                                                            });
                                                    });
                                            });
                                    });
                            });
                    });
            });
    }).then(result => {
            return done(null);
    }).catch(err => {
            return done(err);
    });

Это работает, поскольку деньги все еще передаются между людьми, но он все еще не подтверждает модели. Я думаю, причина в том, что .validate() и .reload() не имеют возможности добавить на нее параметр transaction: t. Мой вопрос в том, есть ли способ сделать валидацию в транзакции, но мне также нужна помощь в исправлении этого "обратного ада". Опять же, я не делал JS через некоторое время, поэтому, вероятно, есть лучшие способы сделать это сейчас, о чем я сейчас знаю.

Спасибо!

Теги:
validation
sequelize.js
transactions

1 ответ

1
Лучший ответ

Я считаю, что вы не можете получить валидации, чтобы Model increment и decrement Model и должны иметь экземпляры. В некоторых методах Seelize Model вы можете настроить проверки для запуска, но это не похоже на это здесь.

Я бы сделал это так

module.exports = async function(myUserId, sendUserId, money) {
  const transaction = await connection.transaction();
  try {
    const [myUser, sendUser] = await Promise.all([
      User.findById(myUserId, { transaction }),
      User.findById(sendUserId, { transaction })
    ]);
    await Promise.all([
      myUser.increment('balance', {
        by: money,
        transaction
      }),
      myUser.increment('balance', {
        by: -money,
        transaction
      })
    ]);
    await Transaction.create({...}, { transaction })
    await transaction.commit();
  } catch(e) {
    await transaction.rollback();
    throw e;
  }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню