Search code examples
quarkus

How to increase transaction timeout in Quarkus?


I have some configurations in my application.properties file

...
quarkus.datasource.url=jdbc:postgresql://...:5432/....
quarkus.datasource.driver=org.postgresql.Driver
quarkus.datasource.username=user
quarkus.datasource.password=password
quarkus.hibernate-orm.database.generation=update
...

I have a scheduler with a @Transactional method that takes a long time to finish executing:

@ApplicationScoped
class MyScheduler {

...

    @Transactional
    @Scheduled(every = "7200s")
    open fun process() {

        ... my slow proccess goes here...
        entityManager.persist(myObject)

    }
}

And then, the transactional method receives a timeout error like that

2019-06-24 20:11:59,874 WARN  [com.arj.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a000020:d58d:5cdad26e:81 in state  RUN

2019-06-24 20:12:47,198 WARN  [com.arj.ats.arjuna] (DefaultQuartzScheduler_Worker-3) ARJUNA012077: Abort called on already aborted atomic action 0:ffff0a000020:d58d:5cdad26e:81

Caused by: javax.transaction.RollbackException: ARJUNA016102: The transaction is not active! Uid is 0:ffff0a000020:d58d:5cdad26e:81

I believe that I must increase the timeout of my transactional method. But I don't know how I can do this. Someone could help me, please?


Solution

  • Quarkus don't allow you to globally configure the default transaction timeout yet (see https://github.com/quarkusio/quarkus/pull/2984).

    But you should be able to do this at the user transaction level.

    You can inject the UserTransaction object and set the transaction timeout in a postconstruct bloc.

    Something like this should work :

    @ApplicationScoped
    class MyScheduler {
    
        @Inject UserTransaction userTransaction;
    
        @PostConstruct
        fun init() {
            //set a timeout as high as you need
            userTransaction.setTransactionTimeout(3600);
        }
    
        @Transactional
        @Scheduled(every = "7200s")
        open fun process() {
            entityManager.persist(myObject)
    
        }
    }
    

    If you extract the code that make the transaction inside a Service, you can have a service with a @Transactional annotation, inject the UserTransaction in your scheduler and set the transaction timeout before calling the service.

    All this works, I just tested both solution ;)