How to make transactions with sails.js/waterline?

wonglik picture wonglik · Jan 15, 2015 · Viewed 7.2k times · Source

I am trying to put my queries into transaction and I am failing in runtime. Error I am getting is :

Object #<bound> has no method 'transaction'

I tried to follow this "documentation".

In short my model looks like that :

updateOrCreate: function (profile_id, positive,negative) {
  var deferred = Q.defer();

  Reputation.transaction().findOne().where({profile: profile_id}).then(function (rep) {
    if (rep) {
      // Reputation logic

      rep.save(function (err) {deferred.resolve();});
    } else {
      // Reputation does not exist. Create.
      Reputation.create({profile: profile_id, positive: positive,negative:negative}).exec(function (e, rep) {
        deferred.resolve();});
    }
  }).fail(function (err) {deferred.reject()});

  return deferred.promise;
}

any ideas what did I do wrong?

thanks.

w.

Answer

edrian picture edrian · Jun 26, 2017

This is now supported in sails v1 (not official release yet at June 26, 2017). You can follow this link for documentation in next.sailsjs.com: Datastore.transaction()

In doc above is the following example:

sails.getDatastore()
.transaction(function (db, proceed) {

  BankAccount.findOne({ owner: req.session.userId }).usingConnection(db)
  .exec(function (err, myAccount) {
    if (err) { return proceed(err); }
    if (!myAccount) { return proceed(new Error('Consistency violation: Database is corrupted-- logged in user record has gone missing')); }

    BankAccount.findOne({ owner: req.param('recipientId') }).usingConnection(db)
    .exec(function (err, recipientAccount) {
      if (err) { return proceed(err); }
      if (!recipientAccount) {
        err = new Error('There is no recipient with that id');
        err.code = 'E_NO_SUCH_RECIPIENT';
        return proceed(err);
      }

      // Do the math to subtract from the logged-in user's account balance,
      // and add to the recipient's bank account balance.
      var myNewBalance = myAccount.balance - req.param('amount');

      // If this would put the logged-in user's account balance below zero,
      // then abort.  (The transaction will be rolled back automatically.)
      if (myNewBalance < 0) {
        err = new Error('Insufficient funds');
        err.code = 'E_INSUFFICIENT_FUNDS';
        return proceed(err);
      }

      // Update the current user's bank account
      BankAccount.update({ owner: req.session.userId })
      .set({
        balance: myNewBalance
      })
      .usingConnection(db)
      .exec(function (err) {
        if (err) { return proceed(err); }

        // Update the recipient's bank account
        BankAccount.update({ owner: req.param('recipientId') })
        .set({
          balance: recipientAccount.balance + req.param('amount')
        })
        .usingConnection(db)
        .exec(function (err) {
          if (err) { return proceed(err); }
          return proceed();
        });
      });
    });
  });

}).exec(function(err){
  // At this point, we know that, if our code above passed through
  // an error to `proceed`, Sails took care of rolling back the
  // transaction.  Otherwise, it committed it to the database.
  if (err && err.code === 'E_INSUFFICIENT_FUNDS') {
    return res.badRequest(err);
  }
  else if (err && err.code === 'E_NO_SUCH_RECIPIENT') {
    return res.notFound();
  }
  else if (err) {
    return res.serverError(err);
  }

  // All done!
  return res.ok();

});