Support cache eviction in microservice mode (#2503)
When running in microservice mode, updating configuration properties via the management component does not automatically update caches in other services. This change introduces support for distributed cache eviction using Spring Cloud Bus. It listens for remote tenant configuration events and evicts the relevant cache key upon receipt. Signed-off-by: Birk Blechschmidt <birk.blechschmidt@liebherr.com>
This commit is contained in:
committed by
GitHub
parent
c5efce4ad8
commit
f249544f5d
@@ -30,6 +30,9 @@ import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RemoteTenantAwareEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TenantConfigurationDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RemoteEntityEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
|
||||
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValueChangeNotAllowedException;
|
||||
@@ -49,11 +52,14 @@ 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.beans.factory.annotation.Autowired;
|
||||
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.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
@@ -79,6 +85,8 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
private final CacheManager cacheManager;
|
||||
private final AfterTransactionCommitExecutor afterCommitExecutor;
|
||||
|
||||
private ServiceMatcher serviceMatcher;
|
||||
|
||||
public JpaTenantConfigurationManagement(
|
||||
final TenantConfigurationRepository tenantConfigurationRepository,
|
||||
final TenantConfigurationProperties tenantConfigurationProperties,
|
||||
@@ -91,6 +99,11 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setServiceMatcher(final ServiceMatcher serviceMatcher) {
|
||||
this.serviceMatcher = serviceMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
|
||||
@Transactional
|
||||
@@ -162,6 +175,36 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
return CONVERSION_SERVICE.convert(key.getDefaultValue(), propertyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that cache eviction takes place in microservice mode in case of deletions.
|
||||
*
|
||||
* @param event The event indicating that a configuration value has been deleted.
|
||||
*/
|
||||
@EventListener
|
||||
public void onTenantConfigurationDeletedEvent(final TenantConfigurationDeletedEvent event) {
|
||||
if (!shouldProcessRemoteTenantAwareEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
evictCacheEntryByKeyIfPresent(event.getConfigKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that cache eviction takes place in microservice mode in case of creation or update events.
|
||||
*
|
||||
* @param event The event indicating that a configuration value has been created or updated.
|
||||
*/
|
||||
@EventListener
|
||||
public void onTenantConfigurationRemoteEntityEvent(final RemoteEntityEvent<TenantConfiguration> event) {
|
||||
if (!shouldProcessRemoteTenantAwareEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.getEntity().ifPresent(tenantConfiguration -> {
|
||||
evictCacheEntryByKeyIfPresent(tenantConfiguration.getKey());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Target, PollStatus> pollStatusResolver() {
|
||||
final PollingTime pollingTime = new PollingTime(
|
||||
@@ -339,4 +382,15 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void evictCacheEntryByKeyIfPresent(final String key) {
|
||||
final Cache cache = cacheManager.getCache("tenantConfiguration");
|
||||
if (cache != null) {
|
||||
cache.evictIfPresent(key);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldProcessRemoteTenantAwareEvent(final RemoteTenantAwareEvent event) {
|
||||
return serviceMatcher == null || !serviceMatcher.isFromSelf(event) && serviceMatcher.isForSelf(event);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user