const mongoose = require('mongoose');
const { mongoURI } = require('./config');

const Transaction = mongoose.model('Transaction', new mongoose.Schema({
  amount: {
    type: Number,
    required: true
  },
  fromAccount: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Account',
    required: true
  },
  toAccount: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Account',
    required: true
  }
}));

const Account = mongoose.model('Account', new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  balance: {
    type: Number,
    default: 0
  }
}));

async function transferMoney(fromAccountId, toAccountId, amount) {
  const session = await mongoose.startSession();
  session.startTransaction();

  try {
    const opts = { session };
    const fromAccount = await Account.findById(fromAccountId, null, opts).exec();
    const toAccount = await Account.findById(toAccountId, null, opts).exec();

    if (!fromAccount || !toAccount) {
      throw new Error('One or both of the accounts do not exist.');
    }

    if (fromAccount.balance < amount) { throw new Error('Not enough balance in the account to transfer.'); } fromAccount.balance -= amount; toAccount.balance += amount; await fromAccount.save(opts); await toAccount.save(opts); const transaction = new Transaction({ fromAccount: fromAccountId, toAccount: toAccountId, amount: amount }); await transaction.save(opts); await session.commitTransaction(); session.endSession(); console.log(`Transaction of ${amount} from account ${fromAccountId} to account ${toAccountId} completed successfully.`); } catch (error) { await session.abortTransaction(); session.endSession(); console.error(error); } } mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => {
    console.log('Connected to MongoDB');
    transferMoney('6074e4f4ad4f2150906d8c10', '6074e4f4ad4f2150906d8c11', 100);
  })
  .catch(error => console.error(error));

Trong ví dụ này, chúng ta sử dụng Mongoose để tạo hai model: AccountTransaction. Account mô tả thông tin về tài khoản, bao gồm số dư, trong khi Transaction mô tả thông tin về các giao dịch được thực hiện giữa các tài khoản.

Trong hàm transferMoney, chúng ta bắt đầu một transaction mới bằng cách sử dụng mongoose.startSession()session.startTransaction(). Tiếp theo, chúng ta lấy ra các tài khoản từ cơ sở dữ liệu bằng cách sử dụng Account.findById(). Nếu bất kỳ tài khoản nào không tồn tại, chúng ta sẽ ném một lỗi.

Sau đó, chúng ta kiểm tra xem tài khoản nguồn có đủ số dư để thực hiện giao dịch không. Nếu số dư của tài khoản nguồn không đủ để thực hiện giao dịch, chúng ta sẽ ném một lỗi và cuộn transaction đang được thực hiện trở lại bằng cách sử dụng session.abortTransaction(). Nếu mọi thứ đều ổn, chúng ta cập nhật số dư của tài khoản nguồn và đích, lưu các thay đổi vào cơ sở dữ liệu bằng cách sử dụng model.save(), tạo một transaction mới và lưu nó vào cơ sở dữ liệu. Cuối cùng, chúng ta sẽ hoàn thành transaction bằng cách sử dụng session.commitTransaction() và kết thúc phiên bằng session.endSession().

Lưu ý rằng chúng ta sử dụng các tùy chọn opts trong mọi hoạt động liên quan đến cơ sở dữ liệu trong transaction này. Điều này đảm bảo rằng tất cả các hoạt động này đều sử dụng cùng một phiên MongoDB và do đó là cùng một transaction.

Với ví dụ này, chúng ta có thể chạy ứng dụng và gọi hàm transferMoney để thực hiện một transaction trừ tiền từ tài khoản nguồn 6074e4f4ad4f2150906d8c10 đến tài khoản đích 6074e4f4ad4f2150906d8c11. Nếu giao dịch được thực hiện thành công, hàm sẽ in ra một thông báo trong console.

Chú ý rằng để sử dụng transaction trong MongoDB, phiên bản MongoDB của bạn phải từ 4.0 trở lên và bộ điều khiển MongoDB của bạn phải hỗ trợ các phiên bản này.

Leave a Reply

Your email address will not be published. Required fields are marked *