From a4dd4ce1911c269f9f2290d5a34aac27736ca5b7 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Mon, 22 May 2017 17:36:42 +0200 Subject: [PATCH] Introduce cache for rollouts status computation. (#509) * Introduce cache for rollouts status computation. Signed-off-by: kaizimmerm * Disable cache during tests. Signed-off-by: kaizimmerm * Move cache into core. Signed-off-by: kaizimmerm * package private event listener. Signed-off-by: kaizimmerm * Fix cache invalidation. Signed-off-by: kaizimmerm * Fix sonar issues. Signed-off-by: kaizimmerm * Fixed a test that assumes that target to group assignment follows a rule which si not the case. Signed-off-by: kaizimmerm --- .../hawkbit-repository-core/pom.xml | 8 + .../repository/RolloutStatusCache.java | 235 ++++++++++++++++++ .../hawkbit-repository-jpa/pom.xml | 5 +- .../repository/jpa/ActionRepository.java | 6 +- .../jpa/JpaRolloutGroupManagement.java | 37 ++- .../repository/jpa/JpaRolloutManagement.java | 34 ++- .../RepositoryApplicationConfiguration.java | 7 + .../repository/jpa/RolloutManagementTest.java | 33 ++- .../repository/test/TestConfiguration.java | 9 + 9 files changed, 345 insertions(+), 29 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java diff --git a/hawkbit-repository/hawkbit-repository-core/pom.xml b/hawkbit-repository/hawkbit-repository-core/pom.xml index 7980d4652..a70024c1b 100644 --- a/hawkbit-repository/hawkbit-repository-core/pom.xml +++ b/hawkbit-repository/hawkbit-repository-core/pom.xml @@ -24,6 +24,14 @@ hawkbit-repository-api ${project.version} + + com.google.guava + guava + + + org.springframework + spring-context-support + io.protostuff protostuff-core diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java new file mode 100644 index 000000000..3fc71d431 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java @@ -0,0 +1,235 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.eclipse.hawkbit.cache.TenancyCacheManager; +import org.eclipse.hawkbit.cache.TenantAwareCacheManager; +import org.eclipse.hawkbit.repository.event.remote.entity.AbstractActionEvent; +import org.eclipse.hawkbit.repository.model.Rollout; +import org.eclipse.hawkbit.repository.model.RolloutGroup; +import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; +import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.cache.Cache; +import org.springframework.cache.guava.GuavaCacheManager; +import org.springframework.context.event.EventListener; + +import com.google.common.cache.CacheBuilder; + +/** + * Internal cache for Rollout status. + * + */ +public class RolloutStatusCache { + private static final String CACHE_RO_NAME = "RolloutStatus"; + private static final String CACHE_GR_NAME = "RolloutGroupStatus"; + private static final long DEFAULT_SIZE = 50_000; + private final TenancyCacheManager cacheManager; + private final TenantAware tenantAware; + + /** + * @param tenantAware + * to get current tenant + * @param size + * the maximum size of the cache + */ + public RolloutStatusCache(final TenantAware tenantAware, final long size) { + this.tenantAware = tenantAware; + + final CacheBuilder cacheBuilder = CacheBuilder.newBuilder().maximumSize(size); + final GuavaCacheManager guavaCacheManager = new GuavaCacheManager(); + guavaCacheManager.setCacheBuilder(cacheBuilder); + + this.cacheManager = new TenantAwareCacheManager(guavaCacheManager, tenantAware); + } + + /** + * @param tenantAware + * to get current tenant + */ + public RolloutStatusCache(final TenantAware tenantAware) { + this(tenantAware, DEFAULT_SIZE); + } + + /** + * Retrieves cached list of {@link TotalTargetCountActionStatus} of + * {@link Rollout}s. + * + * @param rollouts + * rolloutIds to retrieve cache entries for + * @return map of cached entries + */ + public Map> getRolloutStatus(final List rollouts) { + final Cache cache = cacheManager.getCache(CACHE_RO_NAME); + + return retrieveFromCache(rollouts, cache); + } + + /** + * Retrieves cached list of {@link TotalTargetCountActionStatus} of + * {@link Rollout}s. + * + * @param rolloutId + * to retrieve cache entries for + * @return map of cached entries + */ + public List getRolloutStatus(final Long rolloutId) { + final Cache cache = cacheManager.getCache(CACHE_RO_NAME); + + return retrieveFromCache(rolloutId, cache); + } + + /** + * Retrieves cached list of {@link TotalTargetCountActionStatus} of + * {@link RolloutGroup}s. + * + * @param rolloutGroups + * rolloutGroupsIds to retrieve cache entries for + * @return map of cached entries + */ + public Map> getRolloutGroupStatus(final List rolloutGroups) { + final Cache cache = cacheManager.getCache(CACHE_GR_NAME); + + return retrieveFromCache(rolloutGroups, cache); + } + + /** + * Retrieves cached list of {@link TotalTargetCountActionStatus} of + * {@link RolloutGroup}. + * + * @param groupId + * to retrieve cache entries for + * @return map of cached entries + */ + public List getRolloutGroupStatus(final Long groupId) { + final Cache cache = cacheManager.getCache(CACHE_GR_NAME); + + return retrieveFromCache(groupId, cache); + } + + /** + * Put map of {@link TotalTargetCountActionStatus} for multiple + * {@link Rollout}s into cache. + * + * @param put + * map of cached entries + */ + public void putRolloutStatus(final Map> put) { + final Cache cache = cacheManager.getCache(CACHE_RO_NAME); + putIntoCache(put, cache); + } + + /** + * Put {@link TotalTargetCountActionStatus} for one {@link Rollout}s into + * cache. + * + * @param rolloutId + * the cache entries belong to + * @param status + * list to cache + * + */ + public void putRolloutStatus(final Long rolloutId, final List status) { + final Cache cache = cacheManager.getCache(CACHE_RO_NAME); + putIntoCache(rolloutId, status, cache); + } + + /** + * Put {@link TotalTargetCountActionStatus} for multiple + * {@link RolloutGroup}s into cache. + * + * @param put + * map of cached entries + */ + public void putRolloutGroupStatus(final Map> put) { + final Cache cache = cacheManager.getCache(CACHE_GR_NAME); + putIntoCache(put, cache); + } + + /** + * Put {@link TotalTargetCountActionStatus} for multiple + * {@link RolloutGroup}s into cache. + * + * @param groupId + * the cache entries belong to + * @param status + * list to cache + */ + public void putRolloutGroupStatus(final Long groupId, final List status) { + final Cache cache = cacheManager.getCache(CACHE_GR_NAME); + putIntoCache(groupId, status, cache); + } + + private Map> retrieveFromCache(final List ids, final Cache cache) { + return ids.stream().map(rolloutId -> cache.get(rolloutId, CachedTotalTargetCountActionStatus.class)) + .filter(Objects::nonNull).collect(Collectors.toMap(CachedTotalTargetCountActionStatus::getRolloutId, + CachedTotalTargetCountActionStatus::getStatus)); + } + + private List retrieveFromCache(final Long id, final Cache cache) { + final CachedTotalTargetCountActionStatus cacheItem = cache.get(id, CachedTotalTargetCountActionStatus.class); + + if (cacheItem == null) { + return Collections.emptyList(); + } + + return cacheItem.getStatus(); + } + + private void putIntoCache(final Long rolloutId, final List status, + final Cache cache) { + cache.put(rolloutId, new CachedTotalTargetCountActionStatus(rolloutId, status)); + } + + private void putIntoCache(final Map> put, final Cache cache) { + put.entrySet().forEach(entry -> cache.put(entry.getKey(), + new CachedTotalTargetCountActionStatus(entry.getKey(), entry.getValue()))); + } + + @EventListener(classes = AbstractActionEvent.class) + void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) { + if (event.getRolloutId() == null) { + return; + } + + Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME)); + cache.evict(event.getRolloutId()); + + if (event.getRolloutGroupId() == null) { + return; + } + + cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_GR_NAME)); + cache.evict(event.getRolloutGroupId()); + } + + private static final class CachedTotalTargetCountActionStatus { + private final long rolloutId; + private final List status; + + private CachedTotalTargetCountActionStatus(final long rolloutId, + final List status) { + this.rolloutId = rolloutId; + this.status = status; + } + + public long getRolloutId() { + return rolloutId; + } + + public List getStatus() { + return status; + } + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/pom.xml b/hawkbit-repository/hawkbit-repository-jpa/pom.xml index d4b43c67c..a59a698cb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/pom.xml +++ b/hawkbit-repository/hawkbit-repository-jpa/pom.xml @@ -121,7 +121,7 @@ com.ethlo.persistence.tools eclipselink-maven-plugin - 2.6.2 + 2.6.4.2 modelgen @@ -137,6 +137,9 @@ + + org.eclipse.hawkbit.repository.jpa.model + org.eclipse.persistence diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java index 639dd8328..680ca6066 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java @@ -392,7 +392,7 @@ public interface ActionRepository extends BaseEntityRepository, * id of {@link Rollout} * @return list of objects with status and target count */ - @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rollout.id = ?1 GROUP BY a.rollout.id,a.status") + @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rollout.id = ?1 GROUP BY a.rollout.id,a.status") List getStatusCountByRolloutId(Long rolloutId); /** @@ -403,7 +403,7 @@ public interface ActionRepository extends BaseEntityRepository, * id of {@link RolloutGroup} * @return list of objects with status and target count */ - @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rolloutGroup.id = ?1 GROUP BY a.rolloutGroup.id, a.status") + @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rolloutGroup.id = ?1 GROUP BY a.rolloutGroup.id, a.status") List getStatusCountByRolloutGroupId(Long rolloutGroupId); /** @@ -414,7 +414,7 @@ public interface ActionRepository extends BaseEntityRepository, * list of id of {@link RolloutGroup} * @return list of objects with status and target count */ - @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rolloutGroup.id IN ?1 GROUP BY a.rolloutGroup.id, a.status") + @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rolloutGroup.id IN ?1 GROUP BY a.rolloutGroup.id, a.status") List getStatusCountByRolloutGroupId(List rolloutGroupId); /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java index 53a01f95d..73e4b5c7c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java @@ -25,6 +25,7 @@ import javax.validation.constraints.NotNull; import org.eclipse.hawkbit.repository.RolloutGroupFields; import org.eclipse.hawkbit.repository.RolloutGroupManagement; +import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; @@ -79,6 +80,9 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { @Autowired private VirtualPropertyReplacer virtualPropertyReplacer; + @Autowired + private RolloutStatusCache rolloutStatusCache; + @Override public Optional findRolloutGroupById(final Long rolloutGroupId) { return Optional.ofNullable(rolloutGroupRepository.findOne(rolloutGroupId)); @@ -159,8 +163,13 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroup.get(); - final List rolloutStatusCountItems = actionRepository - .getStatusCountByRolloutGroupId(rolloutGroupId); + List rolloutStatusCountItems = rolloutStatusCache + .getRolloutGroupStatus(rolloutGroupId); + + if (rolloutStatusCountItems.isEmpty()) { + rolloutStatusCountItems = actionRepository.getStatusCountByRolloutGroupId(rolloutGroupId); + rolloutStatusCache.putRolloutGroupStatus(rolloutGroupId, rolloutStatusCountItems); + } final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems, Long.valueOf(jpaRolloutGroup.getTotalTargets())); @@ -169,11 +178,25 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { } - private Map> getStatusCountItemForRolloutGroup( - final List rolloutGroupIds) { - final List resultList = actionRepository - .getStatusCountByRolloutGroupId(rolloutGroupIds); - return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId)); + private Map> getStatusCountItemForRolloutGroup(final List groupIds) { + final Map> fromCache = rolloutStatusCache + .getRolloutGroupStatus(groupIds); + + final List rolloutGroupIds = groupIds.stream().filter(id -> !fromCache.containsKey(id)) + .collect(Collectors.toList()); + + if (!rolloutGroupIds.isEmpty()) { + final List resultList = actionRepository + .getStatusCountByRolloutGroupId(rolloutGroupIds); + final Map> fromDb = resultList.stream() + .collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId)); + + rolloutStatusCache.putRolloutGroupStatus(fromDb); + + fromCache.putAll(fromDb); + } + + return fromCache; } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 15402d8e6..f28e77664 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -29,6 +29,7 @@ import org.eclipse.hawkbit.repository.RolloutFields; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutHelper; import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.builder.GenericRolloutUpdate; import org.eclipse.hawkbit.repository.builder.RolloutCreate; @@ -139,6 +140,9 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Autowired private QuotaManagement quotaManagement; + @Autowired + private RolloutStatusCache rolloutStatusCache; + JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement, final DistributionSetManagement distributionSetManagement, final ApplicationContext context, @@ -970,21 +974,41 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { return rollout; } - final List rolloutStatusCountItems = actionRepository - .getStatusCountByRolloutId(rolloutId); + List rolloutStatusCountItems = rolloutStatusCache.getRolloutStatus(rolloutId); + + if (rolloutStatusCountItems.isEmpty()) { + rolloutStatusCountItems = actionRepository.getStatusCountByRolloutId(rolloutId); + rolloutStatusCache.putRolloutStatus(rolloutId, rolloutStatusCountItems); + } + final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems, rollout.get().getTotalTargets()); ((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus); return rollout; } - private Map> getStatusCountItemForRollout(final List rolloutIds) { + private Map> getStatusCountItemForRollout(final List rollouts) { + if (rollouts.isEmpty()) { + return null; + } + + final Map> fromCache = rolloutStatusCache.getRolloutStatus(rollouts); + + final List rolloutIds = rollouts.stream().filter(id -> !fromCache.containsKey(id)) + .collect(Collectors.toList()); + if (!rolloutIds.isEmpty()) { final List resultList = actionRepository .getStatusCountByRolloutId(rolloutIds); - return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId)); + final Map> fromDb = resultList.stream() + .collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId)); + + rolloutStatusCache.putRolloutStatus(fromDb); + + fromCache.putAll(fromDb); } - return null; + + return fromCache; } private void setRolloutStatusDetails(final Slice rollouts) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index 544371e24..a5518b876 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -23,6 +23,7 @@ import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; +import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TagManagement; @@ -132,6 +133,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { return new PropertiesQuotaManagement(securityProperties); } + @Bean + @ConditionalOnMissingBean + RolloutStatusCache rolloutStatusCache(final TenantAware tenantAware) { + return new RolloutStatusCache(tenantAware); + } + /** * @param distributionSetManagement * to loading the {@link DistributionSetType} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 9c535e8de..a8689867a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -19,7 +19,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import org.assertj.core.api.Condition; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.builder.RolloutCreate; import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; @@ -630,8 +632,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { // 5 targets are in the group and the DS has been assigned final List rolloutGroups = rolloutGroupManagement .findRolloutGroupsByRolloutId(createdRollout.getId(), PAGE).getContent(); - final Page targets = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(), - PAGE); + final Page targets = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(), PAGE); final List targetList = targets.getContent(); assertThat(targetList.size()).isEqualTo(5); @@ -1028,7 +1029,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { } @Test - @Description("Verify that the expected targets in the expected order are returned for the rollout groups.") + @Description("Verify that the expected targets are returned for the rollout groups.") public void findRolloutGroupTargetsWithRsqlParam() { final int amountTargetsForRollout = 15; @@ -1049,27 +1050,33 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { // Run here, because scheduler is disabled during tests rolloutManagement.handleRollouts(); + final Condition targetBelongsInRollout = new Condition<>(s -> s.startsWith(rolloutName), + "Target belongs into rollout"); + myRollout = rolloutManagement.findRolloutById(myRollout.getId()).get(); final List rolloutGroups = rolloutGroupManagement .findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent(); Page targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(), - rsqlParam, new OffsetBasedPageRequest(0, 100, new Sort(Direction.ASC, "controllerId"))); + rsqlParam, new OffsetBasedPageRequest(0, 100)); final List targetlistGroup1 = targetPage.getContent(); assertThat(targetlistGroup1.size()).isEqualTo(5); - assertThat(targetlistGroup1.get(0).getControllerId()).isEqualTo("MyRollout--00000"); + assertThat(targetlistGroup1.stream().map(Target::getControllerId).collect(Collectors.toList())) + .are(targetBelongsInRollout); targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(1).getId(), rsqlParam, - new OffsetBasedPageRequest(0, 100, new Sort(Direction.DESC, "controllerId"))); + new OffsetBasedPageRequest(0, 100)); final List targetlistGroup2 = targetPage.getContent(); assertThat(targetlistGroup2.size()).isEqualTo(5); - assertThat(targetlistGroup2.get(0).getControllerId()).isEqualTo("MyRollout--00009"); + assertThat(targetlistGroup2.stream().map(Target::getControllerId).collect(Collectors.toList())) + .are(targetBelongsInRollout); targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(2).getId(), rsqlParam, - new OffsetBasedPageRequest(0, 100, new Sort(Direction.ASC, "controllerId"))); + new OffsetBasedPageRequest(0, 100)); final List targetlistGroup3 = targetPage.getContent(); assertThat(targetlistGroup3.size()).isEqualTo(5); - assertThat(targetlistGroup3.get(0).getControllerId()).isEqualTo("MyRollout--00010"); + assertThat(targetlistGroup3.stream().map(Target::getControllerId).collect(Collectors.toList())) + .are(targetBelongsInRollout); } @@ -1128,8 +1135,8 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); - final List groups = rolloutGroupManagement - .findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent(); + final List groups = rolloutGroupManagement.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE) + .getContent(); assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY); assertThat(groups.get(0).getTotalTargets()).isEqualTo(1); @@ -1301,8 +1308,8 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); assertThat(myRollout.getTotalTargets()).isEqualTo(amountTargetsInGroup1and2 + amountTargetsInGroup1); - final List groups = rolloutGroupManagement - .findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent(); + final List groups = rolloutGroupManagement.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE) + .getContent(); ; assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY); assertThat(groups.get(0).getTotalTargets()).isEqualTo(amountTargetsInGroup1); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java index 0a0671a08..ee9b91497 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java @@ -22,6 +22,7 @@ import org.eclipse.hawkbit.cache.DefaultDownloadIdCache; import org.eclipse.hawkbit.cache.DownloadIdCache; import org.eclipse.hawkbit.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter; +import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -75,6 +76,14 @@ import org.springframework.util.AntPathMatcher; @EnableAutoConfiguration public class TestConfiguration implements AsyncConfigurer { + /** + * Disables caching during test to avoid concurrency failures during test. + */ + @Bean + RolloutStatusCache rolloutStatusCache(final TenantAware tenantAware) { + return new RolloutStatusCache(tenantAware, 0); + } + @Bean public LockRegistry lockRegistry() { return new DefaultLockRegistry();