0

Im trying to extend the QueryBuilder of Knex.js. I want to modify the delete() method in order to delete the child elements of my Objection.js Model. Current code works well, but I want to support transactions in the new method:

class CustomQueryBuilder extends QueryBuilder {
  // Override delete method
  delete() {
    return super.select('*').first().runAfter(async (old, builder) => {
      // Some extra logic here, being able to access old entry
      return await old.query().nativeDelete() // original delete
    })
  }

  nativeDelete() {
    return super.delete()
  }
}

Where is the transaction of current context? Is it accesible?

Note: I cannot pass it as a param in delete(trx) function, since delete() could be called from other methods without passing it explicitly as a param

Rashomon
  • 5,962
  • 4
  • 29
  • 67

1 Answers1

0

The current transaction of the QueryBuilder is accesible trough builder.context():

class CustomQueryBuilder extends QueryBuilder {
  // Override delete method
  delete() {
    return super.select('*').eager('reference').runAfter(async (olds, builder) => {
      return await Promise.all(olds.map(old => old.$query(builder.context().transaction).mergeContext(builder.context()).nativeDelete()))
    })
  }

  nativeDelete() {
    return super.delete()
  }
}
Rashomon
  • 5,962
  • 4
  • 29
  • 67
  • 1
    `Promise.all` like that may cause you problems and since all the queries are going through the same transaction you wont get any parallelism benefits from there either. `Promise.all` will reject / throw an error when first of the queries fail, so your `delete()` method throws an error, but other promises you initialized in `olds.map` are still executing... so better would be to use normal for (let old of olds) loop and await every query separately. – Mikael Lepistö Apr 24 '19 at 22:03
  • This was on the way to production... I will check it and fix this response. Thanks for your comment @MikaelLepistö – Rashomon Apr 26 '19 at 08:51