mysql.createPool transaction with loop
how1231 opened this issue · 1 comments
I'm trying to change mysql connection from mysql.createConnection(config) to mysql.createPool(config). So far most of the APIs required nothing much to change except for transaction.
Problem: There is a for loop going to execute query inside a pool transaction callback hell. But the loop was not waiting for the callback to finish.
- Original code which is working fine
/* Begin transaction */
try {
await db.beginTransaction();
// insert sales
var saleId = await new Promise((resolve, reject) => {
db.query('INSERT INTO sales SET ?', saleData, (err, dbResult) => {
if (err) {
if (err.sqlMessage) console.log(err.sqlMessage);
resolve(null);
} else {
resolve(Object.keys(dbResult).length ? dbResult.insertId : null);
}
});
});
if (!saleId) {
throw "Error: sale id not found, fail to insert sale.";
}
// insert payment
var paymentData = {
method: "cash",
sale_id: saleId
}
var paymentId = await new Promise((resolve, reject) => {
db.query(`INSERT INTO payments SET ?`, paymentData, (err, dbResult) => {
if (err) {
if (err.sqlMessage) console.log(err.sqlMessage);
resolve(null);
} else {
resolve(Object.keys(dbResult).length ? dbResult.insertId : null);
}
});
});
if (!paymentId) {
throw "Error: payment id not found, fail to insert payment.";
}
// update stock
// just an update query inside a loop
for (var i = 0; i < cartList.length; i++) {
var updateStockSql = `UPDATE stocks
SET ${branchId}_quantity = COALESCE(${branchId}_quantity, 0) - ${cartList[i].Total_stock}
WHERE product_id = ${cartList[i].Product_id}`;
var updateStockResult = await new Promise((resolve, reject) => {
db.query(updateStockSql, (err, dbResult) => {
if (err) {
if (err.sqlMessage) console.log(err.sqlMessage);
resolve(null);
} else {
resolve(Object.keys(dbResult).length ? dbResult : null);
}
});
});
if (!updateStockResult) throw "Error: Fail to update stock.";
}
await db.commit();
} catch (error) {
await db.rollback();
return { status: "error", msg: "- Transaction Fail -" };
}
/* End transaction */
- Present code which got problem
/* Begin transaction */
try {
var trxStatus = await new Promise((resolve, reject) => {
db.getConnection((err, trxConn) => {
trxConn.beginTransaction((err) => {
//start
if (err) {
trxConn.rollback(() => trxConn.release());
resolve({ status: "error", msg: `Transaction Fail: ${err}` });
} else {
// insert sales
trxConn.query('INSERT INTO sales SET ?', saleData, (err, salesResult) => {
if (err || !salesResult.insertId) {
// rollback
trxConn.rollback(() => trxConn.release());
if (!salesResult.insertId) err = "Error: sale id not found, fail to insert sale.";
else if (err.hasOwnProperty('sqlMessage')) err = err.sqlMessage;
resolve({ status: "error", msg: `Transaction Fail: ${err}` });
} else {
// insert payments
trxConn.query('INSERT INTO payments SET ?', paymentData, (err, paymentResult) => {
if (err || !paymentResult.insertId) {
// rollback
resolve({ status: "error", msg: `Transaction Fail: ${err}` });
} else {
// here is whr I'm stucked
// update stock
var updateStockStatus = true;
for (var i = 0; i < cartList.length; i++) {
var updateStockSql = `UPDATE stocks
SET ${branchId}_quantity = COALESCE(${branchId}_quantity, 0) - ${cartList[i].Total_stock}
WHERE product_id = ${cartList[i].Product_id}`;
trxConn.query(updateStockSql, (err, updateStockResult) => {
if (err || !Object.keys(updateStockResult).length) {
if (err.hasOwnProperty('sqlMessage')) console.log(err.sqlMessage);
updateStockStatus = false;
}
});
if (!updateStockStatus) break;
}
if (!updateStockStatus) {
// rollback
trxConn.rollback(() => trxConn.release());
resolve({ status: "error", msg: `Transaction Fail: fail to update stock` });
} else {
// commit
trxConn.commit((err) => {
if (err) trxConn.rollback(() => trxConn.release());
else trxConn.release();
resolve({ status: "ok", msg: `- Payment Successful -` });
});
}
}
});
}
});
}
//end
});
});
});
} catch (error) {
console.log(error);
return { status: "error", msg: `Transaction Fail: please contact IT support` };
}
/* End transaction */
Question: Does anyone has any idea on how to solve this kind of asynchronous problem?
ps: Sorry for the long question...I'm already stuck at here for few days, any help would be appreciated, thanks in advance!
Hello, and sorry you are having trouble. Yes, in Node.js using async callbacks in a for loop doesn't work as you would like. Thankfully there is a great library that provides this functionality: https://www.npmjs.com/package/async