Skip to content
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

Add ability to avoid nested transaction by detecting DatabasePoolConnection is a transaction #556

Open
romandvoskin opened this issue Mar 27, 2024 · 4 comments

Comments

@romandvoskin
Copy link

romandvoskin commented Mar 27, 2024

When writing re-usable code it is often the case that a function accepts a DatabasePoolConnection | DatabaseTransactionConnection, this can be a transaction or database connection. If the function needs to be execute in a transaction AND you want to avoid a nested transaction, it would be helpful to detect if the connection-like object is already a transaction. For reference pg-promise has [txif](https://vitaly-t.github.io/pg-promise/Database.html#txIf) for this purpose

Desired Behavior

Ability to detect that a connection like object is a transaction or the ability to only create a transaction if the given connection-like object is not already a transaction.

Motivation

There are workflows that need need to be transactional AND that use multiple functions requiring passing a connection-like object. It would be useful to only create a transaction if the connection-like object is not already a transaction thus avoiding nested transactions (where a SAVEPOINT is used) and allow an all-or-nothing transaction commit behavior.

Implementation

One idea is to have an overload for transaction like

readonly transaction: <T>(
    handler: TransactionFunction<T>,
    transactionRetryLimit?: number,
    existingConnection?: DatabasePoolConnection | DatabaseTransactionConnection
  ) => Promise<T>;

Another idea is to create a transactionIf function like

readonly transactionIf: <T>(
    handler: TransactionFunction<T>,
    existingConnection: DatabasePoolConnection | DatabaseTransactionConnection,
    transactionRetryLimit?: number
) => Promise<T>;
@gajus
Copy link
Owner

gajus commented Mar 27, 2024

Sounds like this would be as simple as exposing connection.isTransaction() on the connection object.

@romandvoskin
Copy link
Author

romandvoskin commented Mar 27, 2024

Adding connection.isTransaction() would certainly allow the caller to know if a connection is a transaction but it would still require the caller to create a custom function to chose to use an existing connection (that is already a transaction) or call connection.transaction() to create a new transaction. Something like transactionIf removes the need to expose isTransaction() and would use internal logic instead. transactionIf could be a feature for Slonik, for when nested transactions are undesired.

@gajus
Copy link
Owner

gajus commented Mar 27, 2024

transactionIf as a name is super confusing. I think that's what threw me off from the idea.

I could see something like continueTransactionOrStartNew / useOrStartTransaction / ensureTransaction as a valuable addition.

@romandvoskin
Copy link
Author

romandvoskin commented Mar 27, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants