-
-
Notifications
You must be signed in to change notification settings - Fork 619
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
This PR adds support for .transaction() #814
base: master
Are you sure you want to change the base?
Conversation
…ransactions now work on Pools and Connections
thoughts re new api @sushantdhiman @gajus @mscdex @dougwilson ? |
I don't have an opinion as I don't use Promises. |
One thing to note: The proposed .transaction() function includes options that the current .beginTransaction() function does not currently accept. IMO, if .transaction() is going to accept options, then .beginTransaction() should probably do so as well. |
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.
API looks good, I have a suggestion to add ISOLATION LEVELS as they are useful concept when working with transactions.
promise.js
Outdated
return userPromise(self); | ||
}); | ||
|
||
if (options.autoCommit === false) { |
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.
You meant autoCommit : true
?
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.
Actually I meant !== true, as I don't want truthy objects to enable autocommit, only the exact value autoCommit: true
promise.js
Outdated
if (options.autoCommit !== true) { | ||
promiseChain = promiseChain.then(function() { | ||
return self.query( | ||
"START 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.
You might also want to support isolation levels https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
A constant type can be exported directly by require('mysql2').ISOLATION_LEVELS
promise.js
Outdated
@@ -214,6 +214,47 @@ PromiseConnection.prototype.changeUser = function(options) { | |||
}); | |||
}); | |||
}; | |||
PromiseConnection.prototype.transaction = function(options,userPromise) { |
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.
/nitpick userPromise
is not a promise, its a callback that will return a promise, name should reflect that
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.
Nitpick accepted
I have been using an interchangeable API without any issues for a while now (https://github.com/gajus/slonik#slonik-query-methods-transaction). |
…tionLevel: as one of the supported parameters
I would argue that |
I don't think it's an option, we have to account for mysql2 users who currently use beginTransaction and mysqljs/mysql users whu might occasionaly switch between libs. If we decide to needs to be coordinated between both and go through long deprecation cycle. Much easier for promise wrapper though |
Looks good, will need some integration tests and it should be good to go |
Looking at the user docs for the API I think it is a really neat use for promises. As for this vs beginTransaction, I guess the only comment I would have is that the new API does not support callbacks at all while the old one does. If the old is removed that would be the only consideration: should callbacks just be removed from the entire driver surface? |
@dougwilson you mean remove |
Sorry, I meant that if the idea is after landing this new API that beginTransaction would end up deprecated and removed, then there wouldn't be a transaction callback API any longer. |
I'd recommend leaving beginTransaction() for compatibility with mysqljs, and adding the following behavior: This model will allow you to have managed transactions when using the callback API, and managed transactions + automatic connection release when using the Promise API |
Any thoughts on this PR? I've been using it in production for a while, and updated it yesterday to be compatible with the new class-style code that is now in promise.js, which seems to work fine I'd like it if we could make a decision one way or another; if it's not something that should be included in the main tree i'd rather convert it into a monkey patch in a separate repository so I can maintain it without having to merge changes into my fork Also, any feedback as far as automatically rolling back open transactions when a connection is returned to the pool? If some bad code throws an exception, and then returns a connection to the pool that has an already open transaction, it seems like that would be very bad situation. |
) | ||
.catch( err => | ||
this.rollback() | ||
.catch(() => null) |
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 should probably emit an error or even override the previous error, it certainly shouldn't be swallowed.
|
||
const startTransactionSQL = | ||
"START TRANSACTION" + | ||
( options.consistentSnapshot === true ? " WITH CONSISTENT SNAPSHOT," : "" ) + |
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.
Inconsistent quotes, apparently lint isn't enforcing this.
con.release(); | ||
return res; | ||
}) | ||
.catch(err => { |
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.
Nit, you probably want to merge the then
and catch
into one then(ok, err)
chain instead, otherwise the catch handler would potentially catch .release()
errors.
I'm really looking forward to be able to use transactions on node-mysql2, if there is anything I can help here I'll be glad to do. |
So we've been using this for the past year, it helps a little bit in simplifying our code, but I am thinking of re-designing this, as it doesn't really solve the problem we envisioned. We have a collection of related problems in the code we have which uses node-mysql2:
So to fix these 4 issues, i'm thinking of making a new module which implements a "managed" query interface that could run on top of the mysql or mysql2 driver - which would allow you to define a chain of queries, possibly with intermediate code run between them to do calculations, which would then run them either in a transaction or raw. It could also flag the individual queries as read vs write so they can be routed to one or more pools, and would handle failures more intelligently - for example you might choose to retry queries twice then fail hard. The idea being to add on a couple key convenience features that ORM systems implement while still writing raw SQL queries. As such, i'm not sure if it makes a ton of sense to merge in one particular method of working with transactions into the MySQL driver - the API in the driver should probably be unopinitated (and allow you to do everything) - or opinionated but optional (like what I am thinking of) |
New pull request for the functionality in this pull request:
#811
I had to create a new PR and close the old one, as github will not allow me to change the head branch once a PR is filed
This adds support for PromiseConnection.transaction() to MySQL2