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

proposal: database/sql: Check if Tx has already been committed or rolled back #38012

Open
pjebs opened this issue Mar 22, 2020 · 5 comments
Open

Comments

@pjebs
Copy link
Contributor

pjebs commented Mar 22, 2020

I have a use case where I would like to know if Tx has already been committed or rolledback. I can't track this information myself because it's for a package that is intended to be used by third parties.

Currently I have to perform a "fake" query on the Tx to check if it returns sql.ErrTxDone. This is ok if the transaction has in fact been committed or rolledback. But if it hasn't, then it will actually take time to call the query.

I believe the object internally tracks this information and it would be good if it was exposed.

@gopherbot gopherbot added this to the Proposal milestone Mar 22, 2020
@kardianos
Copy link
Contributor

This is an interesting proposal.

Could you explain a bit of the backstory about why you are checking to see if Tx has been committed or rolled back?

@pjebs
Copy link
Contributor Author

pjebs commented Jun 8, 2020

I actually can't remember much anymore because it was for some contract work I did for a random client many months ago.

I vaguely remember it was a package with a function to be used by a third party user. The third party user provides a *Tx object to the function.

The adjustment to be made is:

func (tx *Tx) IsDone() bool {
   tx.closemu.RLock()
   defer tx.closemu.RUnlock()
   return tx.isDone()
}

@kardianos
Copy link
Contributor

That is certainly a fine implementation, but without a concrete use case the proposal won't go anywhere.

@rsc rsc added this to Incoming in Proposals (old) Jun 10, 2020
@ocket8888
Copy link

My usecase is a unified cleanup function. Something like

defer func() {
    e := recover()
    if e != nil {
        log.Errorln("panic happened: ", e)
    }
    if !tx.IsDone() {
        tx.Rollback()
    }
}()

@mikestefanello
Copy link

I have a use-case for where this would be very useful but I can't imagine it's a case common enough to warrant a change. I'm working on a library to provide DB-persistent task queues. When creating a task, you can optionally supply a DB transaction and the task creation will be added to it. River queue does something very similar to this. An example is you're creating a new user and as part of that transaction you want to save a task to send a welcome email. The challenge with tacking on to the provided transaction is the library will never know if or when the task was saved without asking/polling the database for some amount of time. There's code I'd like to execute after the transaction is complete but there's no way to do that. Ideally, this is either something like a channel you can listen to, or some sort of hook you can register to execute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

No branches or pull requests

5 participants