CodeFoodPixels / node-promise-mysql

A wrapper for mysqljs/mysql that wraps function calls with Bluebird promises.
MIT License
338 stars 63 forks source link

Transaction not rolling back #84

Closed blackout1208 closed 6 years ago

blackout1208 commented 6 years ago

Can anyone explain me why this transaction is not rolling back?

async function Transaction(conn, competitions) {
  await conn.beginTransaction();

  competitions.forEach(async eachCompetition => {
    eachCompetition.tournamentCalendar.forEach(async season => {
      const newCalendar = await GetCompetitionCalendar(conn, season, idCompetition);
      const { idCompetition, id, name, startDate, endDate, isActive } = newCalendar;
      const response = await conn.query(`UPDATE CompetitionCalendar
      SET idCompetition = '${idCompetition}', name = '${name}',
      startDate = '${startDate}', endDate = '${endDate}', isActive = '0'
      WHERE id = '${id}'`);
    });
  });
  await conn.rollback();
}

Meanwhile, if I use in this method works fine:

async function TEST(conn) {
  try {
    await conn.beginTransaction();

    for (let i = 0; i < 10; i++) {
      await conn.query("UPDATE CompetitionType SET name='TEST TO FAIL 2213" + i + "' WHERE idCompetitionType='35'");
      await conn.query("INSERT INTO CompetitionType SET name='TEST TO FAIL'");
    }
  } catch (e) {
    // conn.rollback();
  }
  await conn.rollback();
}
CodeFoodPixels commented 6 years ago

I'd check for race conditions, the rollback may be getting called before any changes are made. That's the only thing that comes to mind at the moment.

johanneslumpe commented 6 years ago

The issue here is that forEach does not support async functions and thus does not wait for them to resolve. The function doesn’t get suspended, so the transaction is rolled back instantly after forEach ran, but before the inner functions complete.

CodeFoodPixels commented 6 years ago

Yep, that's completely it. I'd use Bluebird's Promise.each: http://bluebirdjs.com/docs/api/promise.each.html