Reputation: 325
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?
Upvotes: 21
Views: 17441
Reputation: 18153
There are 3 ways of doing it :
quarkus:
transaction-manager:
default-transaction-timeout: 120s
@Transactional
@TransactionConfiguration(timeout = 120)
public void myService() {
...
}
QuarkusTransaction
(timeout is in seconds)public void myService() {
QuarkusTransaction.requiringNew()
.timeout(30)
.run(() -> myRepo.persist(new Data()));
}
Upvotes: 5
Reputation: 2959
Use the @TransactionConfiguration annotation and specify the seconds:
@Transactional
@TransactionConfiguration(timeout = 9876)
@Scheduled(every = "7200s")
open fun process() {
... my slow proccess goes here...
entityManager.persist(myObject)
}
Upvotes: 8
Reputation: 1266
Seems that this has changed -> it is now possible to set the Transaction timeout:
https://quarkus.io/guides/transaction
You can configure the default transaction timeout, the timeout that applies to all transactions managed by the transaction manager, via the property:
quarkus.transaction-manager.default-transaction-timeout = 240s
-> specified as a duration (java.time.Duration format). Default is 60 sec
Upvotes: 21
Reputation: 5562
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 ;)
Upvotes: 8
Reputation: 325
Thanks @loicmathieu for the answer!
I will just append some more details below.
You need to remove @Transactional and set transaction timeout before begin the transaction. In the end, you must commit the transaction:
import io.quarkus.scheduler.Scheduled
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.transaction.UserTransaction
@ApplicationScoped
open class MyScheduler {
@Inject
lateinit var em: EntityManager
@Inject
lateinit var ut: UserTransaction
@Scheduled(every = "3600s")
open fun process() {
ut.setTransactionTimeout(3600)
ut.begin()
offerService.processOffers()
ut.commit()
}
}
Upvotes: 3