Refactor caches (#2775)
* added static usage of cache in order access it easier * added mandatory (in hawkbit-core) registration - always tenant aware caches shall be used - hawkbit depends on it * added per cache and tenant name configuration * (not really realted to caches) but in order to be easier evicted entities after commit handlers are now statically accessed Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -41,10 +41,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.protostuff</groupId>
|
||||
<artifactId>protostuff-core</artifactId>
|
||||
|
||||
@@ -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.
|
||||
* <p/>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -38,12 +38,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -53,12 +55,14 @@
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
|
||||
@@ -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.
|
||||
* <ul>
|
||||
* <li>If a tenant is resolved by the {@link TenantResolver}, a dedicated cache manager for that tenant is used/created.</li>
|
||||
* <li>If no tenant is resolved, a global cache manager is used.</li>
|
||||
* </ul>
|
||||
*/
|
||||
@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<String, CacheManager> 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<String> 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<String, Cache> 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<String> getCacheNames() {
|
||||
return caches.keySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
* <p/>
|
||||
* 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<String> 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<String> 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<String> 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
org.eclipse.hawkbit.tenancy.TenantCacheConfiguration
|
||||
org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration.WebConfig
|
||||
org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration.RepositoryConfig
|
||||
|
||||
@@ -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.
|
||||
@@ -32,10 +32,6 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
|
||||
@@ -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<Object, Object> 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<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> ids,
|
||||
@NotNull final Cache cache) {
|
||||
private @NotNull Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> 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<TotalTargetCountActionStatus> 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<TotalTargetCountActionStatus> status) {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Runnable> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Runnable> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<? extends Target> 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<? extends TargetFilterQuery> targetFilterQueryManagement,
|
||||
final TargetManagement<? extends Target> targetManagement,
|
||||
final DeploymentManagement deploymentManagement,
|
||||
final PlatformTransactionManager transactionManager, final ContextAware contextAware) {
|
||||
return new AutoAssignChecker(targetFilterQueryManagement, targetManagement, deploymentManagement, transactionManager, contextAware);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AutoAssignScheduler} bean.
|
||||
* <p/>
|
||||
@@ -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
|
||||
|
||||
@@ -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<MaxAssignmentsExceededInfo> 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<? extends DistributionSet> 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)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<String> auditorProvider,
|
||||
final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager,
|
||||
final PlatformTransactionManager txManager,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware<String> 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;
|
||||
|
||||
@@ -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<JpaAction> actions = findActiveActionsForRollout(rollout.getId(), Pageable.ofSize(MAX_ACTIONS))
|
||||
final List<JpaAction> actions = findActiveActionsForRollout(rollout.getId(), Pageable.ofSize(maxActions))
|
||||
.getContent();
|
||||
log.info("Found {} active actions for rollout {}", actions.size(), rollout.getId());
|
||||
|
||||
|
||||
@@ -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<String> 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<JpaTargetType, TargetTypeManagement.Create, TargetTypeManagement.Update, TargetTypeRepository, TargetTypeFields>
|
||||
implements TargetTypeManagement<JpaTargetType>{
|
||||
|
||||
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<TargetType> findByKey(final String key) {
|
||||
return jpaRepository.findOne(TargetTypeSpecification.hasKey(key)).map(TargetType.class::cast);
|
||||
}
|
||||
|
||||
@@ -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 <T extends Serializable> Map<String, TenantConfigurationValue<T>> addOrUpdateConfiguration(final Map<String, T> 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 <T extends Serializable> TenantConfigurationValue<T> 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 <T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(
|
||||
final String configurationKeyName, final Class<T> 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);
|
||||
}
|
||||
|
||||
@@ -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<MaxAssignmentsExceededInfo> maxAssignmentExceededHandler) {
|
||||
super(targetRepository, afterCommit, actionRepository, actionStatusRepository,
|
||||
super(targetRepository, actionRepository, actionStatusRepository,
|
||||
quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties, maxAssignmentExceededHandler);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<MaxAssignmentsExceededInfo> 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<List<Long>> targetIds,
|
||||
final String currentUser) {
|
||||
public void setAssignedDistributionSetAndTargetStatus(
|
||||
final JpaDistributionSet set, final List<List<Long>> 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<Action> 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<Action> actions) {
|
||||
afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher()
|
||||
.publishEvent(new MultiActionAssignEvent(tenant, actions)));
|
||||
afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new MultiActionAssignEvent(tenant, actions)));
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,6 @@ public interface TenantConfigurationRepository extends BaseEntityRepository<JpaT
|
||||
/**
|
||||
* Deletes a tenant configuration by tenant and key.
|
||||
*
|
||||
* @param tenant the tenant for this configuration
|
||||
* @param keyName the name of the key to be deleted
|
||||
*/
|
||||
void deleteByKey(String keyName);
|
||||
@@ -44,7 +43,7 @@ public interface TenantConfigurationRepository extends BaseEntityRepository<JpaT
|
||||
/**
|
||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||
* manually to query even if this will by done by {@link EntityManager}
|
||||
* manually to query even if this will be done by {@link EntityManager}
|
||||
* anyhow. The DB should take care of optimizing this away.
|
||||
*
|
||||
* @param tenant to delete data from
|
||||
@@ -53,5 +52,4 @@ public interface TenantConfigurationRepository extends BaseEntityRepository<JpaT
|
||||
@Transactional
|
||||
@Query("DELETE FROM JpaTenantConfiguration t WHERE t.tenant = :tenant")
|
||||
void deleteByTenant(@Param("tenant") String tenant);
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
public class BlockWhenFullPolicy implements RejectedExecutionHandler {
|
||||
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
try {
|
||||
|
||||
@@ -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.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -15,8 +15,8 @@ import java.util.concurrent.locks.Lock;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.AutoAssignExecutor;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantMetricsConfiguration;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
@@ -28,7 +28,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
@Slf4j
|
||||
public class AutoAssignScheduler {
|
||||
|
||||
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.autoassign.scheduler.fixedDelay:2000}";
|
||||
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.scheduler.scheduler.fixedDelay:2000}";
|
||||
|
||||
private final SystemManagement systemManagement;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
@@ -70,7 +70,7 @@ public class AutoAssignScheduler {
|
||||
// workaround eclipselink that is currently not possible to execute a query without multitenancy if MultiTenant
|
||||
// annotation is used - https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So iterate through all tenants and execute the rollout
|
||||
// check for each tenant separately.
|
||||
final Lock lock = lockRegistry.obtain("autoassign");
|
||||
final Lock lock = lockRegistry.obtain("scheduler");
|
||||
if (!lock.tryLock()) {
|
||||
return null;
|
||||
}
|
||||
@@ -79,20 +79,20 @@ public class AutoAssignScheduler {
|
||||
try {
|
||||
log.debug("Auto assign scheduled execution has acquired lock and started for each tenant.");
|
||||
systemManagement.forEachTenant(tenant -> {
|
||||
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.");
|
||||
}
|
||||
@@ -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<? extends TargetFilterQuery> targetFilterQueryManagement,
|
||||
final TargetManagement<? extends Target> targetManagement, final DeploymentManagement deploymentManagement,
|
||||
final PlatformTransactionManager transactionManager, final ContextAware contextAware) {
|
||||
@@ -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<Long> 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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -124,5 +124,4 @@ class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTe
|
||||
return slowGroupRepo;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}.
|
||||
* <p/>
|
||||
* Feature: Component Tests - Repository<br/>
|
||||
* 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;
|
||||
|
||||
@@ -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<? extends TargetFilterQuery> 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);
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -74,10 +74,6 @@
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
|
||||
Reference in New Issue
Block a user