Imu Sama
Imu Sama

Reputation: 364

Transaction cannot be rolled back because it has been finished

I am trying to create an order and associate the order with products and quantities :

const t = await sequelize.transaction();
  try {
    const local_orderInstance = await LocalOrder.create({
      user: req.body.client,
      timestamp: Date.now(),
    }, {transaction: t})
    for(let order_item of req.body.items) {
      const order_itemInstance = await LocalOrderItem.create({
        quantity: order_item.quantity,
        ProductReference: order_item.reference,
        LocalOrderId: local_orderInstance.id
      }, {transaction: t})
      await t.commit()
      res.json({message: `successfully saved order`})
    }
  } catch(error) {
    await t.rollback()
    res.status(503).json(error)
  }

enter image description here

As you can see, it's very similar to the example in the sequelize documentation but a weird thing is happening, even when there is no error with all the inserts in the database, (t.commit() is called), apparently it still goes in the catch section and tries to rollback. And after that I get the error "Transaction cannot be rolled back because it has been finished with state: commit" Why does it try to execute the catch section even though there is no exception thrown ? I am also getting this "[DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code." It really wants me to try catch the rollback ? Well I tried and I am getting " Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" Is nodejs broken ?

Upvotes: 3

Views: 3421

Answers (1)

apple apple
apple apple

Reputation: 10604

you should commit after the loop. or create new transaction object each iteration.

const t = await sequelize.transaction();
  try {
    const local_orderInstance = await LocalOrder.create({
      user: req.body.client,
      timestamp: Date.now(),
    }, {transaction: t})
    for(let order_item of req.body.items) {
      const order_itemInstance = await LocalOrderItem.create({
        quantity: order_item.quantity,
        ProductReference: order_item.reference,
        LocalOrderId: local_orderInstance.id
      }, {transaction: t})  
    }
    await t.commit() // <--- move outside of loop
    res.json({message: `successfully saved order`})
  } catch(error) {
    await t.rollback()
    res.status(503).json(error)
  }

Upvotes: 3

Related Questions