【问题标题】:How to increase transaction timeout in Quarkus?如何增加 Quarkus 中的事务超时?
【发布时间】:2019-11-06 20:09:31
【问题描述】:

我的 application.properties 文件中有一些配置:

...
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
...

我有一个带有 @Transactional 方法的调度程序,它需要很长时间才能完成执行:

@ApplicationScoped
class MyScheduler {

...

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

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

    }
}

然后,事务方法收到类似这样的超时错误:

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

我相信我必须增加我的事务方法的超时时间。 但我不知道我该怎么做。

有人可以帮帮我吗?

谢谢!

【问题讨论】:

    标签: quarkus


    【解决方案1】:

    使用@TransactionConfiguration 注解并指定秒数:

    @Transactional
    @TransactionConfiguration(timeout = 9876)
    @Scheduled(every = "7200s")
    open fun process() {
    
        ... my slow proccess goes here...
        entityManager.persist(myObject)
    
    }
    

    【讨论】:

      【解决方案2】:

      似乎这已经改变了 -> 现在可以设置事务超时:

      https://quarkus.io/guides/transaction

      您可以通过属性配置默认事务超时,适用于事务管理器管理的所有事务的超时:

      quarkus.transaction-manager.default-transaction-timeout = 240s
      

      -> 指定为持续时间(java.time.Duration 格式)。默认为 60 秒

      【讨论】:

        【解决方案3】:

        Quarkus 还不允许您全局配置默认事务超时(请参阅 https://github.com/quarkusio/quarkus/pull/2984)。

        但您应该能够在用户事务级别执行此操作。

        您可以注入 UserTransaction 对象并在 postconstruct bloc 中设置事务超时。

        这样的事情应该可以工作:

        @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)
        
            }
        }
        

        如果您提取在 Service 中进行事务的代码,您可以使用带有 @Transactional 注释的服务,在调度程序中注入 UserTransaction 并在调用服务之前设置事务超时。

        所有这些都有效,我刚刚测试了这两种解决方案;)

        【讨论】:

          【解决方案4】:

          感谢@loicmathieu 的回答!

          我将在下面添加更多详细信息。

          您需要在开始事务之前删除@Transactional 并设置事务超时。最后,你必须提交事务:

          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()
              }
          }
          

          【讨论】:

          • 你说得对,我用两个有效的解决方案更新了我的答案,它们仍然允许您使用 @Transactional 注释来获得自动事务支持。因为你的实现太天真了,因为它没有实现回滚和正确的错误处理。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-12-17
          • 2010-12-03
          • 2016-02-12
          • 2023-02-22
          • 1970-01-01
          • 2011-11-08
          • 2013-01-07
          相关资源
          最近更新 更多