diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index a712d298c..1741c0ef3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -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 event) { + if (!shouldProcessRemoteTenantAwareEvent(event)) { + return; + } + + event.getEntity().ifPresent(tenantConfiguration -> { + evictCacheEntryByKeyIfPresent(tenantConfiguration.getKey()); + }); + } + @Override public Function pollStatusResolver() { final PollingTime pollingTime = new PollingTime( @@ -339,4 +382,15 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana } } } -} \ No newline at end of file + + 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); + } +}