This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3799
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 5c2764a9bd741f219f7b8224ffae59c8ea272ada
Author: Dan Haywood <[email protected]>
AuthorDate: Fri Jun 28 14:41:14 2024 +0100

    CAUSEWAY-3799: reduces duplicate logging in CausewayInteraction if a 
deadlock has been hit
---
 .../interaction/session/CausewayInteraction.java   | 51 ++++++++++++----------
 .../metamodel/execution/InteractionInternal.java   | 23 +++++-----
 .../executor/MemberExecutorServiceDefault.java     |  9 ++--
 3 files changed, 47 insertions(+), 36 deletions(-)

diff --git 
a/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
 
b/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
index 8d23f8ce17..614a4d9b73 100644
--- 
a/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
+++ 
b/core/interaction/src/main/java/org/apache/causeway/core/interaction/session/CausewayInteraction.java
@@ -36,7 +36,6 @@ import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.commons.internal.collections._Lists;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.execution.InteractionInternal;
-import org.apache.causeway.core.metamodel.services.publishing.CommandPublisher;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -51,7 +50,9 @@ implements InteractionInternal {
     public CausewayInteraction(final @NonNull UUID interactionId) {
         this.startedAtSystemNanos = System.nanoTime(); // used to measure time 
periods, so not using ClockService here
         this.command = new Command(interactionId);
-        log.debug("new CausewayInteraction id={}", interactionId);
+        if(log.isDebugEnabled()) {
+            log.debug("new CausewayInteraction id={}", interactionId);
+        }
     }
 
     @Getter(onMethod_ = {@Override})
@@ -98,16 +99,14 @@ implements InteractionInternal {
     public Object execute(
             final MemberExecutor<ActionInvocation> memberExecutor,
             final ActionInvocation actionInvocation,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final CommandPublisher commandPublisher) {
+            final Context context) {
 
         push(actionInvocation);
-        start(actionInvocation, clockService, metricsService, 
commandPublisher);
+        start(actionInvocation, context);
         try {
-            return executeInternal(memberExecutor, actionInvocation);
+            return executeInternal(memberExecutor, actionInvocation, context);
         } finally {
-            popAndComplete(clockService, metricsService);
+            popAndComplete(context.getClockService(), 
context.getMetricsService());
         }
     }
 
@@ -115,21 +114,21 @@ implements InteractionInternal {
     public Object execute(
             final MemberExecutor<PropertyEdit> memberExecutor,
             final PropertyEdit propertyEdit,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final CommandPublisher commandPublisher,
-            final Command command) {
+            final Context context) {
 
         push(propertyEdit);
-        start(propertyEdit, clockService, metricsService, commandPublisher);
+        start(propertyEdit, context);
         try {
-            return executeInternal(memberExecutor, propertyEdit);
+            return executeInternal(memberExecutor, propertyEdit, context);
         } finally {
-            popAndComplete(clockService, metricsService);
+            popAndComplete(context.getClockService(), 
context.getMetricsService());
         }
     }
 
-    private <T extends Execution<?,?>> Object executeInternal(final 
MemberExecutor<T> memberExecutor, final T execution) {
+    private <T extends Execution<?,?>> Object executeInternal(
+            final MemberExecutor<T> memberExecutor,
+            final T execution,
+            final Context context) {
 
         try {
             Object result = memberExecutor.execute(execution);
@@ -142,7 +141,17 @@ implements InteractionInternal {
             // examples are IllegalArgument- or NullPointer- exceptions being 
swallowed when using the
             // WrapperFactory utilizing async calls
 
-            log.error("failed to execute an interaction", 
_Exceptions.getRootCause(ex).orElse(null));
+            if(context.getDeadlockRecognizer().isDeadlock(ex)) {
+                if(log.isDebugEnabled()) {
+                    log.debug("failed to execute an interaction due to a 
deadlock", ex);
+                } else if(log.isInfoEnabled()) {
+                    log.info("failed to execute an interaction due to a 
deadlock");
+                }
+            } else {
+                if(log.isErrorEnabled()) {
+                    log.error("failed to execute an interaction", 
_Exceptions.getRootCause(ex).orElse(null));
+                }
+            }
 
             // just because an exception has thrown, does not mean it is that 
significant;
             // it could be that it is recognized by an ExceptionRecognizer and 
is not severe
@@ -183,18 +192,16 @@ implements InteractionInternal {
 
     private void start(
             final Execution<?,?> execution,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final CommandPublisher commandPublisher) {
+            final Context context) {
         // set the startedAt (and update command if this is the top-most 
member execution)
         // (this isn't done within Interaction#execute(...) because it 
requires the DTO
         // to have been set on the current execution).
-        val startedAt = execution.start(clockService, metricsService);
+        val startedAt = execution.start(context.getClockService(), 
context.getMetricsService());
         if(getCommand().getStartedAt() == null) {
             getCommand().updater().setStartedAt(startedAt);
             
getCommand().updater().setPublishingPhase(Command.CommandPublishingPhase.STARTED);
         }
-        commandPublisher.start(getCommand());
+        context.getCommandPublisher().start(getCommand());
     }
 
     /**
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/InteractionInternal.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/InteractionInternal.java
index 500421f62f..4638e3c09f 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/InteractionInternal.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/InteractionInternal.java
@@ -22,16 +22,17 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.LongAdder;
 
 import org.apache.causeway.applib.services.clock.ClockService;
-import org.apache.causeway.applib.services.command.Command;
 import org.apache.causeway.applib.services.iactn.ActionInvocation;
 import org.apache.causeway.applib.services.iactn.Execution;
 import org.apache.causeway.applib.services.iactn.Interaction;
 import org.apache.causeway.applib.services.iactn.PropertyEdit;
 import org.apache.causeway.applib.services.metrics.MetricsService;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
+import org.apache.causeway.core.metamodel.services.deadlock.DeadlockRecognizer;
 import org.apache.causeway.core.metamodel.services.publishing.CommandPublisher;
 
 import lombok.NonNull;
+import lombok.Value;
 import lombok.val;
 
 /**
@@ -44,13 +45,18 @@ extends Interaction {
      * (Modeled after {@link Callable}), is the implementation
      * by which the framework actually performs the interaction.
      */
-    public interface MemberExecutor<T extends Execution<?,?>> {
+    interface MemberExecutor<T extends Execution<?,?>> {
         Object execute(final T currentExecution);
     }
 
-    static class Context {
-
+    @Value(staticConstructor = "of")
+    class Context {
+        ClockService clockService;
+        MetricsService metricsService;
+        CommandPublisher commandPublisher;
+        DeadlockRecognizer deadlockRecognizer;
     }
+
     /**
      * Use the provided {@link MemberExecutor} to invoke an action, with the 
provided
      * {@link ActionInvocation} capturing
@@ -63,9 +69,7 @@ extends Interaction {
     Object execute(
             final MemberExecutor<ActionInvocation> memberExecutor,
             final ActionInvocation actionInvocation,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final CommandPublisher commandPublisher);
+            final Context context);
 
     /**
      * Use the provided {@link MemberExecutor} to edit a property, with the 
provided
@@ -79,10 +83,7 @@ extends Interaction {
     Object execute(
             final MemberExecutor<PropertyEdit> memberExecutor,
             final PropertyEdit propertyEdit,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final CommandPublisher commandPublisher,
-            final Command command);
+            final Context context);
 
 
     /**
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java
index 761d5b1976..b76e164fb2 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java
@@ -25,6 +25,8 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Provider;
 
+import org.apache.causeway.core.metamodel.services.deadlock.DeadlockRecognizer;
+
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
@@ -96,6 +98,7 @@ implements MemberExecutorService {
     private final @Getter CausewayConfiguration configuration;
     private final @Getter ObjectManager objectManager;
     private final @Getter ClockService clockService;
+    private final @Getter DeadlockRecognizer deadlockRecognizer;
     private final @Getter ServiceInjector serviceInjector;
     private final @Getter Provider<MetricsService> metricsServiceProvider;
     private final @Getter InteractionDtoFactory interactionDtoFactory;
@@ -169,7 +172,7 @@ implements MemberExecutorService {
                         interaction, actionId, targetPojo, argumentPojos);
 
         // sets up startedAt and completedAt on the execution, also manages 
the execution call graph
-        interaction.execute(actionExecutor, actionInvocation, clockService, 
metricsService(), commandPublisherProvider.get());
+        interaction.execute(actionExecutor, actionInvocation, 
InteractionInternal.Context.of(clockService, metricsService(), 
commandPublisherProvider.get(), deadlockRecognizer));
 
         // handle any exceptions
         val priorExecution = 
interaction.getPriorExecutionOrThrowIfAnyException(actionInvocation);
@@ -266,8 +269,8 @@ implements MemberExecutorService {
         val propertyEdit = new PropertyEdit(interaction, propertyId, target, 
argValuePojo);
 
         // sets up startedAt and completedAt on the execution, also manages 
the execution call graph
-        val targetPojo = interaction.execute(propertyModifier, propertyEdit, 
clockService, metricsService(),
-                commandPublisherProvider.get(), command);
+        val targetPojo = interaction.execute(propertyModifier, propertyEdit,
+                InteractionInternal.Context.of(clockService, metricsService(), 
commandPublisherProvider.get(), deadlockRecognizer));
 
         // handle any exceptions
         final Execution<?, ?> priorExecution = interaction.getPriorExecution();

Reply via email to