zoran119
zoran119

Reputation: 11327

Can I commit inside withTransaction closure

Can I commit inside the withTransaction closure? I want to do something like this inside my Quartz job:

Author.withTransaction {
    def author = Author.get(1)
    author.staus = 'processing'
    author.save()
    commit // how can i do this?
    // so some work here which takes 1-2 minutes
    author.status = 'completed'
    author.save()
}

The idea is that I want to have a status screen which will show all the Authors which are being processed at the moment, so I want to set the status to processing and be able to see this status from a controller.

EDIT: This would work without withTransaction, but I have to have withTransaction there... see this question.

Upvotes: 4

Views: 3686

Answers (2)

dmahapatro
dmahapatro

Reputation: 50275

I would try to stick to @codelark's approach as much as I can , programmatically handling the transaction and adding logic for rollback as well.

It is a co-incident that I was also digging grounds with codelark on this question. Here is what I have now:

    Author.withSession{session->
        def author = Author.get(blahId)
        try{
            def tx = session.beginTransaction()
            //Update status to processing
            author.status = 'processing'
            tx.commit()

            //Do your 1 - 3 minutes task
        } catch(e){
            //If there is any exception in that task then rollback transaction
            tx?.setRollbackOnly()
        }

        if(!tx.isRollbackOnly()){
            try {
                def tx2 = session.beginTransaction()
                //Update author status to completed
                //Few pain points can also be taken care of here, like checking if the task completed as expected etc..
                author.status = 'completed'
                tx2.commit()
            }
            catch(Exception e) {
                tx2?.setRollbackOnly() //If you want
            }
        }
    }

@Alidad is absolutely correct in saying that commit/flush happens at the end of the withTransaction block. So flush: true inside withTransaction would not work.

Upvotes: 0

codelark
codelark

Reputation: 12334

In order to read values from a different uncommitted transaction, your database isolation level has to be set to "read uncommitted" which is often an indicator you might be doing something wrong.

Is there any reason you couldn't separate this into separate transactions? One to mark the records as "in-progress" and one to perform the actual work?

Author.withTransaction {
    def author = Author.get(id)
    author.status = 'processing'
    author.save()
}

Author.withTransaction() {
    def author = Author.get(id)
    // do some work
    author.status = 'completed'
    author.save()
}

Upvotes: 2

Related Questions