-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add pg-transaction module #3516
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
Conversation
Deploying node-postgres with
|
Latest commit: |
b954f53
|
Status: | ✅ Deploy successful! |
Preview URL: | https://d83c65ed.node-postgres.pages.dev |
Branch Preview URL: | https://bmc-pg-txn.node-postgres.pages.dev |
hmmm this is actually a bit frustrating...with the Option 1: async function doSomethingTransactionalInDatabase() {
await using txn = transaction(client, async (client) => {
await client.query('...')
})
} With option 1 since we're calling a callback with the client we can know for sure if the async callback throws and then automatically commit/rollback accordingly. Option 2: async function doSomethingTransactionalInDatabase() {
async using txn = transaction(client)
await client.query('...')
await txn.commit()
} Option 2 would be making the transaction object have a With option two I could also put a Option 2: async function doSomethingTransactionalInDatabase() {
async using txn = transaction(client)
await txn.query('...')
await txn.commit()
} There's also a 3rd thing I played with, but not a fan at all. Including it for sake of completeness I suppose. The semantics here would be once the scope exits the transaction is automatically commited. Problem is, because we don't have access to an error being thrown or not when disposing we will always commit, even when there's an error. You'd have to explictly call Option 3: async function doSomethingTransactionInDatabase() {
async using txn = transaction(client)
client.query('....')
throw new Error("the first query will still be comitted')
client.query('...this one wont ever get hit')
}
// if you wanted to properly rollback you'd have to do this disgustingness:
async function doSomethingTransactionInDatabase() {
async using txn = transaction(client)
try {
client.query('....')
throw new Error("the first query will still be comitted')
client.query('...this one wont ever get hit')
} catch (e) {
txn.rollback()
throw e
}
} |
hmmm the more i mess w/ this the more it feels like using disposable here doesn't really fit. Particularly, option 1 can be accomplished without disposables at all. Just auto-commit at the end of an async callback if its successful, and auto-rollback otherwise. That also means there's no requirement for changing minimum node version or anything. I think I might go back to the drawing board a bit here. The more I use option 2 it feels yucky to have to call "commit" but what you're really doing is deferring a call to commit to happen later (when the block exits) which kinda seems to violate the "principal of least surprise" and I also just don't think its bringing much to the table outside a standard async callback. |
Add
pg-transaction
module. With the introduction of theusing
keyword to javascript, I've been interested in experimenting with incorporating it intopg
code because quite a bit of database driver code is dealing with resource management and clean up. This is still a draft until I can get the tests passing for all (supported) node versions and write docs and so on, but want to put this up early to get some 👀 on it and some thoughts about the API, etc.One thing to note: savepoints aren't in scope for this. I have honestly never used them, and if you need something more advanced like savepoints its probably best to roll that code yourself more manually.
Particularly interested in more failure modes I could test that I'm missing in the tests here.
edit: note - the old maintainer of the pg-transaction module on npm has graciously turned over the ownership/name to me, and since this is a drastic departure from its old API this would be a semver major bump of the old module. cc @jrf0110 ❤️