Skip to content

Commit

Permalink
Allow setting transaction timeout from a config property
Browse files Browse the repository at this point in the history
Resolves: quarkusio#15752
  • Loading branch information
geoand committed Mar 18, 2021
1 parent 9f5aa94 commit 892bebd
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,19 @@
* @return The transaction timeout in seconds.
*/
int timeout() default UNSET_TIMEOUT;

String UNSET_TIMEOUT_CONFIG_PROPERTY = "<<unset>>";

/**
* The configuration property to use in order to determine the value of the timeout in seconds.
* If the property exists, it must be an integer value representing the transaction timeout in seconds.
*
* An example configuration in {@code application.properties} could be: {@code my-transaction.timeout=5}.
*
* If both {@code timeoutFromConfigProperty} and {@code timeout} are set, then Quarkus will attempt to resolve
* {@code timeoutFromConfigProperty} and if a value for it has been provided, the timeout is set to that value.
* If no value has been provided at runtime for the property, then the value of {@code timeout} will be used
* as the fallback.
*/
String timeoutFromConfigProperty() default UNSET_TIMEOUT_CONFIG_PROPERTY;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import javax.transaction.TransactionManager;
import javax.transaction.Transactional;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;
import org.jboss.tm.usertx.client.ServerVMClientUserTransaction;
import org.reactivestreams.Publisher;

Expand All @@ -34,6 +36,7 @@
public abstract class TransactionalInterceptorBase implements Serializable {

private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(TransactionalInterceptorBase.class);

@Inject
TransactionManager transactionManager;
Expand Down Expand Up @@ -106,16 +109,33 @@ protected Object invokeInOurTx(InvocationContext ic, TransactionManager tm, Runn

TransactionConfiguration configAnnotation = getTransactionConfiguration(ic);
int currentTmTimeout = ((CDIDelegatingTransactionManager) transactionManager).getTransactionTimeout();
if (configAnnotation != null && configAnnotation.timeout() != TransactionConfiguration.UNSET_TIMEOUT) {
tm.setTransactionTimeout(configAnnotation.timeout());
boolean restoreTimeout = false;
if (configAnnotation != null) {
Integer newTimeout = null;
if (!configAnnotation.timeoutFromConfigProperty().equals(TransactionConfiguration.UNSET_TIMEOUT_CONFIG_PROPERTY)) {
Optional<Integer> configTimeout = ConfigProvider.getConfig()
.getOptionalValue(configAnnotation.timeoutFromConfigProperty(), Integer.class);
if (configTimeout.isPresent()) {
newTimeout = configTimeout.get();
} else if (log.isDebugEnabled()) {
log.debug("Configuration property '" + configAnnotation.timeoutFromConfigProperty()
+ "' was not provided, so it will not affect the transaction's timeout.");
}
}
if ((newTimeout == null) && (configAnnotation.timeout() != TransactionConfiguration.UNSET_TIMEOUT)) {
newTimeout = configAnnotation.timeout();
}
if (newTimeout != null) {
tm.setTransactionTimeout(newTimeout);
restoreTimeout = true;
}
}
Transaction tx;
try {
tm.begin();
tx = tm.getTransaction();
} finally {
if (configAnnotation != null && configAnnotation.timeout() != TransactionConfiguration.UNSET_TIMEOUT) {
//restore the default behaviour
if (restoreTimeout) {
tm.setTransactionTimeout(currentTmTimeout);
}
}
Expand Down Expand Up @@ -263,7 +283,9 @@ protected Object invokeInNoTx(InvocationContext ic) throws Exception {

private void checkConfiguration(InvocationContext ic) {
TransactionConfiguration configAnnotation = getTransactionConfiguration(ic);
if (configAnnotation != null && configAnnotation.timeout() != TransactionConfiguration.UNSET_TIMEOUT) {
if (configAnnotation != null && ((configAnnotation.timeout() != TransactionConfiguration.UNSET_TIMEOUT)
|| !TransactionConfiguration.UNSET_TIMEOUT_CONFIG_PROPERTY
.equals(configAnnotation.timeoutFromConfigProperty()))) {
throw new RuntimeException("Changing timeout via @TransactionConfiguration can only be done " +
"at the entry level of a transaction");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;

import io.quarkus.narayana.jta.runtime.TransactionConfiguration;
import io.quarkus.runtime.StartupEvent;

@WebServlet(urlPatterns = "/jpa-h2/testproxy")
Expand All @@ -23,6 +24,7 @@ public class ProxyTestEndpoint extends HttpServlet {
EntityManager entityManager;

@Transactional
@TransactionConfiguration(timeoutFromConfigProperty = "dummy.transaction.timeout")
public void setup(@Observes StartupEvent startupEvent) {
Pet pet = new Pet();
pet.setId(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
quarkus.datasource.jdbc.max-size=8
dummy.transaction.timeout=30

0 comments on commit 892bebd

Please sign in to comment.