-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Executing services methods using transaction, implementation of issue #91 #113
Executing services methods using transaction, implementation of issue #91 #113
Conversation
Great! I'm looking on your solution because I need the same functionality. Put a nested json to a rest service and store it in diverse tables using a all-or-nothing transaction. One small quesition: Is it possible to use hook.service instead of hook.app.get(dbServiceName) in transaction start? This would remove the need for the service name parameter - which is likely to be forgotten, when you rename a service during refactoring later on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thank you for doing this! I made a couple of comments/questions.
Ideally, we'd also want to test this functionality somehow (e.g. having two services, one called in a hook with the transaction, throwing an error and making sure both are rolled back). It looks like SQLite supports transactions so you should be able to just run tests via npm test
.
src/index.js
Outdated
|
||
const debug = require('debug')('feathers-knex'); | ||
const debugTransaction = require('debug')('feathers-knex-transaction'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually only use one debug
per module.
src/index.js
Outdated
db (params = {}) { | ||
if (params.transaction) { | ||
const { trx, id } = params.transaction; | ||
debugTransaction('ran %s with transaction %s', this.table, id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd change this to just debug
src/index.js
Outdated
@@ -169,6 +176,7 @@ class Service { | |||
} | |||
|
|||
find (params) { | |||
debug('method find of service %s called', this.table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be removed for consistency (we might want to add more debug statements to all database adapters but that would be a different issue).
src/transaction-hooks.js
Outdated
@@ -0,0 +1,42 @@ | |||
const debug = require('debug')('feathers-knex-transaction'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to rename this file to just hooks
and call the methods transactionStart
, transactionEnd
and transactionRollback
and export it as init.hooks
instead of https://github.com/feathersjs/feathers-knex/pull/113/files#diff-1fdf421c05c1140f6d71444ea2b27638R339
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively we could also export it as export default { transaction: { start, end, rollback } }
and use it as hooks.transaction.start
etc.
src/transaction-hooks.js
Outdated
debug('started transaction system with %s service', dbServiceName); | ||
return (hook) => | ||
new Promise(resolve => | ||
hook.app.get(dbServiceName).transaction(trx => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try if hook.service.Model
works here? I think it should (because it is the same thing really).
@daffl should I remove the debug from the |
@pnakibar Sorry, I meant one |
It's alright! Just submitted a new PR with the requested changes. |
Awesome, looks great! Any chance to add some tests or would you like me to try and add those? |
The new app.hooks.js:
|
@daffl if you could, it would be awesome! |
Also, we have to update https://docs.feathersjs.com/api/databases/knexjs.html with a section for transaction support once this is released. |
Also, the options object to the |
I don't think the option is necessary. Did you try |
Will try it, my concern was with using two database adapters. |
@daffl tried it. Was a bit unsuccessful, since not all my services have the |
Thank you all for your great work! This is going on so fast, it's amazing! Maybe you could allow the developer to pass his own Model. Or use the default, if he doesn't.
The parameter name "Model" is already used for passing the db instance at knex db service init. Also if you just need some db instance, exposing only this instead of a whole service could decouple things. Just thinking about this... |
The I can't think of a case where this would change throughout a transaction (and I don't think transactions across different databases are possible at the Knex level). |
@daffl is it still ok to merge the pull request? |
Sorry, for some reason I dropped the ball on this. Merged. Will add some tests and let you know when it's released. |
Released as v2.8.0 |
My solution to the issue #91 .
Pretty much a naive implementation due to not knowing the internals of knex.
Easy to use, simply import the newly created hooks and add them to the hooks of the service you want to use it (usually in global hooks) and then the
feathers-knex
deal with using the transaction.Usage:
Looking forward to some feedback on the code!