Introduce cache for rollouts status computation. (#509)
* Introduce cache for rollouts status computation. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Disable cache during tests. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Move cache into core. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * package private event listener. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix cache invalidation. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix sonar issues. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fixed a test that assumes that target to group assignment follows a rule which si not the case. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -24,6 +24,14 @@
|
|||||||
<artifactId>hawkbit-repository-api</artifactId>
|
<artifactId>hawkbit-repository-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.protostuff</groupId>
|
<groupId>io.protostuff</groupId>
|
||||||
<artifactId>protostuff-core</artifactId>
|
<artifactId>protostuff-core</artifactId>
|
||||||
|
|||||||
@@ -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<Object, Object> 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<Long, List<TotalTargetCountActionStatus>> getRolloutStatus(final List<Long> 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<TotalTargetCountActionStatus> 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<Long, List<TotalTargetCountActionStatus>> getRolloutGroupStatus(final List<Long> 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<TotalTargetCountActionStatus> 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<Long, List<TotalTargetCountActionStatus>> 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<TotalTargetCountActionStatus> 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<Long, List<TotalTargetCountActionStatus>> 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<TotalTargetCountActionStatus> status) {
|
||||||
|
final Cache cache = cacheManager.getCache(CACHE_GR_NAME);
|
||||||
|
putIntoCache(groupId, status, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> 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<TotalTargetCountActionStatus> 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<TotalTargetCountActionStatus> status,
|
||||||
|
final Cache cache) {
|
||||||
|
cache.put(rolloutId, new CachedTotalTargetCountActionStatus(rolloutId, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putIntoCache(final Map<Long, List<TotalTargetCountActionStatus>> 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<TotalTargetCountActionStatus> status;
|
||||||
|
|
||||||
|
private CachedTotalTargetCountActionStatus(final long rolloutId,
|
||||||
|
final List<TotalTargetCountActionStatus> status) {
|
||||||
|
this.rolloutId = rolloutId;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRolloutId() {
|
||||||
|
return rolloutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TotalTargetCountActionStatus> getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.ethlo.persistence.tools</groupId>
|
<groupId>com.ethlo.persistence.tools</groupId>
|
||||||
<artifactId>eclipselink-maven-plugin</artifactId>
|
<artifactId>eclipselink-maven-plugin</artifactId>
|
||||||
<version>2.6.2</version>
|
<version>2.6.4.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>modelgen</id>
|
<id>modelgen</id>
|
||||||
@@ -137,6 +137,9 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<basePackage>org.eclipse.hawkbit.repository.jpa.model</basePackage>
|
||||||
|
</configuration>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.persistence</groupId>
|
<groupId>org.eclipse.persistence</groupId>
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
* id of {@link Rollout}
|
* id of {@link Rollout}
|
||||||
* @return list of objects with status and target count
|
* @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<TotalTargetCountActionStatus> getStatusCountByRolloutId(Long rolloutId);
|
List<TotalTargetCountActionStatus> getStatusCountByRolloutId(Long rolloutId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -403,7 +403,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
* id of {@link RolloutGroup}
|
* id of {@link RolloutGroup}
|
||||||
* @return list of objects with status and target count
|
* @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<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(Long rolloutGroupId);
|
List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(Long rolloutGroupId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,7 +414,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
* list of id of {@link RolloutGroup}
|
* list of id of {@link RolloutGroup}
|
||||||
* @return list of objects with status and target count
|
* @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<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(List<Long> rolloutGroupId);
|
List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(List<Long> rolloutGroupId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.RolloutGroupFields;
|
import org.eclipse.hawkbit.repository.RolloutGroupFields;
|
||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||||
import org.eclipse.hawkbit.repository.TargetFields;
|
import org.eclipse.hawkbit.repository.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
@@ -79,6 +80,9 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private VirtualPropertyReplacer virtualPropertyReplacer;
|
private VirtualPropertyReplacer virtualPropertyReplacer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RolloutStatusCache rolloutStatusCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<RolloutGroup> findRolloutGroupById(final Long rolloutGroupId) {
|
public Optional<RolloutGroup> findRolloutGroupById(final Long rolloutGroupId) {
|
||||||
return Optional.ofNullable(rolloutGroupRepository.findOne(rolloutGroupId));
|
return Optional.ofNullable(rolloutGroupRepository.findOne(rolloutGroupId));
|
||||||
@@ -159,8 +163,13 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
|
|
||||||
final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroup.get();
|
final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroup.get();
|
||||||
|
|
||||||
final List<TotalTargetCountActionStatus> rolloutStatusCountItems = actionRepository
|
List<TotalTargetCountActionStatus> rolloutStatusCountItems = rolloutStatusCache
|
||||||
.getStatusCountByRolloutGroupId(rolloutGroupId);
|
.getRolloutGroupStatus(rolloutGroupId);
|
||||||
|
|
||||||
|
if (rolloutStatusCountItems.isEmpty()) {
|
||||||
|
rolloutStatusCountItems = actionRepository.getStatusCountByRolloutGroupId(rolloutGroupId);
|
||||||
|
rolloutStatusCache.putRolloutGroupStatus(rolloutGroupId, rolloutStatusCountItems);
|
||||||
|
}
|
||||||
|
|
||||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
||||||
Long.valueOf(jpaRolloutGroup.getTotalTargets()));
|
Long.valueOf(jpaRolloutGroup.getTotalTargets()));
|
||||||
@@ -169,11 +178,25 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, List<TotalTargetCountActionStatus>> getStatusCountItemForRolloutGroup(
|
private Map<Long, List<TotalTargetCountActionStatus>> getStatusCountItemForRolloutGroup(final List<Long> groupIds) {
|
||||||
final List<Long> rolloutGroupIds) {
|
final Map<Long, List<TotalTargetCountActionStatus>> fromCache = rolloutStatusCache
|
||||||
|
.getRolloutGroupStatus(groupIds);
|
||||||
|
|
||||||
|
final List<Long> rolloutGroupIds = groupIds.stream().filter(id -> !fromCache.containsKey(id))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!rolloutGroupIds.isEmpty()) {
|
||||||
final List<TotalTargetCountActionStatus> resultList = actionRepository
|
final List<TotalTargetCountActionStatus> resultList = actionRepository
|
||||||
.getStatusCountByRolloutGroupId(rolloutGroupIds);
|
.getStatusCountByRolloutGroupId(rolloutGroupIds);
|
||||||
return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId));
|
final Map<Long, List<TotalTargetCountActionStatus>> fromDb = resultList.stream()
|
||||||
|
.collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId));
|
||||||
|
|
||||||
|
rolloutStatusCache.putRolloutGroupStatus(fromDb);
|
||||||
|
|
||||||
|
fromCache.putAll(fromDb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.eclipse.hawkbit.repository.RolloutFields;
|
|||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
import org.eclipse.hawkbit.repository.RolloutHelper;
|
import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
import org.eclipse.hawkbit.repository.builder.GenericRolloutUpdate;
|
import org.eclipse.hawkbit.repository.builder.GenericRolloutUpdate;
|
||||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||||
@@ -139,6 +140,9 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private QuotaManagement quotaManagement;
|
private QuotaManagement quotaManagement;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RolloutStatusCache rolloutStatusCache;
|
||||||
|
|
||||||
JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
|
JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
|
||||||
final RolloutGroupManagement rolloutGroupManagement,
|
final RolloutGroupManagement rolloutGroupManagement,
|
||||||
final DistributionSetManagement distributionSetManagement, final ApplicationContext context,
|
final DistributionSetManagement distributionSetManagement, final ApplicationContext context,
|
||||||
@@ -970,21 +974,41 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
return rollout;
|
return rollout;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<TotalTargetCountActionStatus> rolloutStatusCountItems = actionRepository
|
List<TotalTargetCountActionStatus> rolloutStatusCountItems = rolloutStatusCache.getRolloutStatus(rolloutId);
|
||||||
.getStatusCountByRolloutId(rolloutId);
|
|
||||||
|
if (rolloutStatusCountItems.isEmpty()) {
|
||||||
|
rolloutStatusCountItems = actionRepository.getStatusCountByRolloutId(rolloutId);
|
||||||
|
rolloutStatusCache.putRolloutStatus(rolloutId, rolloutStatusCountItems);
|
||||||
|
}
|
||||||
|
|
||||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
||||||
rollout.get().getTotalTargets());
|
rollout.get().getTotalTargets());
|
||||||
((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus);
|
((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus);
|
||||||
return rollout;
|
return rollout;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, List<TotalTargetCountActionStatus>> getStatusCountItemForRollout(final List<Long> rolloutIds) {
|
private Map<Long, List<TotalTargetCountActionStatus>> getStatusCountItemForRollout(final List<Long> rollouts) {
|
||||||
|
if (rollouts.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<Long, List<TotalTargetCountActionStatus>> fromCache = rolloutStatusCache.getRolloutStatus(rollouts);
|
||||||
|
|
||||||
|
final List<Long> rolloutIds = rollouts.stream().filter(id -> !fromCache.containsKey(id))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (!rolloutIds.isEmpty()) {
|
if (!rolloutIds.isEmpty()) {
|
||||||
final List<TotalTargetCountActionStatus> resultList = actionRepository
|
final List<TotalTargetCountActionStatus> resultList = actionRepository
|
||||||
.getStatusCountByRolloutId(rolloutIds);
|
.getStatusCountByRolloutId(rolloutIds);
|
||||||
return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId));
|
final Map<Long, List<TotalTargetCountActionStatus>> fromDb = resultList.stream()
|
||||||
|
.collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId));
|
||||||
|
|
||||||
|
rolloutStatusCache.putRolloutStatus(fromDb);
|
||||||
|
|
||||||
|
fromCache.putAll(fromDb);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
return fromCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRolloutStatusDetails(final Slice<JpaRollout> rollouts) {
|
private void setRolloutStatusDetails(final Slice<JpaRollout> rollouts) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.eclipse.hawkbit.repository.PropertiesQuotaManagement;
|
|||||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.TagManagement;
|
import org.eclipse.hawkbit.repository.TagManagement;
|
||||||
@@ -132,6 +133,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
return new PropertiesQuotaManagement(securityProperties);
|
return new PropertiesQuotaManagement(securityProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
RolloutStatusCache rolloutStatusCache(final TenantAware tenantAware) {
|
||||||
|
return new RolloutStatusCache(tenantAware);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param distributionSetManagement
|
* @param distributionSetManagement
|
||||||
* to loading the {@link DistributionSetType}
|
* to loading the {@link DistributionSetType}
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.TimeUnit;
|
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.OffsetBasedPageRequest;
|
||||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
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
|
// 5 targets are in the group and the DS has been assigned
|
||||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
|
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
|
||||||
.findRolloutGroupsByRolloutId(createdRollout.getId(), PAGE).getContent();
|
.findRolloutGroupsByRolloutId(createdRollout.getId(), PAGE).getContent();
|
||||||
final Page<Target> targets = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(),
|
final Page<Target> targets = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(), PAGE);
|
||||||
PAGE);
|
|
||||||
final List<Target> targetList = targets.getContent();
|
final List<Target> targetList = targets.getContent();
|
||||||
assertThat(targetList.size()).isEqualTo(5);
|
assertThat(targetList.size()).isEqualTo(5);
|
||||||
|
|
||||||
@@ -1028,7 +1029,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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() {
|
public void findRolloutGroupTargetsWithRsqlParam() {
|
||||||
|
|
||||||
final int amountTargetsForRollout = 15;
|
final int amountTargetsForRollout = 15;
|
||||||
@@ -1049,27 +1050,33 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
// Run here, because scheduler is disabled during tests
|
// Run here, because scheduler is disabled during tests
|
||||||
rolloutManagement.handleRollouts();
|
rolloutManagement.handleRollouts();
|
||||||
|
|
||||||
|
final Condition<String> targetBelongsInRollout = new Condition<>(s -> s.startsWith(rolloutName),
|
||||||
|
"Target belongs into rollout");
|
||||||
|
|
||||||
myRollout = rolloutManagement.findRolloutById(myRollout.getId()).get();
|
myRollout = rolloutManagement.findRolloutById(myRollout.getId()).get();
|
||||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
|
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
|
||||||
.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent();
|
.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent();
|
||||||
|
|
||||||
Page<Target> targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(),
|
Page<Target> targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(0).getId(),
|
||||||
rsqlParam, new OffsetBasedPageRequest(0, 100, new Sort(Direction.ASC, "controllerId")));
|
rsqlParam, new OffsetBasedPageRequest(0, 100));
|
||||||
final List<Target> targetlistGroup1 = targetPage.getContent();
|
final List<Target> targetlistGroup1 = targetPage.getContent();
|
||||||
assertThat(targetlistGroup1.size()).isEqualTo(5);
|
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,
|
targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(1).getId(), rsqlParam,
|
||||||
new OffsetBasedPageRequest(0, 100, new Sort(Direction.DESC, "controllerId")));
|
new OffsetBasedPageRequest(0, 100));
|
||||||
final List<Target> targetlistGroup2 = targetPage.getContent();
|
final List<Target> targetlistGroup2 = targetPage.getContent();
|
||||||
assertThat(targetlistGroup2.size()).isEqualTo(5);
|
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,
|
targetPage = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroups.get(2).getId(), rsqlParam,
|
||||||
new OffsetBasedPageRequest(0, 100, new Sort(Direction.ASC, "controllerId")));
|
new OffsetBasedPageRequest(0, 100));
|
||||||
final List<Target> targetlistGroup3 = targetPage.getContent();
|
final List<Target> targetlistGroup3 = targetPage.getContent();
|
||||||
assertThat(targetlistGroup3.size()).isEqualTo(5);
|
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);
|
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||||
|
|
||||||
final List<RolloutGroup> groups = rolloutGroupManagement
|
final List<RolloutGroup> groups = rolloutGroupManagement.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE)
|
||||||
.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent();
|
.getContent();
|
||||||
|
|
||||||
assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
||||||
assertThat(groups.get(0).getTotalTargets()).isEqualTo(1);
|
assertThat(groups.get(0).getTotalTargets()).isEqualTo(1);
|
||||||
@@ -1301,8 +1308,8 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||||
assertThat(myRollout.getTotalTargets()).isEqualTo(amountTargetsInGroup1and2 + amountTargetsInGroup1);
|
assertThat(myRollout.getTotalTargets()).isEqualTo(amountTargetsInGroup1and2 + amountTargetsInGroup1);
|
||||||
|
|
||||||
final List<RolloutGroup> groups = rolloutGroupManagement
|
final List<RolloutGroup> groups = rolloutGroupManagement.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE)
|
||||||
.findRolloutGroupsByRolloutId(myRollout.getId(), PAGE).getContent();
|
.getContent();
|
||||||
;
|
;
|
||||||
assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
||||||
assertThat(groups.get(0).getTotalTargets()).isEqualTo(amountTargetsInGroup1);
|
assertThat(groups.get(0).getTotalTargets()).isEqualTo(amountTargetsInGroup1);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.eclipse.hawkbit.cache.DefaultDownloadIdCache;
|
|||||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||||
import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter;
|
import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter;
|
||||||
|
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
@@ -75,6 +76,14 @@ import org.springframework.util.AntPathMatcher;
|
|||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
public class TestConfiguration implements AsyncConfigurer {
|
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
|
@Bean
|
||||||
public LockRegistry lockRegistry() {
|
public LockRegistry lockRegistry() {
|
||||||
return new DefaultLockRegistry();
|
return new DefaultLockRegistry();
|
||||||
|
|||||||
Reference in New Issue
Block a user