ditojs / dito

Dito.js is a declarative and modern web framework with a focus on API driven development, based on Objection.js, Koa.js and Vue.js – Developed at Lineto by Jürg Lehni and made available by Lineto in 2018 under the MIT license
https://lineto.com
MIT License
82 stars 8 forks source link

Add support for transactions on controller actions #5

Closed lehni closed 6 years ago

lehni commented 6 years ago

As proposed by @koskimas & @ollisal:

@action('get')
@transactional()
async doStuff(ctx) {
  await Thingy.query(ctx.trx)
  ...
}

The koa's middleware are perfect for transaction management:

async function transactionMiddleware(ctx, next) {
  const trx = ctx.trx = await transaction.start()
  try {
    await next()
    await trx.commit()
  } catch (err) {
    await trx.rollback()
  }
  ctx.trx = null
}

This would allow other middleware to use the transaction too. For example it's sometimes good (or even necessary) that the session update query takes part in the same transaction. This way the session middleware could use ctx.trx if it exists.

lehni commented 6 years ago

Unfortunately it looks like this is currently only possibly with some nasty cacks inside koa-session. I've created an issue there to make it possible, let's see how it goes:

https://github.com/koajs/session/issues/144

lehni commented 6 years ago

The only workaround I see so far is to (ab)use the session.before.beforeSave(ctx) hook to get access to the ctx object, temporarily store it on the custom store so the store can access it in its set() method. This sounds dodgy to me though, and I'm wondering if there isn't an async in between somewhere that would mean that we may get the wrong values for ctx in set() when multiple requests are being received.