Is there a way in pg-promise to trigger an inner transaction that won't affect the outer transaction?

217 views Asked by At

In pg-promise I have a situation in which I need to trigger an inner transaction that can roll back if needed that won't cause the calling transaction to be rolled back when it errors:

var db = pgp()(connection);
db.task( function (tk){
  tk.method(/* Logic used to decide if I need to continue */)
  .then( function(data){
    if (!data) return;
    tk.tx( function*(tx){
      // Somewhere in here I need to fire another transaction that I don't care if it fails
      // but I need things to roll back inside of it should it fail
      // without cause this tx to fail
    })
  })
})

Everything I've tried so far has just caused the outer transaction (tx) to rollback if the inner transaction fails instead of the inner transaction rolling back and the outer transaction continuing with the logic that would come after. Is there a reliable way to cause an inner transaction that WON'T cause tx to rollback if the child transaction fails?

As an additional: this also fails when I attempt to use a Bluebird Promise.some(tx1, tx2) as either failing causes tx to roll back and the other tx# to fail and rollback as well.

1

There are 1 answers

3
vitaly-t On BEST ANSWER

Everything within pg-promise, as the name implies, built on promises, including the transaction logic, so the answer you are looking for is purely promise-related:

If you do not want the result of an inner promise to affect the outer promise, you simply do not chain that inner promise to the parent, you process/handle it locally instead.

For your transaction this means that instead of this:

tk.tx(function * (t1) {
    return yield t1.tx(function * (t2))
       // chained inner transaction (savepoint)
    });
}).then(data=>{}).catch(error=>{});

you would be doing this:

tk.tx(function * (t1) {
    t1.tx(function * (t2))
        // unchained/localized inner transaction (savepoint)
    }).then(data=>{}).catch(error=>{});
}).then(data=>{}).catch(error=>{});

i.e. you process the result from the inner transaction locally, without chaining it to the parent.