Skip to content

Instantly share code, notes, and snippets.

@danneu
Last active June 9, 2016 10:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danneu/9eb48875bf9563a8f7fe6faf22239de7 to your computer and use it in GitHub Desktop.
Save danneu/9eb48875bf9563a8f7fe6faf22239de7 to your computer and use it in GitHub Desktop.
function rollback (conn, cb) {
conn.query('ROLLBACK', function (err) {
if (err) {
console.log('Rollback failed');
// need to remove conn from the pool
return cb(err);
}
return cb();
})
}
function withTransaction (tasks, cb) {
getConnection(function (err, conn) {
if (err) return cb(err);
conn.query('START TRANSACTION', function (err) {
if (err) return cb(err);
// here we give the connection to each task
async.parallel(tasks.map(conn), function (err) {
if (err) return rollback(conn, cb);
conn.query('COMMIT', function (err) {
if (err) return rollback(conn, cb);
/* if we get here, the transaction succeeded */
return cb();
});
});
});
})
}
// EXAMPLE
// We basically need to end up with a function that takes the DB conn
// as an argument at a later time (i.e. from inside the withTransaction function)
function updateBalance (accountId, amount) {
return function pretask (conn) {
return function task (cb) {
conn.query(`
UPDATE accounts
SET balance = $2
WHERE id = $1
`, [accountId, amount], function (err) {
if (err) return cb(err);
return cb();
});
}
}
}
app.post('/transfer/:fromAccount/:toAccount/:amount', function (req, res, next) {
var tasks = [];
tasks.push(updateBalance(req.params.fromAccount, -req.params.amount));
tasks.push(updateBalance(req.params.toAccount, req.params.amount));
withTransaction(tasks, function (err) {
if (err) return next(err);
res.json({ transfer: 'success' });
});
});
@danneu
Copy link
Author

danneu commented Jun 9, 2016

If you're on Node 6.x, you can clean up the db function:

function updateBalance (accountId, amount) {
  return (conn) => (cb) => {
    conn.query(`
      UPDATE accounts 
      SET balance = $2
      WHERE id = $1
    `, [accountId, amount], (err) => {
      if (err) return cb(err);
      return cb();
    });
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment