不同线程上的 Quarkus 事务
Quarkus Transactions on different thread
我有一个带有异步端点的 quarkus 应用程序,它创建一个具有默认属性的实体,在请求方法中启动一个新线程并执行一个长 运行 作业,然后 returns 实体作为供客户跟踪的响应。
@POST
@Transactional
public Response startJob(@NonNull JsonObject request) {
// create my entity
JobsRecord job = new JobsRecord();
// set default properties
job.setName(request.getString("name"));
// make persistent
jobsRepository.persist(job);
// start the long running job on a different thread
Executor.execute(() -> longRunning(job));
return Response.accepted().entity(job).build();
}
此外,长 运行 作业将在实体运行时对其进行更新,因此它也必须是事务性的。然而,数据库实体并没有得到更新。
这些是我面临的问题:
- 我收到以下警告:
ARJUNA012094: Commit of action id 0:ffffc0a80065:f2db:5ef4e1c7:0 invoked while multiple threads active within it.
ARJUNA012107: CheckedAction::check - atomic action 0:ffffc0a80065:f2db:5ef4e1c7:0 commiting with 2 threads active!
似乎是应该避免的事情。
我试过 @Transaction(value = TxType.REQUIRES_NEW)
没用。
我尝试在 longRunning
上使用 API Approach 而不是 @Transactional
方法,如下 guide 中所述:
@Inject UserTransaction transaction;
.
.
.
try {
transaction.begin();
jobsRecord.setStatus("Complete");
jobsRecord.setCompletedOn(new Timestamp(System.currentTimeMillis()));
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
但随后我收到错误:ARJUNA016051: thread is already associated with a transaction!
和 ARJUNA016079: Transaction rollback status is:ActionStatus.COMMITTED
这次我在启用 context propagation 的情况下再次尝试了声明式和基于 API 的方法。但是还是不行。
最后,基于第三种方法,我认为将 @Transactional
保留在 Http 请求处理程序上,并在没有声明或基于 API 的情况下保留 longRunning
交易方法会起作用。但是数据库仍然没有更新。
显然我误解了 JTA 和上下文传播的工作原理(以及其他)。
有没有一种方法(甚至是一种设计模式)允许我在 quarkus Web 应用程序中异步更新数据库实体?还有为什么我采取的任何方法都没有任何效果?
使用 quarkus 1.4.1.Final 与 ext: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, kubernetes-client, mutiny, narayana-jta, rest-客户端、resteasy、resteasy-jackson、resteasy-mutiny、smallrye-context-propagation、smallrye-health、smallrye-openapi、swagger-ui]
您应该 return 来自 JAX-RS 资源方法的异步类型,事务上下文将在异步阶段执行时可用。 quarkus guide on context propagation.
中有一些相关文档
我将从查看 getting started quickstart 等反应性示例之一开始。尝试使用 @Transactional 注释每个资源端点,异步代码将 运行 使用事务上下文。
我有一个带有异步端点的 quarkus 应用程序,它创建一个具有默认属性的实体,在请求方法中启动一个新线程并执行一个长 运行 作业,然后 returns 实体作为供客户跟踪的响应。
@POST
@Transactional
public Response startJob(@NonNull JsonObject request) {
// create my entity
JobsRecord job = new JobsRecord();
// set default properties
job.setName(request.getString("name"));
// make persistent
jobsRepository.persist(job);
// start the long running job on a different thread
Executor.execute(() -> longRunning(job));
return Response.accepted().entity(job).build();
}
此外,长 运行 作业将在实体运行时对其进行更新,因此它也必须是事务性的。然而,数据库实体并没有得到更新。
这些是我面临的问题:
- 我收到以下警告:
ARJUNA012094: Commit of action id 0:ffffc0a80065:f2db:5ef4e1c7:0 invoked while multiple threads active within it.
ARJUNA012107: CheckedAction::check - atomic action 0:ffffc0a80065:f2db:5ef4e1c7:0 commiting with 2 threads active!
似乎是应该避免的事情。
我试过
@Transaction(value = TxType.REQUIRES_NEW)
没用。我尝试在
longRunning
上使用 API Approach 而不是@Transactional
方法,如下 guide 中所述:
@Inject UserTransaction transaction;
.
.
.
try {
transaction.begin();
jobsRecord.setStatus("Complete");
jobsRecord.setCompletedOn(new Timestamp(System.currentTimeMillis()));
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
但随后我收到错误:ARJUNA016051: thread is already associated with a transaction!
和 ARJUNA016079: Transaction rollback status is:ActionStatus.COMMITTED
这次我在启用 context propagation 的情况下再次尝试了声明式和基于 API 的方法。但是还是不行。
最后,基于第三种方法,我认为将
@Transactional
保留在 Http 请求处理程序上,并在没有声明或基于 API 的情况下保留longRunning
交易方法会起作用。但是数据库仍然没有更新。
显然我误解了 JTA 和上下文传播的工作原理(以及其他)。
有没有一种方法(甚至是一种设计模式)允许我在 quarkus Web 应用程序中异步更新数据库实体?还有为什么我采取的任何方法都没有任何效果?
使用 quarkus 1.4.1.Final 与 ext: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, kubernetes-client, mutiny, narayana-jta, rest-客户端、resteasy、resteasy-jackson、resteasy-mutiny、smallrye-context-propagation、smallrye-health、smallrye-openapi、swagger-ui]
您应该 return 来自 JAX-RS 资源方法的异步类型,事务上下文将在异步阶段执行时可用。 quarkus guide on context propagation.
中有一些相关文档我将从查看 getting started quickstart 等反应性示例之一开始。尝试使用 @Transactional 注释每个资源端点,异步代码将 运行 使用事务上下文。