Fix messages in ACM 00/136200/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Mon, 16 Oct 2023 11:57:37 +0000 (12:57 +0100)
committerFrancesco Fiora <francesco.fiora@est.tech>
Mon, 16 Oct 2023 15:08:36 +0000 (15:08 +0000)
Fix TIMEOUT support in MIGRATING.
Avoid conflicts updating AC instance Element instead
of a full AC instance.
Using ExecutorService to send messages to the participant,
the transaction will completed before the message is sent.

Issue-ID: POLICY-4811
Change-Id: I2730ae694c8a5c9edfe500b1fa93cfb3787f32c5
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ProviderUtils.java
models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java

index 7fed8a7..ace246c 100755 (executable)
@@ -95,10 +95,11 @@ public class AcInstanceStateResolver {
 
         // timeout
         this.graph.put(new String[] {DEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, DEPLOY);
-        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY);
-        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UPDATING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY);
-
         this.graph.put(new String[] {DEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, DEPLOY);
+
+        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY);
+        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UPDATING, LOCKED, TIMEOUT}, UNDEPLOY);
+        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, MIGRATING, LOCKED, TIMEOUT}, UNDEPLOY);
         this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY);
 
         this.graph.put(new String[] {DELETE, LOCK_NONE, DELETING, LOCK_NONE, TIMEOUT}, DELETE);
index 6ff8d84..6b90619 100755 (executable)
@@ -31,6 +31,7 @@ import java.util.UUID;
 import lombok.AllArgsConstructor;
 import lombok.NonNull;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
@@ -43,6 +44,7 @@ import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.springframework.data.domain.Example;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -77,7 +79,7 @@ public class AutomationCompositionProvider {
      * @param instanceId the ID of the automation composition to get
      * @return the automation composition found
      */
-    @Transactional(readOnly = true)
+    @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
     public Optional<AutomationComposition> findAutomationComposition(final UUID instanceId) {
         var result = automationCompositionRepository.findById(instanceId.toString());
         return result.stream().map(JpaAutomationComposition::toAuthorative).findFirst();
@@ -209,4 +211,18 @@ public class AutomationCompositionProvider {
         }
         acElementRepository.saveAll(jpaList);
     }
+
+    /**
+     * Update AutomationCompositionElement.
+     *
+     * @param element the AutomationCompositionElement
+     * @param instanceId the instance Id
+     */
+    public void updateAutomationCompositionElement(@NonNull final AutomationCompositionElement element,
+                @NonNull final UUID instanceId) {
+        var jpaAcElement = new JpaAutomationCompositionElement(element.getId().toString(), instanceId.toString());
+        jpaAcElement.fromAuthorative(element);
+        ProviderUtils.validate(element, jpaAcElement, "AutomationCompositionElement");
+        acElementRepository.save(jpaAcElement);
+    }
 }
