diff --git a/hawkbit-autoconfigure/pom.xml b/hawkbit-autoconfigure/pom.xml index 4e6b328b7..01b105170 100644 --- a/hawkbit-autoconfigure/pom.xml +++ b/hawkbit-autoconfigure/pom.xml @@ -41,10 +41,6 @@ true - - org.springframework - spring-context-support - io.protostuff protostuff-core diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java deleted file mode 100644 index 48f493ee7..000000000 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.autoconfigure.cache; - -import com.github.benmanes.caffeine.cache.Caffeine; -import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; -import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; -import org.eclipse.hawkbit.tenancy.TenantAware; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cache.caffeine.CaffeineCacheManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -/** - * A configuration for configuring the spring {@link CacheManager} for specific multi-tenancy caching. The caches between - * tenants must not interfere each other. - *

- * This is done by providing a special {@link TenantCacheManager} which generates a cache name included the current tenant. - */ -@Configuration -@EnableCaching -public class CacheAutoConfiguration { - - /** - * @return the default cache manager bean if none other cache manager is existing. - */ - @Bean - @ConditionalOnMissingBean - @Primary - TenantCacheManager cacheManager( - @Qualifier("directCacheManager") final CacheManager directCacheManager, final TenantAware tenantAware) { - return new TenantAwareCacheManager(directCacheManager, tenantAware); - } - - /** - * A separate configuration of the direct cache manager for the {@link TenantAwareCacheManager} that it can get overridden by another - * configuration. - */ - @Configuration - @EnableConfigurationProperties(CacheProperties.class) - static class DirectCacheManagerConfiguration { - - /** - * @return the direct cache manager to access without tenant aware check, cause in sometimes it's necessary to access the cache - * directly without having the current tenant, e.g. initial creation of tenant - */ - @Bean(name = "directCacheManager") - @ConditionalOnMissingBean(name = "directCacheManager") - public CacheManager directCacheManager(final CacheProperties cacheProperties) { - final CaffeineCacheManager cacheManager = new CaffeineCacheManager(); - - if (cacheProperties.getTtl() > 0) { - cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(cacheProperties.getTtl(), cacheProperties.getTtlUnit())); - } - - return cacheManager; - } - } -} \ No newline at end of file diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java deleted file mode 100644 index 6431765ec..000000000 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.autoconfigure.cache; - -import java.util.concurrent.TimeUnit; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Properties for configuring the cache within a cluster. The TTL (time to live) is used for the lifetime limit of data in caches. - * After lifetime the data gets reloaded out of the database. - */ -@Data -@ConfigurationProperties("hawkbit.cache") -public class CacheProperties { - - /** - * TTL for cached entries in millis. - */ - private int ttl = 10_000; // default TTL - 10 seconds - - /** - * Initial delay in millis - */ - private int initialDelay; - - public final TimeUnit getTtlUnit() { - return TimeUnit.MILLISECONDS; - } -} \ No newline at end of file diff --git a/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 91a1a0602..06ee8bb7f 100644 --- a/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,5 +1,4 @@ org.eclipse.hawkbit.autoconfigure.artifact.PropertyBasedArtifactUrlResolverAutoConfiguration -org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration org.eclipse.hawkbit.autoconfigure.repository.event.EventPublisherAutoConfiguration org.eclipse.hawkbit.autoconfigure.repository.JpaRepositoryAutoConfiguration org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration diff --git a/hawkbit-core/pom.xml b/hawkbit-core/pom.xml index a1f473420..ff15849da 100644 --- a/hawkbit-core/pom.xml +++ b/hawkbit-core/pom.xml @@ -38,12 +38,14 @@ org.springframework spring-web - compile org.springframework.data spring-data-commons - compile + + + org.springframework + spring-context-support @@ -53,12 +55,14 @@ jakarta.servlet jakarta.servlet-api - compile io.micrometer micrometer-core - compile + + + com.github.ben-manes.caffeine + caffeine diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareCacheManager.java new file mode 100644 index 000000000..52e3fbe5b --- /dev/null +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareCacheManager.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.tenancy; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +import com.github.benmanes.caffeine.cache.Caffeine; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import org.eclipse.hawkbit.tenancy.TenantAware.TenantResolver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.core.env.Environment; +import org.springframework.lang.Nullable; + +/** + * A spring Cache Manager that handles the multi tenancy. + *

+ */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings("java:S6548") // singleton holder ensures static access to spring resources in some places +public class TenantAwareCacheManager implements CacheManager { + + private static final String CONFIG_PREFIX = "hawkbit.cache."; + private static final String CONFIG_SPEC = "spec"; + + private static final TenantAwareCacheManager SINGLETON = new TenantAwareCacheManager(); + + private CacheManager globalCacheManager; + private final Map tenant2CacheManager = new ConcurrentHashMap<>(); + + private TenantResolver resolver; + private Environment env; + + // default caffeine cache spec - see com.github.benmanes.caffeine.cache.CaffeineSpec javadoc for format details + private String defaultSpec; + + public static TenantAwareCacheManager getInstance() { + return SINGLETON; + } + + @Autowired + public void init(final TenantResolver resolver, final Environment env) { + this.resolver = resolver; + this.env = env; + defaultSpec = env.resolvePlaceholders("${" + CONFIG_PREFIX + CONFIG_SPEC + ":expireAfterWrite=${hawkbit.cache.ttl:10s}}"); + globalCacheManager = new TenantCacheManager(null); + } + + @Nullable + @Override + public Cache getCache(@NonNull final String name) { + return Optional.ofNullable(resolver.resolveTenant()) + .map(currentTenant -> tenant2CacheManager.computeIfAbsent(currentTenant, TenantCacheManager::new)) + .orElse(globalCacheManager) + .getCache(name); + } + + @NonNull + @Override + public Collection getCacheNames() { + final String currentTenant = resolver.resolveTenant(); + if (currentTenant == null) { + return globalCacheManager.getCacheNames(); + } else { + final CacheManager cacheManager = tenant2CacheManager.get(currentTenant); + return cacheManager == null ? List.of() : cacheManager.getCacheNames(); + } + } + + public void evictTenant(final String tenant) { + if (tenant == null) { + globalCacheManager.getCacheNames().forEach(name -> Optional.ofNullable(globalCacheManager.getCache(name)).ifPresent(Cache::clear)); + } else { + tenant2CacheManager.remove(tenant); + } + } + + private class TenantCacheManager implements CacheManager { + + private final String tenant; + private final Map caches = new ConcurrentHashMap<>(); + + private TenantCacheManager(final String tenant) { + this.tenant = tenant; + } + + @Nullable + @Override + public Cache getCache(@NonNull final String name) { + return caches.computeIfAbsent(name, n -> { + // try tenant and cache specific config first + String spec = env.getProperty(CONFIG_PREFIX + (tenant == null ? "" : tenant + ".") + name + "." + CONFIG_SPEC); + if (spec == null) { + // try cache specific config next + spec = env.getProperty(CONFIG_PREFIX + name + "." + CONFIG_SPEC); + if (spec == null) { + spec = defaultSpec; + } + } + return new CaffeineCache(n, Caffeine.from(spec).build(), false); + }); + } + + @NonNull + @Override + public Collection getCacheNames() { + return caches.keySet(); + } + } +} \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantCacheConfiguration.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantCacheConfiguration.java new file mode 100644 index 000000000..65f5d95e8 --- /dev/null +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantCacheConfiguration.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.tenancy; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TenantCacheConfiguration { + + @Bean + TenantAwareCacheManager cacheManager() { + return TenantAwareCacheManager.getInstance(); + } +} \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java deleted file mode 100644 index cbd75a733..000000000 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.tenancy.cache; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; - -import lombok.NonNull; -import org.eclipse.hawkbit.tenancy.TenantAware; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.lang.Nullable; - -/** - * A {@link CacheManager} delegator which wraps the {@link CacheManager#getCache(String)} and {@link CacheManager#getCacheNames()} - * to include the {@link TenantAware#getCurrentTenant()} when accessing a cache, so caches are seperated. - *

- * Additionally, it also provides functionality to retrieve all caches overall tenants at once, for monitoring and system access. - */ -public class TenantAwareCacheManager implements TenantCacheManager { - - private static final String TENANT_CACHE_DELIMITER = "|"; - - private final CacheManager delegate; - private final TenantAware tenantAware; - - /** - * Constructor. - * - * @param delegate the {@link CacheManager} to delegate to. - * @param tenantAware the tenant aware to retrieve the current tenant - */ - public TenantAwareCacheManager(final CacheManager delegate, final TenantAware tenantAware) { - this.delegate = delegate; - this.tenantAware = tenantAware; - } - - @Nullable - @Override - public Cache getCache(@NonNull final String name) { - final String currentTenant = tenantAware.getCurrentTenant(); - if (isTenantInvalid(currentTenant)) { - return null; - } - - return delegate.getCache(buildKey(currentTenant.toUpperCase(), name)); - } - - @NonNull - @Override - public Collection getCacheNames() { - final String currentTenant = tenantAware.getCurrentTenant(); - if (isTenantInvalid(currentTenant)) { - return Collections.emptyList(); - } - - return getCacheNames(currentTenant.toUpperCase()); - } - - @Override - public Cache getDirectCache(final String name) { - return delegate.getCache(name); - } - - @Override - public void evictCaches(final String tenant) { - getCacheNames(tenant).forEach( - cacheName -> Optional.ofNullable(delegate.getCache(buildKey(tenant, cacheName))).ifPresent(Cache::clear)); - } - - /** - * A direct-access for retrieving all cache names overall tenants. - * - * @return all cache names without tenant check - */ - public Collection getDirectCacheNames() { - return delegate.getCacheNames(); - } - - private static boolean isTenantInvalid(final String tenant) { - return tenant == null || tenant.contains(TENANT_CACHE_DELIMITER); - } - - private static String buildKey(final String tenant, final String cacheName) { - return tenant + TENANT_CACHE_DELIMITER + cacheName; - } - - private Collection getCacheNames(final String tenant) { - final String tenantWithDelimiter = tenant + TENANT_CACHE_DELIMITER; - return delegate.getCacheNames().parallelStream() - .filter(cacheName -> cacheName.startsWith(tenantWithDelimiter)) - .map(cacheName -> cacheName.substring(tenantWithDelimiter.length())) - .toList(); - } -} \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java deleted file mode 100644 index 8ef0db2de..000000000 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.tenancy.cache; - -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -/** - * A cache interface which handles multi tenancy. - */ -public interface TenantCacheManager extends CacheManager { - - /** - * A direct-access for retrieving the cache without including the current tenant key. This is necessary e.g. for retrieving caches not for - * the current tenant. - * - * @param name the name of the cache to retrieve directly - * @return the cache associated with the name without tenancy separation - */ - Cache getDirectCache(String name); - - /** - * Evicts all caches for a given tenant. All caches under a certain tenant gets evicted. - * - * @param tenant the tenant to evict caches - */ - void evictCaches(String tenant); -} \ No newline at end of file diff --git a/hawkbit-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hawkbit-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index b1f410d93..c4895c969 100644 --- a/hawkbit-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/hawkbit-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ +org.eclipse.hawkbit.tenancy.TenantCacheConfiguration org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration.WebConfig org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration.RepositoryConfig diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/AutoAssignExecutor.java similarity index 94% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/AutoAssignExecutor.java index e13b3dafa..fc0ece26a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/AutoAssignExecutor.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.autoassign; +package org.eclipse.hawkbit.repository; /** * An interface declaration which contains the check for the auto assignment logic. diff --git a/hawkbit-repository/hawkbit-repository-core/pom.xml b/hawkbit-repository/hawkbit-repository-core/pom.xml index 489522038..7aa469d50 100644 --- a/hawkbit-repository/hawkbit-repository-core/pom.xml +++ b/hawkbit-repository/hawkbit-repository-core/pom.xml @@ -32,10 +32,6 @@ org.apache.commons commons-text - - com.github.ben-manes.caffeine - caffeine - org.springframework spring-context-support 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 index 4a465c297..9ec8004db 100644 --- 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 @@ -17,9 +17,6 @@ import java.util.stream.Collectors; import jakarta.validation.constraints.NotNull; -import com.github.benmanes.caffeine.cache.Caffeine; -import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; -import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent; @@ -27,9 +24,9 @@ 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.TenantAwareCacheManager; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.cache.Cache; -import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.context.event.EventListener; /** @@ -39,35 +36,17 @@ 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 TenantCacheManager cacheManager; + private static final TenantAwareCacheManager CACHE_MANAGER = TenantAwareCacheManager.getInstance(); + 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 Caffeine cacheBuilder = Caffeine.newBuilder().maximumSize(size); - final CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(); - caffeineCacheManager.setCaffeine(cacheBuilder); - - this.cacheManager = new TenantAwareCacheManager(caffeineCacheManager, tenantAware); - } - - /** - * @param tenantAware to get current tenant - */ public RolloutStatusCache(final TenantAware tenantAware) { - this(tenantAware, DEFAULT_SIZE); + this.tenantAware = tenantAware; } /** - * Retrieves cached list of {@link TotalTargetCountActionStatus} of - * {@link Rollout}s. + * Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link Rollout}s. * * @param rollouts rolloutIds to retrieve cache entries for * @return map of cached entries @@ -77,8 +56,7 @@ public class RolloutStatusCache { } /** - * Retrieves cached list of {@link TotalTargetCountActionStatus} of - * {@link Rollout}s. + * Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link Rollout}s. * * @param rolloutId to retrieve cache entries for * @return map of cached entries @@ -88,8 +66,7 @@ public class RolloutStatusCache { } /** - * Retrieves cached list of {@link TotalTargetCountActionStatus} of - * {@link RolloutGroup}s. + * Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link RolloutGroup}s. * * @param rolloutGroups rolloutGroupsIds to retrieve cache entries for * @return map of cached entries @@ -99,8 +76,7 @@ public class RolloutStatusCache { } /** - * Retrieves cached list of {@link TotalTargetCountActionStatus} of - * {@link RolloutGroup}. + * Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link RolloutGroup}. * * @param groupId to retrieve cache entries for * @return map of cached entries @@ -120,8 +96,7 @@ public class RolloutStatusCache { } /** - * Put {@link TotalTargetCountActionStatus} for one {@link Rollout}s into - * cache. + * Put {@link TotalTargetCountActionStatus} for one {@link Rollout}s into cache. * * @param rolloutId the cache entries belong to * @param status list to cache @@ -131,8 +106,7 @@ public class RolloutStatusCache { } /** - * Put {@link TotalTargetCountActionStatus} for multiple - * {@link RolloutGroup}s into cache. + * Put {@link TotalTargetCountActionStatus} for multiple {@link RolloutGroup}s into cache. * * @param put map of cached entries */ @@ -141,8 +115,7 @@ public class RolloutStatusCache { } /** - * Put {@link TotalTargetCountActionStatus} for multiple - * {@link RolloutGroup}s into cache. + * Put {@link TotalTargetCountActionStatus} for multiple {@link RolloutGroup}s into cache. * * @param groupId the cache entries belong to * @param status list to cache @@ -154,52 +127,37 @@ public class RolloutStatusCache { @EventListener(classes = AbstractActionEvent.class) public void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) { if (event.getRolloutId() != null) { - final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME)); + final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME)); cache.evict(event.getRolloutId()); } if (event.getRolloutGroupId() != null) { - final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_GR_NAME)); + final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)); cache.evict(event.getRolloutGroupId()); } } @EventListener(classes = RolloutDeletedEvent.class) public void invalidateCachedTotalTargetCountOnRolloutDelete(final RolloutDeletedEvent event) { - final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME)); + final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME)); cache.evict(event.getEntityId()); } @EventListener(classes = RolloutGroupDeletedEvent.class) public void invalidateCachedTotalTargetCountOnRolloutGroupDelete(final RolloutGroupDeletedEvent event) { - final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_GR_NAME)); + final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)); cache.evict(event.getEntityId()); } @EventListener(classes = RolloutStoppedEvent.class) public void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) { - final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME)); + final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME)); cache.evict(event.getRolloutId()); - - for (final long groupId : event.getRolloutGroupIds()) { - final Cache groupCache = tenantAware.runAsTenant(event.getTenant(), - () -> cacheManager.getCache(CACHE_GR_NAME)); - groupCache.evict(groupId); - } + event.getRolloutGroupIds().forEach( + groupId -> tenantAware.runAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)).evict(groupId)); } - /** - * Evicts all caches for a given tenant. All caches under a certain tenant - * gets evicted. - * - * @param tenant the tenant to evict caches - */ - public void evictCaches(final String tenant) { - cacheManager.evictCaches(tenant); - } - - private @NotNull Map> retrieveFromCache(final List ids, - @NotNull final Cache cache) { + private @NotNull Map> retrieveFromCache(final List ids, @NotNull final Cache cache) { return ids.stream() .map(id -> cache.get(id, CachedTotalTargetCountActionStatus.class)) .filter(Objects::nonNull) @@ -208,11 +166,9 @@ public class RolloutStatusCache { private List retrieveFromCache(final Long id, @NotNull final Cache cache) { final CachedTotalTargetCountActionStatus cacheItem = cache.get(id, CachedTotalTargetCountActionStatus.class); - if (cacheItem == null) { return Collections.emptyList(); } - return cacheItem.status(); } @@ -226,11 +182,11 @@ public class RolloutStatusCache { } private @NotNull Cache getRolloutStatusCache() { - return Objects.requireNonNull(cacheManager.getCache(CACHE_RO_NAME), "Cache '" + CACHE_RO_NAME + "' is null!"); + return Objects.requireNonNull(CACHE_MANAGER.getCache(CACHE_RO_NAME), "Cache '" + CACHE_RO_NAME + "' is null!"); } private @NotNull Cache getGroupStatusCache() { - return Objects.requireNonNull(cacheManager.getCache(CACHE_GR_NAME), "Cache '" + CACHE_RO_NAME + "' is null!"); + return Objects.requireNonNull(CACHE_MANAGER.getCache(CACHE_GR_NAME), "Cache '" + CACHE_RO_NAME + "' is null!"); } private record CachedTotalTargetCountActionStatus(long id, List status) {} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties b/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties index 3138b26bb..271e41c69 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties +++ b/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties @@ -21,6 +21,13 @@ hawkbit.controller.minPollingTime=00:00:30 # pollingTime(@time=t) = (maintenanceStartTime - t)/maintenanceWindowPollCount hawkbit.controller.maintenanceWindowPollCount=3 +# Cache config +hawkbit.cache.ttl=10s +hawkbit.cache.spec=expireAfterAccess=${hawkbit.cache.ttl} +hawkbit.cache.RolloutStatus.spec=maximumSize=50000,expireAfterAccess=${hawkbit.cache.ttl} +hawkbit.cache.RolloutGroupStatus.spec=maximumSize=50000,expireAfterAccess=${hawkbit.cache.ttl} +# Cache config - END + # Attention: if you want to use a maximumPollingTime greater 23:59:59 you have to update the DurationField in the configuration window # Default tenant configuration - START diff --git a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitDefaultServiceExecutor.java b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitDefaultServiceExecutor.java deleted file mode 100644 index 69918b727..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitDefaultServiceExecutor.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.executor; - -import java.util.ArrayList; -import java.util.List; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * A Service which calls register runnable. This runnables will be executed after a successful spring transaction commit. - * The class is thread safe. - */ -@Slf4j -public class AfterTransactionCommitDefaultServiceExecutor implements AfterTransactionCommitExecutor { - - private static class TransactionSynchronizationImpl implements TransactionSynchronization { - - private final List afterCommitRunnables = new ArrayList<>(); - - @Override - // Exception squid:S1217 - Is aspectJ proxy - @SuppressWarnings({ "squid:S1217" }) - public void afterCommit() { - log.debug("Transaction successfully committed, executing {} runnables", afterCommitRunnables.size()); - for (final Runnable afterCommitRunnable : afterCommitRunnables) { - log.debug("Executing runnable {}", afterCommitRunnable); - try { - afterCommitRunnable.run(); - } catch (final RuntimeException e) { - log.error("Failed to execute runnable {}", afterCommitRunnable, e); - } - } - } - - @Override - @SuppressWarnings({ "squid:S1217" }) - public void afterCompletion(final int status) { - log.debug("Transaction completed after commit with status {}", status == TransactionSynchronization.STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK"); - } - - private void afterCommit(final Runnable runnable) { - afterCommitRunnables.add(runnable); - } - } - - @Override - // Exception squid:S1217 - we want to run this synchronous - @SuppressWarnings("squid:S1217") - public void afterCommit(final Runnable runnable) { - log.debug("Submitting new runnable {} to run after transaction commit", runnable); - if (TransactionSynchronizationManager.isSynchronizationActive()) { - TransactionSynchronizationManager.getSynchronizations().stream().filter(TransactionSynchronizationImpl.class::isInstance) - .map(TransactionSynchronizationImpl.class::cast).findAny().orElseGet(() -> { - final TransactionSynchronizationImpl newTS = new TransactionSynchronizationImpl(); - TransactionSynchronizationManager.registerSynchronization(newTS); - return newTS; - }).afterCommit(runnable); - } else { - log.info("Transaction synchronization is NOT ACTIVE/ INACTIVE. Executing right now runnable {}", runnable); - runnable.run(); - } - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java index d902085b3..12b0a5d70 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java @@ -9,18 +9,66 @@ */ package org.eclipse.hawkbit.repository.jpa.executor; -/** - * A interface to register a runnable, which will be executed after a successful - * spring transaction. - */ -@FunctionalInterface -public interface AfterTransactionCommitExecutor { +import java.util.ArrayList; +import java.util.List; - /** - * Register a runnable which will be executed after a successful spring - * transaction. - * - * @param runnable the after commit runnable - */ - void afterCommit(Runnable runnable); +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +/** + * A hook to register a runnable, which will be executed after a successful spring transaction. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Slf4j +public class AfterTransactionCommitExecutor { + + // Exception squid:S1217 - we want to run this synchronous + @SuppressWarnings("squid:S1217") + public static void afterCommit(final Runnable runnable) { + log.debug("Submitting new runnable {} to run after transaction commit", runnable); + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.getSynchronizations().stream().filter(TransactionSynchronizationImpl.class::isInstance) + .map(TransactionSynchronizationImpl.class::cast).findAny().orElseGet(() -> { + final TransactionSynchronizationImpl newTS = new TransactionSynchronizationImpl(); + TransactionSynchronizationManager.registerSynchronization(newTS); + return newTS; + }).afterCommit(runnable); + } else { + log.info("Transaction synchronization is NOT ACTIVE/ INACTIVE. Executing right now runnable {}", runnable); + runnable.run(); + } + } + + private static class TransactionSynchronizationImpl implements TransactionSynchronization { + + private final List afterCommitRunnables = new ArrayList<>(); + + @Override + // Exception squid:S1217 - Is aspectJ proxy + @SuppressWarnings({ "squid:S1217" }) + public void afterCommit() { + log.debug("Transaction successfully committed, executing {} runnables", afterCommitRunnables.size()); + for (final Runnable afterCommitRunnable : afterCommitRunnables) { + log.debug("Executing runnable {}", afterCommitRunnable); + try { + afterCommitRunnable.run(); + } catch (final RuntimeException e) { + log.error("Failed to execute runnable {}", afterCommitRunnable, e); + } + } + } + + @Override + @SuppressWarnings({ "squid:S1217" }) + public void afterCompletion(final int status) { + log.debug("Transaction completed after commit with status {}", status == TransactionSynchronization.STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK"); + } + + private void afterCommit(final Runnable runnable) { + afterCommitRunnables.add(runnable); + } + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java deleted file mode 100644 index d02a90c19..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.model.helper; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * A singleton bean which holds the {@link AfterTransactionCommitExecutor} to provide it to in beans not instantiated by spring e.g. JPA - * entities which cannot be autowired. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -@SuppressWarnings("java:S6548") // java:S6548 - singleton holder ensures static access to spring resources in some places -public final class AfterTransactionCommitExecutorHolder { - - private static final AfterTransactionCommitExecutorHolder SINGLETON = new AfterTransactionCommitExecutorHolder(); - - @Getter - private AfterTransactionCommitExecutor afterCommit; - - /** - * @return the cache manager holder singleton instance - */ - public static AfterTransactionCommitExecutorHolder getInstance() { - return SINGLETON; - } - - @Autowired // spring setter injection - public void setAfterTransactionCommitExecutor(final AfterTransactionCommitExecutor afterCommit) { - this.afterCommit = afterCommit; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 003ffe0cf..9172f7c01 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -28,7 +28,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.springframework.data.annotation.CreatedBy; @@ -199,7 +199,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { protected static void doNotify(final Runnable runnable) { // fire events onl AFTER transaction commit - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable); + AfterTransactionCommitExecutor.afterCommit(runnable); } protected boolean isController() { diff --git a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index f006881b9..e70aabdb6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -28,7 +28,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.springframework.data.annotation.CreatedBy; @@ -199,7 +199,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { protected static void doNotify(final Runnable runnable) { // fire events onl AFTER transaction commit - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable); + AfterTransactionCommitExecutor.afterCommit(runnable); } protected boolean isController() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java index 46170cab0..20c4dfc63 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java @@ -19,11 +19,11 @@ import jakarta.validation.Validation; import io.micrometer.core.instrument.MeterRegistry; import org.aopalliance.intercept.MethodInvocation; -import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryption; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionSecretsStorage; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.ActionFields; +import org.eclipse.hawkbit.repository.AutoAssignExecutor; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; import org.eclipse.hawkbit.repository.QueryField; @@ -32,16 +32,12 @@ import org.eclipse.hawkbit.repository.RepositoryConfiguration; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutExecutor; -import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutHandler; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; -import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder; @@ -49,16 +45,12 @@ import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler; -import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignChecker; -import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoActionCleanup; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoCleanupScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask; import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository; import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitDefaultServiceExecutor; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; @@ -67,7 +59,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison; @@ -79,13 +70,11 @@ import org.eclipse.hawkbit.repository.jpa.repository.ArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; -import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; -import org.eclipse.hawkbit.repository.jpa.repository.RolloutTargetGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; -import org.eclipse.hawkbit.repository.jpa.rollout.RolloutScheduler; +import org.eclipse.hawkbit.repository.jpa.scheduler.RolloutScheduler; import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAction; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator; @@ -94,11 +83,12 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRollou import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser; +import org.eclipse.hawkbit.repository.jpa.scheduler.AutoAssignScheduler; +import org.eclipse.hawkbit.repository.jpa.scheduler.JpaAutoAssignExecutor; +import org.eclipse.hawkbit.repository.jpa.scheduler.JpaRolloutHandler; import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; @@ -151,10 +141,12 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess @EnableScheduling @EnableRetry @EntityScan("org.eclipse.hawkbit.repository.jpa.model") -@ComponentScan("org.eclipse.hawkbit.repository.jpa.management") +@ComponentScan({ "org.eclipse.hawkbit.repository.jpa.management", "org.eclipse.hawkbit.repository.jpa.scheduler" }) @PropertySource("classpath:/hawkbit-jpa-defaults.properties") -@Import({ JpaConfiguration.class, RepositoryConfiguration.class, LockProperties.class, DataSourceAutoConfiguration.class, - SystemManagementCacheKeyGenerator.class }) +@Import({ + RepositoryConfiguration.class, + JpaConfiguration.class, LockProperties.class, SystemManagementCacheKeyGenerator.class, + DataSourceAutoConfiguration.class}) @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class JpaRepositoryConfiguration { @@ -275,12 +267,6 @@ public class JpaRepositoryConfiguration { return new SystemManagementCacheKeyGenerator(tenantAware); } - @Bean - @ConditionalOnMissingBean - AfterTransactionCommitDefaultServiceExecutor afterTransactionCommitDefaultServiceExecutor() { - return new AfterTransactionCommitDefaultServiceExecutor(); - } - @Bean @ConditionalOnMissingBean QuotaManagement staticQuotaManagement(final HawkbitSecurityProperties securityProperties) { @@ -347,14 +333,6 @@ public class JpaRepositoryConfiguration { return EntityInterceptorHolder.getInstance(); } - /** - * @return the singleton instance of the {@link AfterTransactionCommitExecutorHolder} - */ - @Bean - AfterTransactionCommitExecutorHolder afterTransactionCommitExecutorHolder() { - return AfterTransactionCommitExecutorHolder.getInstance(); - } - /** * @return {@link ExceptionMappingAspectHandler} aspect bean */ @@ -371,24 +349,6 @@ public class JpaRepositoryConfiguration { return new JpaRolloutHandler(tenantAware, rolloutManagement, rolloutExecutor, lockRegistry, txManager, meterRegistry); } - @Bean - @ConditionalOnMissingBean - RolloutExecutor rolloutExecutor( - final ActionRepository actionRepository, final RolloutGroupRepository rolloutGroupRepository, - final RolloutTargetGroupRepository rolloutTargetGroupRepository, - final RolloutRepository rolloutRepository, final TargetManagement targetManagement, - final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement, - final RolloutManagement rolloutManagement, final QuotaManagement quotaManagement, - final RolloutGroupEvaluationManager evaluationManager, final RolloutApprovalStrategy rolloutApprovalStrategy, - final EntityManager entityManager, final PlatformTransactionManager txManager, - final AfterTransactionCommitExecutor afterCommit, - final TenantAware tenantAware, final ContextAware contextAware, final RepositoryProperties repositoryProperties) { - return new JpaRolloutExecutor(actionRepository, rolloutGroupRepository, rolloutTargetGroupRepository, - rolloutRepository, targetManagement, deploymentManagement, rolloutGroupManagement, rolloutManagement, - quotaManagement, evaluationManager, rolloutApprovalStrategy, entityManager, txManager, afterCommit, - tenantAware, contextAware, repositoryProperties); - } - /** * {@link DefaultRolloutApprovalStrategy} bean. * @@ -425,25 +385,6 @@ public class JpaRepositoryConfiguration { return new JpaEventEntityManager(aware, entityManager); } - /** - * {@link AutoAssignChecker} bean. - * - * @param targetFilterQueryManagement to get all target filter queries - * @param targetManagement to get targets - * @param deploymentManagement to assign distribution sets to targets - * @param transactionManager to run transactions - * @return a new {@link AutoAssignChecker} - */ - @Bean - @ConditionalOnMissingBean - AutoAssignExecutor autoAssignExecutor( - final TargetFilterQueryManagement targetFilterQueryManagement, - final TargetManagement targetManagement, - final DeploymentManagement deploymentManagement, - final PlatformTransactionManager transactionManager, final ContextAware contextAware) { - return new AutoAssignChecker(targetFilterQueryManagement, targetManagement, deploymentManagement, transactionManager, contextAware); - } - /** * {@link AutoAssignScheduler} bean. *

@@ -454,7 +395,7 @@ public class JpaRepositoryConfiguration { * @param systemSecurityContext to run as system * @param autoAssignExecutor to run a check as tenant * @param lockRegistry to lock the tenant for auto assignment - * @return a new {@link AutoAssignChecker} + * @return a new {@link JpaAutoAssignExecutor} */ @Bean @ConditionalOnMissingBean diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java index 9a0dbd935..af57bbae3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; + import java.util.Collection; import java.util.Collections; import java.util.List; @@ -27,7 +29,6 @@ import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement.MaxAssignmentsExceededInfo; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; @@ -59,7 +60,6 @@ import org.springframework.util.StringUtils; public abstract class AbstractDsAssignmentStrategy { protected final TargetRepository targetRepository; - protected final AfterTransactionCommitExecutor afterCommit; protected final ActionRepository actionRepository; private final ActionStatusRepository actionStatusRepository; @@ -72,13 +72,11 @@ public abstract class AbstractDsAssignmentStrategy { @SuppressWarnings("java:S107") AbstractDsAssignmentStrategy( final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties, final Consumer maxAssignmentExceededHandler) { this.targetRepository = targetRepository; - this.afterCommit = afterCommit; this.actionRepository = actionRepository; this.actionStatusRepository = actionStatusRepository; this.quotaManagement = quotaManagement; @@ -133,7 +131,7 @@ public abstract class AbstractDsAssignmentStrategy { } protected void sendTargetUpdatedEvent(final JpaTarget target) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetUpdatedEvent(target))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetUpdatedEvent(target))); } /** @@ -209,8 +207,7 @@ public abstract class AbstractDsAssignmentStrategy { * @param action the action of the assignment */ protected void cancelAssignDistributionSetEvent(final Action action) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new CancelTargetAssignmentEvent(action))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new CancelTargetAssignmentEvent(action))); } protected boolean isMultiAssignmentsEnabled() { @@ -279,8 +276,8 @@ public abstract class AbstractDsAssignmentStrategy { return; } final String tenant = actions.get(0).getTenant(); - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new CancelTargetAssignmentEvent(tenant, actions))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent( + new CancelTargetAssignmentEvent(tenant, actions))); } private void assertActionsPerTargetQuota(final Target target) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java index 793652c57..cdbaaf688 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; + import java.io.IOException; import java.io.InputStream; import java.util.Optional; @@ -38,7 +40,6 @@ import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.repository.ArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.specifications.ArtifactSpecifications; @@ -185,7 +186,7 @@ public class JpaArtifactManagement implements ArtifactManagement { artifactRepository.deleteById(id); final String sha1Hash = toDelete.getSha1Hash(); - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> clearArtifactBinary(sha1Hash)); + afterCommit(() -> clearArtifactBinary(sha1Hash)); } /** @@ -202,11 +203,10 @@ public class JpaArtifactManagement implements ArtifactManagement { void clearArtifactBinary(final String sha1Hash) { DeploymentHelper.runInNewTransaction(txManager, "clearArtifactBinary", status -> { // countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse will skip ACM checks and will return total count as it should be - if (artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash, - tenantAware.getCurrentTenant()) <= 0) { // 1 artifact is the one being deleted! + if (artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash, tenantAware.getCurrentTenant()) <= 0) { // removes the real artifact ONLY AFTER the delete of artifact or software module // in local history has passed successfully (caller has permission and no errors) - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> { + afterCommit(() -> { try { log.debug("deleting artifact from repository {}", sha1Hash); artifactStorage.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index cdfe3f07e..d8ac1d21f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -9,6 +9,7 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED; import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_MAX_KEY_SIZE; @@ -70,7 +71,6 @@ import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTarge import org.eclipse.hawkbit.repository.jpa.Jpa; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -153,7 +153,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont private final Duration maxPollingTime; private final PlatformTransactionManager txManager; private final EntityManager entityManager; - private final AfterTransactionCommitExecutor afterCommit; private final SystemSecurityContext systemSecurityContext; private final TenantAware tenantAware; @@ -168,7 +167,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont final DistributionSetManagement distributionSetManagement, final TenantConfigurationManagement tenantConfigurationManagement, final ControllerPollProperties controllerPollProperties, final PlatformTransactionManager txManager, final EntityManager entityManager, - final AfterTransactionCommitExecutor afterCommit, final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final ScheduledExecutorService executorService) { super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); @@ -190,7 +188,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont : DurationHelper.fromString(controllerPollProperties.getMaxPollingTime()); this.txManager = txManager; this.entityManager = entityManager; - this.afterCommit = afterCommit; this.systemSecurityContext = systemSecurityContext; this.tenantAware = tenantAware; @@ -676,9 +673,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } final Target result = targetRepository.save(jpaTarget); - - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetPollEvent(result))); - + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetPollEvent(result))); return result; } @@ -726,7 +721,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont pollChunks.forEach(chunk -> { setLastTargetQuery(tenant, System.currentTimeMillis(), chunk); - chunk.forEach(controllerId -> afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() + chunk.forEach(controllerId -> afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() .publishEvent(new TargetPollEvent(controllerId, tenant)))); }); @@ -787,7 +782,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont toUpdate.setUpdateStatus(TargetUpdateStatus.REGISTERED); } toUpdate.setLastTargetQuery(System.currentTimeMillis()); - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetPollEvent(toUpdate))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetPollEvent(toUpdate))); return targetRepository.save(toUpdate); } return toUpdate; @@ -926,8 +921,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } private void cancelAssignDistributionSetEvent(final Action action) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new CancelTargetAssignmentEvent(action))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new CancelTargetAssignmentEvent(action))); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index cd40ae50d..15f754638 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -57,7 +57,6 @@ import org.eclipse.hawkbit.repository.jpa.Jpa; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -151,7 +150,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl protected JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository, final JpaDistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, - final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager, + final PlatformTransactionManager txManager, final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware auditorAware, final JpaProperties jpaProperties, final RepositoryProperties repositoryProperties) { @@ -166,10 +165,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl maxAssignmentsExceededInfo.targetId, maxAssignmentsExceededInfo.requested, maxAssignmentsExceededInfo.quotaExceededException); - onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository, + onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties, maxAssignmentsExceededHandler); - offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository, + offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties, maxAssignmentsExceededHandler); this.tenantConfigurationManagement = tenantConfigurationManagement; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index 68f527438..eba545229 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -52,7 +54,6 @@ import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.jpa.Jpa; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -60,13 +61,13 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction; -import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; @@ -85,8 +86,8 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.security.SystemSecurityContext; -import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; @@ -121,7 +122,7 @@ public class JpaRolloutManagement implements RolloutManagement { RolloutStatus.PAUSED, RolloutStatus.APPROVAL_DENIED); @Value("${hawkbit.repository.jpa.management.rollout.max.actions.per.transaction:5000}") - private int MAX_ACTIONS; + private int maxActions; private final EntityManager entityManager; private final RolloutRepository rolloutRepository; @@ -136,7 +137,6 @@ public class JpaRolloutManagement implements RolloutManagement { private final TenantAware tenantAware; private final TenantConfigurationManagement tenantConfigurationManagement; private final QuotaManagement quotaManagement; - private final AfterTransactionCommitExecutor afterCommit; private final SystemSecurityContext systemSecurityContext; private final ContextAware contextAware; private final RepositoryProperties repositoryProperties; @@ -157,7 +157,6 @@ public class JpaRolloutManagement implements RolloutManagement { final TenantAware tenantAware, final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, - final AfterTransactionCommitExecutor afterCommit, final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final RepositoryProperties repositoryProperties) { this.entityManager = entityManager; @@ -173,12 +172,11 @@ public class JpaRolloutManagement implements RolloutManagement { this.tenantAware = tenantAware; this.tenantConfigurationManagement = tenantConfigurationManagement; this.quotaManagement = quotaManagement; - this.afterCommit = afterCommit; this.systemSecurityContext = systemSecurityContext; this.contextAware = contextAware; this.repositoryProperties = repositoryProperties; - this.onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository, + this.onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties, null); } @@ -187,7 +185,7 @@ public class JpaRolloutManagement implements RolloutManagement { } public void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() .publishEvent(new RolloutGroupCreatedEvent(group, rollout.getId()))); } @@ -524,7 +522,7 @@ public class JpaRolloutManagement implements RolloutManagement { ActionSpecifications .byRolloutIdAndActiveAndStatusIsNot(rollout.getId(), List.of(Action.Status.CANCELING)), // avoid cancelling state here, because it is count as still active - Pageable.ofSize(MAX_ACTIONS)) + Pageable.ofSize(maxActions)) .getContent(); log.info("Found {} active actions for rollout {}, performing soft cancel.", actions.size(), rollout.getId()); @@ -535,7 +533,7 @@ public class JpaRolloutManagement implements RolloutManagement { } private void forceQuitActionsOfRollout(final Rollout rollout) { - final List actions = findActiveActionsForRollout(rollout.getId(), Pageable.ofSize(MAX_ACTIONS)) + final List actions = findActiveActionsForRollout(rollout.getId(), Pageable.ofSize(maxActions)) .getContent(); log.info("Found {} active actions for rollout {}", actions.size(), rollout.getId()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java index 151e50ee2..cb17fc992 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; import java.util.Collection; import java.util.Collections; @@ -33,7 +34,6 @@ import org.eclipse.hawkbit.repository.exception.LockedException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; @@ -195,8 +195,7 @@ public class JpaSoftwareModuleManagement extends jpaRepository.getAccessController() .ifPresent(accessController -> accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); final Set sha1Hashes = swModule.getArtifacts().stream().map(Artifact::getSha1Hash).collect(Collectors.toSet()); - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit() - .afterCommit(() -> sha1Hashes.forEach(((JpaArtifactManagement) artifactManagement)::clearArtifactBinary)); + afterCommit(() -> sha1Hashes.forEach(((JpaArtifactManagement) artifactManagement)::clearArtifactBinary)); } private void assertDistributionSetExists(final long distributionSetId) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java index b48184005..6dcd954de 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java @@ -16,9 +16,8 @@ import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.artifact.ArtifactStorage; -import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; +import org.eclipse.hawkbit.tenancy.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -98,8 +97,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst private final SystemSecurityContext systemSecurityContext; private final TenantAware tenantAware; private final PlatformTransactionManager txManager; - private final TenantCacheManager cacheManager; - private final RolloutStatusCache rolloutStatusCache; private final EntityManager entityManager; private final RepositoryProperties repositoryProperties; @@ -116,7 +113,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst final TenantConfigurationRepository tenantConfigurationRepository, final TenantMetaDataRepository tenantMetaDataRepository, final TenantStatsManagement systemStatsManagement, final SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator, final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final PlatformTransactionManager txManager, - final TenantCacheManager cacheManager, final RolloutStatusCache rolloutStatusCache, final EntityManager entityManager, final RepositoryProperties repositoryProperties, final JpaProperties properties) { this.targetRepository = targetRepository; @@ -136,8 +132,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst this.systemSecurityContext = systemSecurityContext; this.tenantAware = tenantAware; this.txManager = txManager; - this.cacheManager = cacheManager; - this.rolloutStatusCache = rolloutStatusCache; this.entityManager = entityManager; this.repositoryProperties = repositoryProperties; @@ -166,8 +160,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } final String tenant = t.toUpperCase(); - cacheManager.evictCaches(tenant); - rolloutStatusCache.evictCaches(tenant); + TenantAwareCacheManager.getInstance().evictTenant(tenant); tenantAware.runAsTenant(tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "deleteTenant", status -> { tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant); tenantConfigurationRepository.deleteByTenant(tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java index 78fb643d4..74fb3647e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java @@ -32,6 +32,7 @@ import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.TargetType; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; +import org.springframework.cache.annotation.Cacheable; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; @@ -50,6 +51,8 @@ public class JpaTargetTypeManagement extends AbstractJpaRepositoryManagement implements TargetTypeManagement{ + private static final String CACHE_TARGET_TYPE_NAME = "targetType"; + private final TargetRepository targetRepository; private final DistributionSetTypeRepository distributionSetTypeRepository; private final QuotaManagement quotaManagement; @@ -76,6 +79,7 @@ public class JpaTargetTypeManagement } @Override + @Cacheable(value = CACHE_TARGET_TYPE_NAME, key = "#key") public Optional findByKey(final String key) { return jpaRepository.findOne(TargetTypeSpecification.hasKey(key)).map(TargetType.class::cast); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index f90030b6a..b0124e401 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_GATEWAY_SECURITY_TOKEN; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.BATCH_ASSIGNMENTS_ENABLED; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED; @@ -37,7 +38,6 @@ import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException; import org.eclipse.hawkbit.repository.exception.TenantConfigurationValueChangeNotAllowedException; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration; import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; @@ -48,13 +48,13 @@ import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.eclipse.hawkbit.tenancy.TenantAwareCacheManager; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.PollingTime; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationContext; @@ -79,28 +79,24 @@ import org.springframework.validation.annotation.Validated; @ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "tenant-configuration-management" }, matchIfMissing = true) public class JpaTenantConfigurationManagement implements TenantConfigurationManagement { + private static final String CACHE_TENANT_CONFIGURATION_NAME = "tenantConfiguration"; private static final ConfigurableConversionService CONVERSION_SERVICE = new DefaultConversionService(); private final TenantConfigurationRepository tenantConfigurationRepository; private final TenantConfigurationProperties tenantConfigurationProperties; private final ApplicationContext applicationContext; - private final CacheManager cacheManager; - private final AfterTransactionCommitExecutor afterCommitExecutor; public JpaTenantConfigurationManagement( final TenantConfigurationRepository tenantConfigurationRepository, final TenantConfigurationProperties tenantConfigurationProperties, - final CacheManager cacheManager, final AfterTransactionCommitExecutor afterCommitExecutor, final ApplicationContext applicationContext) { this.tenantConfigurationRepository = tenantConfigurationRepository; this.tenantConfigurationProperties = tenantConfigurationProperties; - this.cacheManager = cacheManager; - this.afterCommitExecutor = afterCommitExecutor; this.applicationContext = applicationContext; } @Override - @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") + @CacheEvict(value = CACHE_TENANT_CONFIGURATION_NAME, key = "#configurationKeyName") @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) @@ -114,8 +110,8 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Map> addOrUpdateConfiguration(final Map configurations) { // Register a callback to be invoked after the transaction is committed - for cache eviction - afterCommitExecutor.afterCommit(() -> { - final Cache cache = cacheManager.getCache("tenantConfiguration"); + afterCommit(() -> { + final Cache cache = TenantAwareCacheManager.getInstance().getCache(CACHE_TENANT_CONFIGURATION_NAME); if (cache != null) { configurations.keySet().forEach(cache::evict); } @@ -125,7 +121,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana } @Override - @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") + @CacheEvict(value = CACHE_TENANT_CONFIGURATION_NAME, key = "#configurationKeyName") @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) @@ -135,7 +131,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana @Override // TODO - check if cache works -// @Cacheable(value = "tenantConfiguration", key = "#configurationKeyName") +// @Cacheable(value = CACHE_TENANT_CONFIGURATION_NAME, key = "#configurationKeyName") public TenantConfigurationValue getConfigurationValue(final String configurationKeyName) { checkAccess(configurationKeyName); @@ -145,7 +141,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana } @Override - @Cacheable(value = "tenantConfiguration", key = "#configurationKeyName") + @Cacheable(value = CACHE_TENANT_CONFIGURATION_NAME, key = "#configurationKeyName") public TenantConfigurationValue getConfigurationValue( final String configurationKeyName, final Class propertyType) { checkAccess(configurationKeyName); @@ -163,8 +159,8 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana final TenantConfigurationKey key = tenantConfigurationProperties.fromKeyName(configurationKeyName); if (!key.getDataType().isAssignableFrom(propertyType)) { - throw new TenantConfigurationValidatorException(String.format( - "Cannot parse the database value of type %s into the type %s.", key.getDataType(), propertyType)); + throw new TenantConfigurationValidatorException( + String.format("Cannot parse the database value of type %s into the type %s.", key.getDataType(), propertyType)); } return CONVERSION_SERVICE.convert(key.getDefaultValue(), propertyType); @@ -372,7 +368,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana } private void evictCacheEntryByKeyIfPresent(final String key) { - final Cache cache = cacheManager.getCache("tenantConfiguration"); + final Cache cache = TenantAwareCacheManager.getInstance().getCache(CACHE_TENANT_CONFIGURATION_NAME); if (cache != null) { cache.evictIfPresent(key); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java index 126f7056e..704e3e9db 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java @@ -45,12 +45,11 @@ class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { OfflineDsAssignmentStrategy( final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties, final Consumer maxAssignmentExceededHandler) { - super(targetRepository, afterCommit, actionRepository, actionStatusRepository, + super(targetRepository, actionRepository, actionStatusRepository, quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties, maxAssignmentExceededHandler); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java index 3e525e32f..b3060521c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; + import java.util.Collections; import java.util.List; import java.util.function.BooleanSupplier; @@ -26,7 +28,6 @@ import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEv import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement.MaxAssignmentsExceededInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -49,13 +50,13 @@ import org.springframework.util.CollectionUtils; */ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { - OnlineDsAssignmentStrategy(final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, + OnlineDsAssignmentStrategy( + final TargetRepository targetRepository, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties, final Consumer maxAssignmentExceededHandler) { - super(targetRepository, afterCommit, actionRepository, actionStatusRepository, + super(targetRepository, actionRepository, actionStatusRepository, quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties, maxAssignmentExceededHandler); } @@ -124,8 +125,8 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } @Override - public void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet set, final List> targetIds, - final String currentUser) { + public void setAssignedDistributionSetAndTargetStatus( + final JpaDistributionSet set, final List> targetIds, final String currentUser) { final long now = System.currentTimeMillis(); targetIds.forEach(targetIdsChunk -> { if (targetRepository.count(AccessController.Operation.UPDATE, @@ -223,10 +224,8 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { return; } - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new TargetAssignDistributionSetEvent( - tenant, distributionSetId, actions, - actions.get(0).isMaintenanceWindowAvailable()))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent( + new TargetAssignDistributionSetEvent(tenant, distributionSetId, actions, actions.get(0).isMaintenanceWindowAvailable()))); } /** @@ -237,8 +236,7 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { * @param actions assigned to the targets */ private void sendMultiActionCancelEvent(final String tenant, final List actions) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new MultiActionCancelEvent(tenant, actions))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new MultiActionCancelEvent(tenant, actions))); } /** @@ -248,7 +246,6 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { * @param actions assigned to the targets */ private void sendMultiActionAssignEvent(final String tenant, final List actions) { - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new MultiActionAssignEvent(tenant, actions))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new MultiActionAssignEvent(tenant, actions))); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java index a0cc76af7..85e9561ca 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java @@ -36,7 +36,6 @@ public interface TenantConfigurationRepository extends BaseEntityRepository { - final long startNanoT = System.nanoTime(); + final long startNanoT = System.nanoTime(); autoAssignExecutor.checkAllTargets(); meterRegistry .map(mReg -> mReg.timer( - "hawkbit.autoassign.executor", + "hawkbit.scheduler.executor", TenantMetricsConfiguration.TENANT_TAG, tenant)) .ifPresent(timer -> timer.record(System.nanoTime() - startNanoT, TimeUnit.NANOSECONDS)); }); } finally { lock.unlock(); meterRegistry - .map(mReg -> mReg.timer("hawkbit.autoassign.executor.all")) + .map(mReg -> mReg.timer("hawkbit.scheduler.executor.all")) .ifPresent(timer -> timer.record(System.nanoTime() - startNano, TimeUnit.NANOSECONDS)); log.debug("Auto assign scheduled execution has released lock and finished."); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutor.java similarity index 97% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutor.java index 864d4db36..132ca86ce 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutor.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa.autoassign; +package org.eclipse.hawkbit.repository.jpa.scheduler; import java.util.Collections; import java.util.List; @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; -import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; +import org.eclipse.hawkbit.repository.AutoAssignExecutor; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.model.Action; @@ -31,6 +31,7 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; @@ -43,7 +44,8 @@ import org.springframework.util.StringUtils; * query, that match the TFQ and that don't have the auto assign DS in their action history. */ @Slf4j -public class AutoAssignChecker implements AutoAssignExecutor { +@Service +public class JpaAutoAssignExecutor implements AutoAssignExecutor { /** * The message which is added to the action status when a distribution set is assigned to a target. @@ -62,7 +64,7 @@ public class AutoAssignChecker implements AutoAssignExecutor { private final PlatformTransactionManager transactionManager; private final ContextAware contextAware; - public AutoAssignChecker( + public JpaAutoAssignExecutor( final TargetFilterQueryManagement targetFilterQueryManagement, final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, final PlatformTransactionManager transactionManager, final ContextAware contextAware) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutExecutor.java similarity index 98% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutExecutor.java index 27e20d954..2e42d87a9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutExecutor.java @@ -7,7 +7,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa; +package org.eclipse.hawkbit.repository.jpa.scheduler; + +import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; @@ -37,7 +39,6 @@ import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.management.JpaRolloutManagement; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; @@ -69,6 +70,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionException; @@ -76,6 +78,7 @@ import org.springframework.transaction.TransactionException; * A Jpa implementation of {@link RolloutExecutor} */ @Slf4j +@Service public class JpaRolloutExecutor implements RolloutExecutor { /** @@ -112,7 +115,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { private final RolloutApprovalStrategy rolloutApprovalStrategy; private final EntityManager entityManager; private final PlatformTransactionManager txManager; - private final AfterTransactionCommitExecutor afterCommit; private final TenantAware tenantAware; private final ContextAware contextAware; private final RepositoryProperties repositoryProperties; @@ -127,7 +129,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { final RolloutManagement rolloutManagement, final QuotaManagement quotaManagement, final RolloutGroupEvaluationManager evaluationManager, final RolloutApprovalStrategy rolloutApprovalStrategy, final EntityManager entityManager, final PlatformTransactionManager txManager, - final AfterTransactionCommitExecutor afterCommit, final TenantAware tenantAware, final ContextAware contextAware, final RepositoryProperties repositoryProperties) { this.actionRepository = actionRepository; this.rolloutGroupRepository = rolloutGroupRepository; @@ -142,7 +143,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { this.rolloutApprovalStrategy = rolloutApprovalStrategy; this.entityManager = entityManager; this.txManager = txManager; - this.afterCommit = afterCommit; this.tenantAware = tenantAware; this.contextAware = contextAware; this.repositoryProperties = repositoryProperties; @@ -327,8 +327,8 @@ public class JpaRolloutExecutor implements RolloutExecutor { rolloutRepository.save(rollout); final List groupIds = rollout.getRolloutGroups().stream().map(RolloutGroup::getId).toList(); - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutStoppedEvent( - tenantAware.getCurrentTenant(), rollout.getId(), groupIds))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent( + new RolloutStoppedEvent(tenantAware.getCurrentTenant(), rollout.getId(), groupIds))); } } @@ -392,8 +392,7 @@ public class JpaRolloutExecutor implements RolloutExecutor { .map(Action::getId) .toList(); actionRepository.deleteAllById(actionIds); - afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new RolloutUpdatedEvent(rollout))); + afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutUpdatedEvent(rollout))); } catch (final RuntimeException e) { log.error("Exception during deletion of actions of rollout {}", rollout, e); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutHandler.java similarity index 98% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutHandler.java index b53af8d70..dde286438 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaRolloutHandler.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa; +package org.eclipse.hawkbit.repository.jpa.scheduler; import java.util.List; import java.util.Optional; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/RolloutScheduler.java similarity index 97% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/RolloutScheduler.java index f02ed36ee..3e8f0942f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/scheduler/RolloutScheduler.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa.rollout; +package org.eclipse.hawkbit.repository.jpa.scheduler; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -16,6 +16,7 @@ import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.RolloutHandler; import org.eclipse.hawkbit.repository.SystemManagement; +import org.eclipse.hawkbit.repository.jpa.rollout.BlockWhenFullPolicy; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration; import org.springframework.scheduling.annotation.Scheduled; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java index 03b889881..410b119f1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java @@ -124,5 +124,4 @@ class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTe return slowGroupRepo; } } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/AutoAssignTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/AutoAssignTest.java index 1c566b6bd..23daf866e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/AutoAssignTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/AutoAssignTest.java @@ -22,8 +22,8 @@ import java.util.Optional; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate; -import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; -import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignScheduler; +import org.eclipse.hawkbit.repository.AutoAssignExecutor; +import org.eclipse.hawkbit.repository.jpa.scheduler.AutoAssignScheduler; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/ContextAwareTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/ContextAwareTest.java index f886a9bd4..7f1412e91 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/ContextAwareTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/ContextAwareTest.java @@ -22,7 +22,7 @@ import java.util.concurrent.Callable; import lombok.SneakyThrows; import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; +import org.eclipse.hawkbit.repository.AutoAssignExecutor; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/RolloutExecutionTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/RolloutExecutionTest.java index b6294cc55..b9860f5b3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/RolloutExecutionTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/RolloutExecutionTest.java @@ -22,7 +22,7 @@ import java.util.Arrays; import java.util.Optional; import org.eclipse.hawkbit.repository.Identifiable; -import org.eclipse.hawkbit.repository.jpa.rollout.RolloutScheduler; +import org.eclipse.hawkbit.repository.jpa.scheduler.RolloutScheduler; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Target; import org.junit.jupiter.api.Test; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorIntTest.java similarity index 99% rename from hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java rename to hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorIntTest.java index 4bb6bced9..4465fae01 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorIntTest.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa.autoassign; +package org.eclipse.hawkbit.repository.jpa.scheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -44,18 +44,18 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; /** - * Test class for {@link AutoAssignChecker}. + * Test class for {@link JpaAutoAssignExecutor}. *

* Feature: Component Tests - Repository
* Story: Auto assign checker */ @SuppressWarnings("java:S6813") // constructor injects are not possible for test classes -class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { +class JpaAutoAssignExecutorIntTest extends AbstractJpaIntegrationTest { private static final String SPACE_AND_DESCRIPTION = " description"; @Autowired - private AutoAssignChecker autoAssignChecker; + private JpaAutoAssignExecutor autoAssignChecker; @Autowired private DeploymentManagement deploymentManagement; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorTest.java similarity index 96% rename from hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java rename to hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorTest.java index f87618839..83174563f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/scheduler/JpaAutoAssignExecutorTest.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa.autoassign; +package org.eclipse.hawkbit.repository.jpa.scheduler; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -45,7 +45,7 @@ import org.springframework.transaction.PlatformTransactionManager; * Story: Auto assign checker */ @ExtendWith(MockitoExtension.class) -class AutoAssignCheckerTest { +class JpaAutoAssignExecutorTest { @Mock private TargetFilterQueryManagement targetFilterQueryManagement; @@ -58,11 +58,11 @@ class AutoAssignCheckerTest { @Mock private ContextAware contextAware; - private AutoAssignChecker autoAssignChecker; + private JpaAutoAssignExecutor autoAssignChecker; @BeforeEach void before() { - autoAssignChecker = new AutoAssignChecker( + autoAssignChecker = new JpaAutoAssignExecutor( targetFilterQueryManagement, targetManagement, deploymentManagement, transactionManager, contextAware); } 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 cf8f63a3d..fbcf69616 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,8 +22,8 @@ import org.eclipse.hawkbit.artifact.fs.FileArtifactProperties; import org.eclipse.hawkbit.artifact.fs.FileArtifactStorage; import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolver; import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolverProperties; -import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.im.authentication.Hierarchy; +import org.eclipse.hawkbit.repository.RepositoryConfiguration; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; @@ -49,10 +49,10 @@ import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.context.event.SimpleApplicationEventMulticaster; @@ -78,6 +78,10 @@ import org.springframework.security.concurrent.DelegatingSecurityContextSchedule @PropertySource("classpath:/hawkbit-test-defaults.properties") public class TestConfiguration implements AsyncConfigurer { + @Configuration + @Import(RepositoryConfiguration.class) + static class OverridePropertiesSourceFromRepositoryConfiguration {} + @Override public Executor getAsyncExecutor() { return asyncExecutor(); @@ -104,7 +108,7 @@ public class TestConfiguration implements AsyncConfigurer { */ @Bean RolloutStatusCache rolloutStatusCache(final TenantAware tenantAware) { - return new RolloutStatusCache(tenantAware, 0); + return new RolloutStatusCache(tenantAware); } @Bean @@ -158,11 +162,6 @@ public class TestConfiguration implements AsyncConfigurer { return org.mockito.Mockito.spy(new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer, tenantResolver)); } - @Bean - TenantAwareCacheManager cacheManager(final TenantAware tenantAware) { - return new TenantAwareCacheManager(new CaffeineCacheManager(), tenantAware); - } - @Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME) SimpleApplicationEventMulticaster applicationEventMulticaster(final ApplicationEventFilter applicationEventFilter) { final SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java index 3df7f0f44..a637c348c 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java @@ -14,9 +14,9 @@ import java.util.List; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.eclipse.hawkbit.tenancy.TenantAwareCacheManager; import org.springframework.context.ApplicationContext; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -38,7 +38,6 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener SecurityContextSwitch.callAsPrivileged(() -> { final ApplicationContext applicationContext = testContext.getApplicationContext(); clearTestRepository( - applicationContext.getBean(TenantAwareCacheManager.class), applicationContext.getBean(SystemSecurityContext.class), applicationContext.getBean(SystemManagement.class)); return null; @@ -46,10 +45,8 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener } private void clearTestRepository( - final TenantAwareCacheManager cacheManager, final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement) { - final List tenants = systemSecurityContext.runAsSystem(() -> systemManagement.findTenants(PAGE).getContent()); tenants.forEach(tenant -> { try { @@ -58,6 +55,6 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener log.error("Error while delete tenant", e); } }); - cacheManager.getDirectCacheNames().forEach(name -> cacheManager.getDirectCache(name).clear()); + TenantAwareCacheManager.getInstance().evictTenant(null); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties b/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties index 2d2f3e100..cd3833167 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties +++ b/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties @@ -20,9 +20,13 @@ spring.jpa.properties.eclipselink.logging.parameters=true # Test utility properties for easier fault investigation - END # Default properties for test that can be overridden during test run - START -# Enforce persistence of targetpolls for test predictability. +# Enforce persistence of target polls for test predictability. hawkbit.server.repository.eagerPollPersistence=true +# disables Rollout and RoulloutGroup status cache for tests +hawkbit.cache.RolloutStatus.spec=maximumSize=0 +hawkbit.cache.RolloutGroupStatus.spec=maximumSize=0 + # Default properties for test that can be overridden during test run - END # Properties that are managed by autoconfigure module at runtime and not available during test - START diff --git a/hawkbit-rest-core/pom.xml b/hawkbit-rest-core/pom.xml index 004123a3e..7a9494427 100644 --- a/hawkbit-rest-core/pom.xml +++ b/hawkbit-rest-core/pom.xml @@ -74,10 +74,6 @@ commons-io ${commons-io.version} - - com.github.ben-manes.caffeine - caffeine -