Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize local storing of Tx #1569

Open
wants to merge 15 commits into
base: hotfix-1.10.x
Choose a base branch
from
6 changes: 6 additions & 0 deletions LTS-CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ include::content/docs/variables.adoc-include[]
The LTS changelog lists releases which are only accessible via a commercial subscription.
All fixes and changes in LTS releases will be released the next minor release. Changes from LTS 1.4.x will be included in release 1.5.0.


[[v1.10.24]]
== 1.10.24 (TBD)

icon:check[] Core: The work with the database transactions has been modified to be proof against race conditions in asynchronous runs.

[[v1.10.23]]
== 1.10.23 (20.12.2023)

Expand Down
22 changes: 18 additions & 4 deletions mdm/api/src/main/java/com/gentics/mesh/core/db/Tx.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gentics.mesh.core.db;

import java.util.Optional;
import java.util.function.Function;

import com.gentics.mesh.cache.CacheCollection;
import com.gentics.mesh.context.InternalActionContext;
Expand All @@ -12,6 +13,9 @@
import com.gentics.mesh.event.EventQueueBatch;
import com.gentics.mesh.security.SecurityUtils;

import io.vertx.reactivex.core.Context;
import io.vertx.reactivex.core.Vertx;

/**
* A {@link Tx} is an interface for autoclosable transactions.
*/
Expand All @@ -23,22 +27,32 @@ public interface Tx extends BaseTransaction, DaoCollection, CacheCollection, Sec
static ThreadLocal<Tx> threadLocalGraph = new ThreadLocal<>();

/**
* Set the nested active transaction for the current thread.
* Set the nested active transaction for the current Vert.x context, or thread.
*
* @param tx
* Transaction
*/
static void setActive(Tx tx) {
Tx.threadLocalGraph.set(tx);
Optional.ofNullable(Vertx.currentContext())
.ifPresentOrElse(
ctx -> ctx.putLocal("tx", Optional.ofNullable(tx)),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual change. There are get() and getLocal() in the Vert.x Context, which seem to be functionally equal, but getLocal() has internal usages.

() -> Tx.threadLocalGraph.set(tx)
);
}

/**
* Return the current active transaction. A transaction should be the only place where this threadlocal is updated.
* Return the current active transaction. A transaction should be the only place where this context/threadlocal is updated.
*
* @return Currently active transaction
*/
static Tx get() {
return Tx.threadLocalGraph.get();
Optional<Context> maybeVertxContext = Optional.ofNullable(Vertx.currentContext());
if (maybeVertxContext.isPresent()) {
Context vertxContext = maybeVertxContext.get();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't mix the cases where we have an empty Context, and where we have no Context at all.

return Optional.ofNullable(vertxContext.<Optional<Tx>>getLocal("tx")).flatMap(Function.identity()).orElse(null);
} else {
return Tx.threadLocalGraph.get();
}
}

/**
Expand Down