index 6ba6ac0..6feb2b7 100755 (executable)
@@ -72,17 +72,28 @@ public final class ProviderUtils {
      */
     public static <A, J extends Validated & PfAuthorative<A>> J getJpaAndValidate(A authorativeConcept,
             Supplier<J> jpaSupplier, String conceptDescription) {
-        var validationResult = new BeanValidationResult(conceptDescription, authorativeConcept);
-
         var jpaConcept = jpaSupplier.get();
         jpaConcept.fromAuthorative(authorativeConcept);
+        validate(authorativeConcept, jpaConcept, conceptDescription);
+        return jpaConcept;
+    }
+
+    /**
+     * Validate a Jpa object.
+     *
+     * @param authorativeConcept the concept
+     * @param jpaConcept  the Jpa of the concept
+     * @param conceptDescription the description used for validation result
+     */
+    public static <A, J extends Validated & PfAuthorative<A>> void validate(A authorativeConcept,
+            J jpaConcept, String conceptDescription) {
+        var validationResult = new BeanValidationResult(conceptDescription, authorativeConcept);
 
         validationResult.addResult(jpaConcept.validate(conceptDescription));
 
         if (!validationResult.isValid()) {
             throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult());
         }
-        return jpaConcept;
     }
 
     /**
index c3d8fc4..0fd7ab9 100755 (executable)
@@ -381,6 +381,7 @@ public final class AcmUtils {
         for (var element : automationComposition.getElements().values()) {
             element.setDeployState(deployState);
             element.setLockState(lockState);
+            element.setMessage(null);
         }
     }
 
index 0991c1b..e7ceab8 100644 (file)
@@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.List;
@@ -44,7 +45,8 @@ import org.springframework.data.domain.Example;
 
 class AutomationCompositionProviderTest {
 
-    private static final String OBJECT_IS_NULL = "automationComposition is marked non-null but is null";
+    private static final String AC_IS_NULL = "automationComposition is marked non-null but is null";
+    private static final String ACELEMENT_IS_NULL = "element is marked non-null but is null";
 
     private static final Coder CODER = new StandardCoder();
     private static final String AUTOMATION_COMPOSITION_JSON =
@@ -84,7 +86,7 @@ class AutomationCompositionProviderTest {
                 mock(AutomationCompositionElementRepository.class));
 
         assertThatThrownBy(() -> automationCompositionProvider.updateAutomationComposition(null))
-                .hasMessageMatching(OBJECT_IS_NULL);
+                .hasMessageMatching(AC_IS_NULL);
 
         when(automationCompositionRepository.save(inputAutomationCompositionsJpa.get(0)))
                 .thenReturn(inputAutomationCompositionsJpa.get(0));
@@ -185,4 +187,19 @@ class AutomationCompositionProviderTest {
                 automationCompositionProvider.deleteAutomationComposition(automationComposition.getInstanceId());
         assertEquals(automationComposition, deletedAc);
     }
+
+    @Test
+    void testAutomationCompositionElementUpdate() {
+        var acElementRepository = mock(AutomationCompositionElementRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(
+            mock(AutomationCompositionRepository.class), acElementRepository);
+
+        assertThatThrownBy(() -> automationCompositionProvider.updateAutomationCompositionElement(null, null))
+            .hasMessageMatching(ACELEMENT_IS_NULL);
+
+        var acElement = inputAutomationCompositions.getAutomationCompositionList().get(0).getElements().values()
+            .iterator().next();
+        automationCompositionProvider.updateAutomationCompositionElement(acElement, UUID.randomUUID());
+        verify(acElementRepository).save(any());
+    }
 }
index 02fce55..79fef3d 100755 (executable)
@@ -267,6 +267,7 @@ public class AutomationCompositionHandler {
      */
     private void handleUndeployState(UUID messageId, final AutomationComposition automationComposition,
             Integer startPhaseMsg) {
+        automationComposition.setCompositionTargetId(null);
         for (var acElement : automationComposition.getElements().values()) {
             int startPhase = ParticipantUtils.findStartPhase(
                     cacheProvider.getCommonProperties(automationComposition.getInstanceId(), acElement.getId()));
index e2e93da..927eaa6 100755 (executable)
@@ -123,7 +123,8 @@ public class AutomationCompositionOutHandler {
         var checkOpt = automationComposition.getElements().values().stream()
                 .filter(acElement -> !deployState.equals(acElement.getDeployState())).findAny();
         if (checkOpt.isEmpty()) {
-            if (DeployState.MIGRATING.equals(automationComposition.getDeployState())) {
+            if (DeployState.DEPLOYED.equals(automationComposition.getDeployState())
+                    && automationComposition.getCompositionTargetId() != null) {
                 // migration scenario
                 automationComposition.setCompositionId(automationComposition.getCompositionTargetId());
                 automationComposition.setCompositionTargetId(null);
index cbd236e..a04f907 100755 (executable)
@@ -231,7 +231,7 @@ class AutomationCompositionOutHandlerTest {
 
         var compositionTarget = UUID.randomUUID();
         automationComposition.setCompositionTargetId(compositionTarget);
-        automationComposition.setDeployState(DeployState.MIGRATING);
+        automationComposition.setDeployState(DeployState.DEPLOYED);
         when(cacheProvider.getAcElementsDefinitions()).thenReturn(Map.of(compositionTarget, Map.of()));
 
         for (var element : automationComposition.getElements().values()) {
index dbed7f7..d7a00f2 100755 (executable)
@@ -25,6 +25,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import lombok.AllArgsConstructor;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AcElementPropertiesPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher;
@@ -62,6 +64,8 @@ public class SupervisionAcHandler {
     private final AcElementPropertiesPublisher acElementPropertiesPublisher;
     private final AutomationCompositionMigrationPublisher acCompositionMigrationPublisher;
 
+    private final ExecutorService executor = Executors.newFixedThreadPool(1);
+
     /**
      * Handle Deploy an AutomationComposition instance.
      *
@@ -74,6 +78,7 @@ public class SupervisionAcHandler {
             for (var element : automationComposition.getElements().values()) {
                 if (!DeployState.DEPLOYED.equals(element.getDeployState())) {
                     element.setDeployState(DeployState.DEPLOYING);
+                    element.setMessage(null);
                 }
             }
         } else {
@@ -82,8 +87,9 @@ public class SupervisionAcHandler {
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
         automationCompositionProvider.updateAutomationComposition(automationComposition);
         var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate());
-        automationCompositionDeployPublisher.send(automationComposition, acDefinition.getServiceTemplate(), startPhase,
-                true);
+        executor.execute(
+            () -> automationCompositionDeployPublisher.send(automationComposition, acDefinition.getServiceTemplate(),
+                startPhase, true));
     }
 
     /**
@@ -104,9 +110,11 @@ public class SupervisionAcHandler {
             AcmUtils.setCascadedState(automationComposition, DeployState.UNDEPLOYING, LockState.NONE);
         }
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
+        automationComposition.setCompositionTargetId(null);
         automationCompositionProvider.updateAutomationComposition(automationComposition);
         var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate());
-        automationCompositionStateChangePublisher.send(automationComposition, startPhase, true);
+        executor.execute(
+            () -> automationCompositionStateChangePublisher.send(automationComposition, startPhase, true));
     }
 
     /**
@@ -129,7 +137,8 @@ public class SupervisionAcHandler {
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
         automationCompositionProvider.updateAutomationComposition(automationComposition);
         var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate());
-        automationCompositionStateChangePublisher.send(automationComposition, startPhase, true);
+        executor.execute(
+            () -> automationCompositionStateChangePublisher.send(automationComposition, startPhase, true));
     }
 
     /**
@@ -152,7 +161,8 @@ public class SupervisionAcHandler {
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
         automationCompositionProvider.updateAutomationComposition(automationComposition);
         var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate());
-        automationCompositionStateChangePublisher.send(automationComposition, startPhase, true);
+        executor.execute(
+            () -> automationCompositionStateChangePublisher.send(automationComposition, startPhase, true));
     }
 
     /**
@@ -163,7 +173,8 @@ public class SupervisionAcHandler {
     public void update(AutomationComposition automationComposition) {
         AcmUtils.setCascadedState(automationComposition, DeployState.UPDATING, automationComposition.getLockState());
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
-        acElementPropertiesPublisher.send(automationComposition);
+        executor.execute(
+            () -> acElementPropertiesPublisher.send(automationComposition));
     }
 
     /**
@@ -177,7 +188,8 @@ public class SupervisionAcHandler {
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
         automationCompositionProvider.updateAutomationComposition(automationComposition);
         var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate());
-        automationCompositionStateChangePublisher.send(automationComposition, startPhase, true);
+        executor.execute(
+            () -> automationCompositionStateChangePublisher.send(automationComposition, startPhase, true));
     }
 
     /**
@@ -227,9 +239,10 @@ public class SupervisionAcHandler {
                 for (var element : automationComposition.getElements().values()) {
                     if (element.getParticipantId().equals(automationCompositionAckMessage.getParticipantId())) {
                         element.setDeployState(DeployState.DELETED);
+                        automationCompositionProvider.updateAutomationCompositionElement(element,
+                            automationComposition.getInstanceId());
                     }
                 }
-                automationCompositionProvider.updateAutomationComposition(automationComposition);
             } else {
                 LOGGER.warn("Empty AutomationCompositionResultMap  {} {}",
                         automationCompositionAckMessage.getAutomationCompositionId(),
@@ -251,8 +264,9 @@ public class SupervisionAcHandler {
             StateChangeResult stateChangeResult) {
         var updated = false;
         boolean inProgress = !StateChangeResult.FAILED.equals(automationComposition.getStateChangeResult());
-        if (inProgress) {
+        if (inProgress && !stateChangeResult.equals(automationComposition.getStateChangeResult())) {
             automationComposition.setStateChangeResult(stateChangeResult);
+            updated = true;
         }
 
         for (var acElementAck : automationCompositionResultSet) {
@@ -265,7 +279,8 @@ public class SupervisionAcHandler {
                 element.setDeployState(acElementAck.getValue().getDeployState());
                 element.setLockState(acElementAck.getValue().getLockState());
                 element.setRestarting(null);
-                updated = true;
+                automationCompositionProvider.updateAutomationCompositionElement(element,
+                    automationComposition.getInstanceId());
             }
         }
 
@@ -274,6 +289,7 @@ public class SupervisionAcHandler {
                     .map(AutomationCompositionElement::getRestarting).filter(Objects::nonNull).findAny();
             if (restarting.isEmpty()) {
                 automationComposition.setRestarting(null);
+                updated = true;
             }
         }
 
@@ -289,6 +305,7 @@ public class SupervisionAcHandler {
     public void migrate(AutomationComposition automationComposition, UUID compositionTargetId) {
         AcmUtils.setCascadedState(automationComposition, DeployState.MIGRATING, LockState.LOCKED);
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
-        acCompositionMigrationPublisher.send(automationComposition, compositionTargetId);
+        executor.execute(
+            () -> acCompositionMigrationPublisher.send(automationComposition, compositionTargetId));
     }
 }
index d3f8598..f39970f 100755 (executable)
@@ -24,6 +24,8 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML;
@@ -41,6 +43,7 @@ import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
 import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
@@ -70,7 +73,8 @@ class SupervisionAcHandlerTest {
                         automationComposition, DeployState.DEPLOYED, LockState.UNLOCKED);
         handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage);
 
-        verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
+        verify(automationCompositionProvider, times(3))
+            .updateAutomationCompositionElement(any(AutomationCompositionElement.class), any());
     }
 
     private AutomationCompositionDeployAck getAutomationCompositionDeployAck(ParticipantMessageType messageType,
@@ -83,6 +87,7 @@ class SupervisionAcHandlerTest {
         }
         automationCompositionAckMessage.setAutomationCompositionId(automationComposition.getInstanceId());
         automationCompositionAckMessage.setParticipantId(CommonTestData.getParticipantId());
+        automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR);
         return automationCompositionAckMessage;
     }
 
@@ -121,6 +126,7 @@ class SupervisionAcHandlerTest {
 
         var automationCompositionAckMessage =
                 new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_DEPLOY_ACK);
+        automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR);
         for (var element : automationComposition.getElements().values()) {
             element.setDeployState(DeployState.DEPLOYED);
         }
@@ -142,7 +148,8 @@ class SupervisionAcHandlerTest {
 
         handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage);
 
-        verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
+        verify(automationCompositionProvider)
+            .updateAutomationCompositionElement(any(AutomationCompositionElement.class), any());
     }
 
     @Test
@@ -159,8 +166,8 @@ class SupervisionAcHandlerTest {
         automationComposition.setStateChangeResult(StateChangeResult.FAILED);
         handler.deploy(automationComposition, acDefinition);
         verify(automationCompositionProvider).updateAutomationComposition(automationComposition);
-        verify(automationCompositionDeployPublisher).send(automationComposition, acDefinition.getServiceTemplate(), 0,
-                true);
+        verify(automationCompositionDeployPublisher, timeout(1000))
+            .send(automationComposition, acDefinition.getServiceTemplate(), 0, true);
     }
 
     @Test
@@ -177,7 +184,7 @@ class SupervisionAcHandlerTest {
         handler.undeploy(automationComposition, acDefinition);
 
         verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -197,7 +204,7 @@ class SupervisionAcHandlerTest {
                 .forEach(element -> element.setDeployState(DeployState.UNDEPLOYING));
         handler.undeploy(automationComposition, acDefinition);
         verify(automationCompositionProvider).updateAutomationComposition(automationComposition);
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -214,7 +221,7 @@ class SupervisionAcHandlerTest {
         handler.unlock(automationComposition, acDefinition);
 
         verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -233,7 +240,7 @@ class SupervisionAcHandlerTest {
         handler.unlock(automationComposition, acDefinition);
 
         verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -250,7 +257,7 @@ class SupervisionAcHandlerTest {
         handler.lock(automationComposition, acDefinition);
 
         verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -269,7 +276,7 @@ class SupervisionAcHandlerTest {
         handler.lock(automationComposition, acDefinition);
 
         verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
-        verify(acStateChangePublisher).send(any(AutomationComposition.class), anyInt(), anyBoolean());
+        verify(acStateChangePublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt(), anyBoolean());
     }
 
     @Test
@@ -293,7 +300,8 @@ class SupervisionAcHandlerTest {
 
         handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage);
 
-        verify(automationCompositionProvider).updateAutomationComposition(any(AutomationComposition.class));
+        verify(automationCompositionProvider)
+            .updateAutomationCompositionElement(any(AutomationCompositionElement.class), any());
     }
 
     @Test
@@ -305,7 +313,7 @@ class SupervisionAcHandlerTest {
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Lock");
         handler.update(automationComposition);
-        verify(acElementPropertiesPublisher).send(any(AutomationComposition.class));
+        verify(acElementPropertiesPublisher, timeout(1000)).send(any(AutomationComposition.class));
     }
 
     @Test
@@ -317,6 +325,6 @@ class SupervisionAcHandlerTest {
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate");
         handler.migrate(automationComposition, UUID.randomUUID());
-        verify(acCompositionMigrationPublisher).send(any(AutomationComposition.class), any());
+        verify(acCompositionMigrationPublisher, timeout(1000)).send(any(AutomationComposition.class), any());
     }
 }