Performance optimizations for Multi-Assignments (#858)
* Add remote event test for the new MultiActionEvent * Improve test descriptions * Improve sendMultiActionRequestMessages * Moved action filtering to the database query level (#12) * Use @ExpectedEvents instead of EventHandlerStubs * Removed @Param from 'existsByTargetControllerIdAndStatusAndActiveIsTrue' * Reverted metadata initialization * Fix hawkBit bot findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>
This commit is contained in:
@@ -127,6 +127,20 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
@Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaAction a JOIN a.target t WHERE t.controllerId=:controllerId AND a.active=1")
|
||||
boolean activeActionExistsForControllerId(@Param("controllerId") String controllerId);
|
||||
|
||||
/**
|
||||
* Check if any active actions with given action status and given controller
|
||||
* ID exist.
|
||||
*
|
||||
* @param controllerId
|
||||
* of the target to check for actions
|
||||
* @param currentStatus
|
||||
* of the active action to look for
|
||||
*
|
||||
* @return <code>true</code> if one or more active actions for the given
|
||||
* controllerId and action status are found
|
||||
*/
|
||||
boolean existsByTargetControllerIdAndStatusAndActiveIsTrue(String controllerId, Action.Status currentStatus);
|
||||
|
||||
/**
|
||||
* Retrieves latest {@link Action} for given target and
|
||||
* {@link SoftwareModule}.
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -39,8 +37,6 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||
import org.springframework.cloud.bus.BusProperties;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -51,8 +47,6 @@ import com.google.common.collect.Lists;
|
||||
*/
|
||||
public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
|
||||
private static final Pageable ACTION_PAGE_REQUEST = PageRequest.of(0, MAX_ACTION_COUNT);
|
||||
|
||||
private final Supplier<Boolean> multiAssignmentsConfig;
|
||||
|
||||
OnlineDsAssignmentStrategy(final TargetRepository targetRepository,
|
||||
@@ -196,8 +190,8 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
}
|
||||
|
||||
private boolean hasPendingCancellations(final Target target) {
|
||||
return actionRepository.findByActiveAndTarget(ACTION_PAGE_REQUEST, target.getControllerId(), true).getContent()
|
||||
.stream().anyMatch(action -> action.getStatus() == Status.CANCELING);
|
||||
return actionRepository.existsByTargetControllerIdAndStatusAndActiveIsTrue(target.getControllerId(),
|
||||
Status.CANCELING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,13 +79,15 @@ public abstract class AbstractRemoteEventTest extends AbstractJpaIntegrationTest
|
||||
return busProtoStuffMessageConverter.toMessage(event, new MessageHeaders(headers));
|
||||
}
|
||||
|
||||
protected TenantAwareEvent createJacksonEvent(final TenantAwareEvent event) {
|
||||
final Message<?> message = createJsonMessage(event);
|
||||
return (TenantAwareEvent) jacksonMessageConverter.fromMessage(message, event.getClass());
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends TenantAwareEvent> T createJacksonEvent(final T event) {
|
||||
final Message<String> message = createJsonMessage(event);
|
||||
return (T) jacksonMessageConverter.fromMessage(message, event.getClass());
|
||||
}
|
||||
|
||||
protected TenantAwareEvent createProtoStuffEvent(final TenantAwareEvent event) {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends TenantAwareEvent> T createProtoStuffEvent(final T event) {
|
||||
final Message<?> message = createProtoStuffMessage(event);
|
||||
return (TenantAwareEvent) busProtoStuffMessageConverter.fromMessage(message, event.getClass());
|
||||
return (T) busProtoStuffMessageConverter.fromMessage(message, event.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ public class RemoteIdEventTest extends AbstractRemoteEventTest {
|
||||
protected void assertEntity(final RemoteIdEvent event) {
|
||||
assertThat(event.getEntityId()).isSameAs(ENTITY_ID);
|
||||
|
||||
final RemoteIdEvent protoStuffEvent = (RemoteIdEvent) createProtoStuffEvent(event);
|
||||
final RemoteIdEvent protoStuffEvent = createProtoStuffEvent(event);
|
||||
assertDeserializeEvent(protoStuffEvent, event);
|
||||
|
||||
final RemoteIdEvent jacksonEvent = (RemoteIdEvent) createJacksonEvent(event);
|
||||
final RemoteIdEvent jacksonEvent = createJacksonEvent(event);
|
||||
assertDeserializeEvent(jacksonEvent, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.event.remote;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -18,7 +19,6 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionProperties;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
@@ -29,47 +29,71 @@ import io.qameta.allure.Story;
|
||||
@Story("RemoteTenantAwareEvent Tests")
|
||||
public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest {
|
||||
|
||||
private static final String TENANT_DEFAULT = "DEFAULT";
|
||||
|
||||
private static final String APPLICATION_ID_DEFAULT = "Node";
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the download progress reloading by remote events works")
|
||||
public void reloadDownloadProgessByRemoteEvent() {
|
||||
final DownloadProgressEvent downloadProgressEvent = new DownloadProgressEvent("DEFAULT", 1L, 3L, "Node");
|
||||
@Description("Verifies that a MultiActionEvent can be properly serialized and deserialized")
|
||||
public void testMultiActionEvent() {
|
||||
|
||||
DownloadProgressEvent remoteEvent = (DownloadProgressEvent) createProtoStuffEvent(downloadProgressEvent);
|
||||
assertThat(downloadProgressEvent).isEqualTo(remoteEvent);
|
||||
final List<String> controllerIds = Arrays.asList("id0", "id1", "id2", "id3",
|
||||
"id4loooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnng");
|
||||
final MultiActionEvent event = new MultiActionEvent(TENANT_DEFAULT, APPLICATION_ID_DEFAULT, controllerIds);
|
||||
|
||||
final MultiActionEvent remoteEventProtoStuff = createProtoStuffEvent(event);
|
||||
assertThat(event).isEqualTo(remoteEventProtoStuff);
|
||||
assertThat(remoteEventProtoStuff.getControllerIds()).containsExactlyElementsOf(controllerIds);
|
||||
|
||||
final MultiActionEvent remoteEventJackson = createJacksonEvent(event);
|
||||
assertThat(event).isEqualTo(remoteEventJackson);
|
||||
assertThat(remoteEventJackson.getControllerIds()).containsExactlyElementsOf(controllerIds);
|
||||
|
||||
remoteEvent = (DownloadProgressEvent) createJacksonEvent(downloadProgressEvent);
|
||||
assertThat(downloadProgressEvent).isEqualTo(remoteEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that target assignment event works")
|
||||
@Description("Verifies that a DownloadProgressEvent can be properly serialized and deserialized")
|
||||
public void reloadDownloadProgessByRemoteEvent() {
|
||||
final DownloadProgressEvent downloadProgressEvent = new DownloadProgressEvent(TENANT_DEFAULT, 1L, 3L,
|
||||
APPLICATION_ID_DEFAULT);
|
||||
|
||||
final DownloadProgressEvent remoteEventProtoStuff = createProtoStuffEvent(downloadProgressEvent);
|
||||
assertThat(downloadProgressEvent).isEqualTo(remoteEventProtoStuff);
|
||||
|
||||
final DownloadProgressEvent remoteEventJackson = createJacksonEvent(downloadProgressEvent);
|
||||
assertThat(downloadProgressEvent).isEqualTo(remoteEventJackson);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a TargetAssignDistributionSetEvent can be properly serialized and deserialized")
|
||||
public void testTargetAssignDistributionSetEvent() {
|
||||
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
final JpaAction generateAction = new JpaAction();
|
||||
generateAction.setActionType(ActionType.FORCED);
|
||||
final Target target = testdataFactory.createTarget("Test");
|
||||
generateAction.setTarget(target);
|
||||
generateAction.setTarget(testdataFactory.createTarget("Test"));
|
||||
generateAction.setDistributionSet(dsA);
|
||||
generateAction.setStatus(Status.RUNNING);
|
||||
|
||||
final Action action = actionRepository.save(generateAction);
|
||||
|
||||
final TargetAssignDistributionSetEvent assignmentEvent = new TargetAssignDistributionSetEvent(
|
||||
action.getTenant(), dsA.getId(), Arrays.asList(action), serviceMatcher.getServiceId(),
|
||||
action.isMaintenanceWindowAvailable());
|
||||
|
||||
TargetAssignDistributionSetEvent underTest = (TargetAssignDistributionSetEvent) createProtoStuffEvent(
|
||||
assignmentEvent);
|
||||
assertTargetAssignDistributionSetEvent(action, underTest);
|
||||
final TargetAssignDistributionSetEvent remoteEventProtoStuff = createProtoStuffEvent(assignmentEvent);
|
||||
assertTargetAssignDistributionSetEvent(action, remoteEventProtoStuff);
|
||||
|
||||
underTest = (TargetAssignDistributionSetEvent) createJacksonEvent(assignmentEvent);
|
||||
assertTargetAssignDistributionSetEvent(action, underTest);
|
||||
final TargetAssignDistributionSetEvent remoteEventJackson = createJacksonEvent(assignmentEvent);
|
||||
assertTargetAssignDistributionSetEvent(action, remoteEventJackson);
|
||||
}
|
||||
|
||||
private void assertTargetAssignDistributionSetEvent(final Action action,
|
||||
final TargetAssignDistributionSetEvent underTest) {
|
||||
|
||||
assertThat(underTest.getActions().size()).isEqualTo(1);
|
||||
ActionProperties actionProperties = underTest.getActions().get(action.getTarget().getControllerId());
|
||||
final ActionProperties actionProperties = underTest.getActions().get(action.getTarget().getControllerId());
|
||||
assertThat(actionProperties).isNotNull();
|
||||
assertThat(actionProperties).isEqualToComparingFieldByField(new ActionProperties(action));
|
||||
assertThat(underTest.getDistributionSetId()).isEqualTo(action.getDistributionSet().getId());
|
||||
|
||||
@@ -57,10 +57,10 @@ public abstract class AbstractRemoteEntityEventTest<E> extends AbstractRemoteEve
|
||||
protected RemoteEntityEvent<?> assertEntity(final E baseEntity, final RemoteEntityEvent<?> event) {
|
||||
assertThat(event.getEntity()).isSameAs(baseEntity);
|
||||
|
||||
RemoteEntityEvent<?> underTestCreatedEvent = (RemoteEntityEvent<?>) createProtoStuffEvent(event);
|
||||
RemoteEntityEvent<?> underTestCreatedEvent = createProtoStuffEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
|
||||
underTestCreatedEvent = (RemoteEntityEvent<?>) createJacksonEvent(event);
|
||||
underTestCreatedEvent = createJacksonEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
return underTestCreatedEvent;
|
||||
}
|
||||
|
||||
@@ -74,12 +74,12 @@ public class ActionEventTest extends AbstractRemoteEntityEventTest<Action> {
|
||||
assertThat(event.getEntity()).isSameAs(baseEntity);
|
||||
assertThat(event.getRolloutId()).isEqualTo(1L);
|
||||
|
||||
AbstractActionEvent underTestCreatedEvent = (AbstractActionEvent) createProtoStuffEvent(event);
|
||||
AbstractActionEvent underTestCreatedEvent = createProtoStuffEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
assertThat(underTestCreatedEvent.getRolloutId()).isEqualTo(1L);
|
||||
assertThat(underTestCreatedEvent.getRolloutGroupId()).isEqualTo(2L);
|
||||
|
||||
underTestCreatedEvent = (AbstractActionEvent) createJacksonEvent(event);
|
||||
underTestCreatedEvent = createJacksonEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
assertThat(underTestCreatedEvent.getRolloutId()).isEqualTo(1L);
|
||||
assertThat(underTestCreatedEvent.getRolloutGroupId()).isEqualTo(2L);
|
||||
|
||||
@@ -76,11 +76,11 @@ public class RolloutGroupEventTest extends AbstractRemoteEntityEventTest<Rollout
|
||||
assertThat(event.getEntity()).isSameAs(baseEntity);
|
||||
assertThat(event.getRolloutId()).isEqualTo(1L);
|
||||
|
||||
AbstractRolloutGroupEvent underTestCreatedEvent = (AbstractRolloutGroupEvent) createProtoStuffEvent(event);
|
||||
AbstractRolloutGroupEvent underTestCreatedEvent = createProtoStuffEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
assertThat(underTestCreatedEvent.getRolloutId()).isEqualTo(1L);
|
||||
|
||||
underTestCreatedEvent = (AbstractRolloutGroupEvent) createJacksonEvent(event);
|
||||
underTestCreatedEvent = createJacksonEvent(event);
|
||||
assertThat(underTestCreatedEvent.getEntity()).isEqualTo(baseEntity);
|
||||
assertThat(underTestCreatedEvent.getRolloutId()).isEqualTo(1L);
|
||||
|
||||
|
||||
@@ -17,10 +17,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -31,6 +28,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
@@ -48,7 +46,6 @@ import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionProperties;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
@@ -60,11 +57,7 @@ import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
@@ -90,22 +83,6 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
private static final boolean STATE_ACTIVE = true;
|
||||
private static final boolean STATE_INACTIVE = false;
|
||||
|
||||
private EventHandlerStub eventHandlerStub;
|
||||
|
||||
private CancelEventHandlerStub cancelEventHandlerStub;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@Before
|
||||
public void addHandler() {
|
||||
eventHandlerStub = new EventHandlerStub();
|
||||
applicationContext.addApplicationListener(eventHandlerStub);
|
||||
|
||||
cancelEventHandlerStub = new CancelEventHandlerStub();
|
||||
applicationContext.addApplicationListener(cancelEventHandlerStub);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access react as specfied on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@@ -276,7 +253,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Test verifies that an assignment with automatic cancelation works correctly even if the update is split into multiple partitions on the database.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = Constants.MAX_ENTRIES_IN_STATEMENT + 10),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2 * (Constants.MAX_ENTRIES_IN_STATEMENT + 10)),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2 * (Constants.MAX_ENTRIES_IN_STATEMENT + 10)),
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = Constants.MAX_ENTRIES_IN_STATEMENT + 10),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = Constants.MAX_ENTRIES_IN_STATEMENT + 10),
|
||||
@@ -581,12 +558,15 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
* {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)}
|
||||
* and checking the active action and the action history of the targets.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Test
|
||||
@Description("Simple deployment or distribution set to target assignment test.")
|
||||
public void assignDistributionSet2Targets() throws InterruptedException {
|
||||
eventHandlerStub.setExpectedNumberOfEvents(1);
|
||||
@ExpectEvents({@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetCreatedEvent.class, count = 30), @Expect(type = ActionCreatedEvent.class, count = 20),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 20),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3)})
|
||||
public void assignDistributionSet2Targets() {
|
||||
|
||||
final String myCtrlIDPref = "myCtrlID";
|
||||
final Iterable<Target> savedNakedTargets = testdataFactory.createTargets(10, myCtrlIDPref, "first description");
|
||||
@@ -631,17 +611,19 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(ua.getDistributionSet()).as("action has wrong ds").isEqualTo(ds);
|
||||
}
|
||||
}
|
||||
|
||||
final List<TargetAssignDistributionSetEvent> events = eventHandlerStub.getEvents(10, TimeUnit.SECONDS);
|
||||
|
||||
assertTargetAssignDistributionSetEvents(savedDeployedTargets, ds, events);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test that it is not possible to assign a distribution set that is not complete.")
|
||||
public void failDistributionSetAssigmentThatIsNotComplete() throws InterruptedException {
|
||||
eventHandlerStub.setExpectedNumberOfEvents(0);
|
||||
@ExpectEvents({@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetCreatedEvent.class, count = 10), @Expect(type = ActionCreatedEvent.class, count = 10),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 10),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 2),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1)
|
||||
|
||||
})
|
||||
public void failDistributionSetAssigmentThatIsNotComplete() throws InterruptedException {
|
||||
final List<Target> targets = testdataFactory.createTargets(10);
|
||||
|
||||
final SoftwareModule ah = testdataFactory.createSoftwareModuleApp();
|
||||
@@ -656,51 +638,32 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
} catch (final IncompleteDistributionSetException ex) {
|
||||
}
|
||||
|
||||
// give some chance to receive events asynchronously
|
||||
Thread.sleep(1L);
|
||||
final List<TargetAssignDistributionSetEvent> events = eventHandlerStub.getEvents(5, TimeUnit.SECONDS);
|
||||
assertThat(events).as("events should be empty").isEmpty();
|
||||
|
||||
final DistributionSet nowComplete = distributionSetManagement.assignSoftwareModules(incomplete.getId(),
|
||||
Sets.newHashSet(os.getId()));
|
||||
|
||||
eventHandlerStub.setExpectedNumberOfEvents(1);
|
||||
|
||||
assertThat(assignDistributionSet(nowComplete, targets).getAssigned()).as("assign ds doesn't work")
|
||||
.isEqualTo(10);
|
||||
|
||||
assertTargetAssignDistributionSetEvents(targets, nowComplete, eventHandlerStub.getEvents(15, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Multiple deployments or distribution set to target assignment test. Expected behaviour is that a new deployment "
|
||||
+ "overides unfinished old one which are canceled as part of the operation.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 5 + 4),
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 5 + 4),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3 * 4),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 3 * 4),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 4 * 2),
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 4 * 2),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 9),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1) })
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2)})
|
||||
public void mutipleDeployments() throws InterruptedException {
|
||||
final String undeployedTargetPrefix = "undep-T";
|
||||
final int noOfUndeployedTargets = 5;
|
||||
|
||||
final String deployedTargetPrefix = "dep-T";
|
||||
final int noOfDeployedTargets = 4;
|
||||
|
||||
final int noOfDistributionSets = 3;
|
||||
|
||||
// One assigment per DS
|
||||
final int expectedNumberOfEventsForAssignment = 1;
|
||||
eventHandlerStub.setExpectedNumberOfEvents(expectedNumberOfEventsForAssignment);
|
||||
|
||||
// Each of the four targets get two more assignment the which are
|
||||
// cancelled (4 * 2 = 8)
|
||||
final int expectedNumberOfEventsForCancel = 8;
|
||||
cancelEventHandlerStub.setExpectedNumberOfEvents(expectedNumberOfEventsForCancel);
|
||||
|
||||
final DeploymentResult deploymentResult = prepareComplexRepo(undeployedTargetPrefix, noOfUndeployedTargets,
|
||||
deployedTargetPrefix, noOfDeployedTargets, noOfDistributionSets, "myTestDS");
|
||||
|
||||
@@ -739,13 +702,6 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
.doesNotContain(Iterables.toArray(undeployedTargetsFromDB, JpaTarget.class));
|
||||
assertThat(undeployedTargetsFromDB).as("content of undeployed target is wrong").containsAll(savedNakedTargets)
|
||||
.doesNotContain(Iterables.toArray(deployedTargetsFromDB, JpaTarget.class));
|
||||
|
||||
// For each of the 4 targets 1 distribution sets gets assigned
|
||||
eventHandlerStub.getEvents(10, TimeUnit.SECONDS);
|
||||
|
||||
// For each of the 4 targets 2 distribution sets gets cancelled
|
||||
cancelEventHandlerStub.getEvents(10, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1111,22 +1067,6 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
private void assertTargetAssignDistributionSetEvents(final List<Target> targets, final DistributionSet ds,
|
||||
final List<TargetAssignDistributionSetEvent> events) {
|
||||
assertThat(events).hasSize(1);
|
||||
final TargetAssignDistributionSetEvent event = events.get(0);
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionSetId()).isEqualTo(ds.getId());
|
||||
|
||||
final List<Long> eventActionIds = event.getActions().values().stream().map(ActionProperties::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
final List<Long> targetActiveActionIds = targets.stream()
|
||||
.map(t -> deploymentManagement.findActiveActionsByTarget(PAGE, t.getControllerId()).getContent())
|
||||
.flatMap(List::stream).map(Action::getId).collect(Collectors.toList());
|
||||
assertThat(eventActionIds).containsOnlyElementsOf(targetActiveActionIds);
|
||||
}
|
||||
|
||||
private class DeploymentResult {
|
||||
final List<Long> deployedTargetIDs = new ArrayList<>();
|
||||
final List<Long> undeployedTargetIDs = new ArrayList<>();
|
||||
@@ -1178,73 +1118,6 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
protected static class EventHandlerStub implements ApplicationListener<TargetAssignDistributionSetEvent> {
|
||||
private final List<TargetAssignDistributionSetEvent> events = Collections.synchronizedList(new LinkedList<>());
|
||||
private CountDownLatch latch;
|
||||
private int expectedNumberOfEvents;
|
||||
|
||||
/**
|
||||
* @param expectedNumberOfEvents
|
||||
* the expectedNumberOfEvents to set
|
||||
*/
|
||||
public void setExpectedNumberOfEvents(final int expectedNumberOfEvents) {
|
||||
events.clear();
|
||||
this.expectedNumberOfEvents = expectedNumberOfEvents;
|
||||
this.latch = new CountDownLatch(expectedNumberOfEvents);
|
||||
}
|
||||
|
||||
public List<TargetAssignDistributionSetEvent> getEvents(final long timeout, final TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
latch.await(timeout, unit);
|
||||
final List<TargetAssignDistributionSetEvent> handledEvents = Collections
|
||||
.unmodifiableList(new LinkedList<>(events));
|
||||
assertThat(handledEvents).as("Did not receive the expected amount of events (" + expectedNumberOfEvents
|
||||
+ ") within timeout. Received events are " + handledEvents).hasSize(expectedNumberOfEvents);
|
||||
return handledEvents;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(final TargetAssignDistributionSetEvent event) {
|
||||
if (latch == null) {
|
||||
return;
|
||||
}
|
||||
events.add(event);
|
||||
latch.countDown();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class CancelEventHandlerStub implements ApplicationListener<CancelTargetAssignmentEvent> {
|
||||
private final List<CancelTargetAssignmentEvent> events = Collections.synchronizedList(new LinkedList<>());
|
||||
private CountDownLatch latch;
|
||||
private int expectedNumberOfEvents;
|
||||
|
||||
public void setExpectedNumberOfEvents(final int expectedNumberOfEvents) {
|
||||
events.clear();
|
||||
this.expectedNumberOfEvents = expectedNumberOfEvents;
|
||||
this.latch = new CountDownLatch(expectedNumberOfEvents);
|
||||
}
|
||||
|
||||
public List<CancelTargetAssignmentEvent> getEvents(final long timeout, final TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
latch.await(timeout, unit);
|
||||
final List<CancelTargetAssignmentEvent> handledEvents = new LinkedList<>(events);
|
||||
assertThat(handledEvents).as("Did not receive the expected amount of events (" + expectedNumberOfEvents
|
||||
+ ") within timeout. Received events are " + handledEvents).hasSize(expectedNumberOfEvents);
|
||||
return handledEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(final CancelTargetAssignmentEvent event) {
|
||||
if (latch == null) {
|
||||
return;
|
||||
}
|
||||
events.add(event);
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private void enableMultiAssignments() {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user