From e889e2186c7f0d6c3ad9cb58a38bdb4c53485a68 Mon Sep 17 00:00:00 2001 From: Gabriel Roldan Date: Mon, 9 Sep 2024 11:15:33 -0300 Subject: [PATCH] Fix for GWC not storing tiles when using datadir or jdbcconfig catalog back-ends Abstract out the PgconfigGwcInitializer as AbstractGwcInitializer and refactor the default configuration classes to include the initializer. Tiles weren't being stored when using the `datadir` or `jdbcconfig` catalog backends because `ConfigurableBlobStore.setChanged()` wouldn't be called at startup and it would hence bypass the storage, as its internal `configured` flag was not set. --- src/gwc/autoconfigure/pom.xml | 5 + ...aultTileLayerCatalogAutoConfiguration.java | 6 +- .../gwc/backend/PgconfigGwcInitializer.java | 172 +------------- ...nfigTileLayerCatalogAutoConfiguration.java | 1 + .../backend/GwcCoreAutoConfigurationTest.java | 54 +++++ .../core/GwcCoreAutoConfigurationTest.java | 10 +- .../config/core/AbstractGwcInitializer.java | 210 ++++++++++++++++++ .../DefaultTileLayerCatalogConfiguration.java | 26 +++ .../GeoServerIntegrationConfiguration.java | 31 +-- ...alizer.java => DefaultGwcInitializer.java} | 50 +++-- src/pom.xml | 6 + 11 files changed, 360 insertions(+), 211 deletions(-) create mode 100644 src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/AbstractGwcInitializer.java rename src/gwc/core/src/main/java/org/geoserver/gwc/config/{GwcGeoserverConfigurationInitializer.java => DefaultGwcInitializer.java} (52%) diff --git a/src/gwc/autoconfigure/pom.xml b/src/gwc/autoconfigure/pom.xml index 8f9dea3bf..63c7c7cf2 100644 --- a/src/gwc/autoconfigure/pom.xml +++ b/src/gwc/autoconfigure/pom.xml @@ -74,5 +74,10 @@ test-jar test + + com.github.stefanbirkner + system-lambda + test + diff --git a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/DefaultTileLayerCatalogAutoConfiguration.java b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/DefaultTileLayerCatalogAutoConfiguration.java index c8fddc9c9..6b22dccf5 100644 --- a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/DefaultTileLayerCatalogAutoConfiguration.java +++ b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/DefaultTileLayerCatalogAutoConfiguration.java @@ -19,10 +19,14 @@ /** * {@link AutoConfiguration @AutoConfiguration} to set up the GeoServer {@link TileLayerCatalog} - * using the default implementation based on the {@link ResourceStore} + * using the default implementation based on the {@link ResourceStore}. + * + *

This default configuration applies if there's no other {@link GeoServerTileLayerConfiguration} + * provided. * * @see DefaultTileLayerCatalogConfiguration * @see ConditionalOnGeoWebCacheEnabled + * @see PgconfigTileLayerCatalogAutoConfiguration * @since 1.0 */ @AutoConfiguration(after = PgconfigTileLayerCatalogAutoConfiguration.class) diff --git a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigGwcInitializer.java b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigGwcInitializer.java index 77d366388..6ce29894d 100644 --- a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigGwcInitializer.java +++ b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigGwcInitializer.java @@ -4,39 +4,22 @@ */ package org.geoserver.cloud.autoconfigure.gwc.backend; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Stopwatch; - import lombok.NonNull; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.geoserver.cloud.gwc.backend.pgconfig.PgconfigTileLayerCatalog; +import org.geoserver.cloud.gwc.config.core.AbstractGwcInitializer; import org.geoserver.cloud.gwc.event.TileLayerEvent; import org.geoserver.cloud.gwc.repository.GeoServerTileLayerConfiguration; -import org.geoserver.config.GeoServer; import org.geoserver.config.GeoServerReinitializer; import org.geoserver.gwc.ConfigurableBlobStore; -import org.geoserver.gwc.config.GWCConfig; import org.geoserver.gwc.config.GWCConfigPersister; import org.geoserver.gwc.config.GWCInitializer; -import org.geoserver.gwc.layer.GeoServerTileLayer; import org.geoserver.gwc.layer.TileLayerCatalog; import org.geowebcache.config.TileLayerConfiguration; -import org.geowebcache.layer.TileLayer; import org.geowebcache.layer.TileLayerDispatcher; -import org.geowebcache.storage.blobstore.memory.CacheConfiguration; import org.geowebcache.storage.blobstore.memory.CacheProvider; -import org.geowebcache.storage.blobstore.memory.guava.GuavaCacheProvider; -import org.springframework.context.event.EventListener; - -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import org.slf4j.Logger; /** * Replacement for {@link GWCInitializer} when using the "pgconfig" storage. @@ -57,151 +40,18 @@ * * @since 1.8 */ -@RequiredArgsConstructor @Slf4j(topic = "org.geoserver.cloud.autoconfigure.gwc.backend") -class PgconfigGwcInitializer implements GeoServerReinitializer { - - private final @NonNull GWCConfigPersister configPersister; - private final @NonNull ConfigurableBlobStore blobStore; - private final @NonNull GeoServerTileLayerConfiguration geoseverTileLayers; - - /** - * @see org.geoserver.config.GeoServerInitializer#initialize(org.geoserver.config.GeoServer) - */ - @Override - public void initialize(final GeoServer geoServer) throws Exception { - log.info("Initializing GeoServer specific GWC configuration from gwc-gs.xml"); - - final GWCConfig gwcConfig = configPersister.getConfig(); - checkNotNull(gwcConfig); +class PgconfigGwcInitializer extends AbstractGwcInitializer { - configureInMemoryCacheProvider(gwcConfig); - - final boolean initialization = true; - blobStore.setChanged(gwcConfig, initialization); - - setUpNonMemoryCacheableLayers(); - } - - @EventListener(TileLayerEvent.class) - void onTileLayerEvent(TileLayerEvent event) { - cacheProvider() - .ifPresent( - cache -> { - switch (event.getEventType()) { - case DELETED: - log.debug( - "TileLayer {} deleted, notifying in-memory CacheProvider", - event.getName()); - cache.removeUncachedLayer(event.getName()); - break; - case MODIFIED: - if (event.getOldName() != null - && !Objects.equals( - event.getOldName(), event.getName())) { - log.info( - "TileLayer {} renamed to {}, notifying in-memory CacheProvider", - event.getOldName(), - event.getName()); - cache.removeUncachedLayer(event.getOldName()); - } - setInMemoryLayerCaching(event.getName()); - break; - default: - setInMemoryLayerCaching(event.getName()); - break; - } - }); + public PgconfigGwcInitializer( + @NonNull GWCConfigPersister configPersister, + @NonNull ConfigurableBlobStore blobStore, + @NonNull GeoServerTileLayerConfiguration geoseverTileLayers) { + super(configPersister, blobStore, geoseverTileLayers); } - private void configureInMemoryCacheProvider(final GWCConfig gwcConfig) throws IOException { - // Setting default CacheProvider class if not present - if (gwcConfig.getCacheProviderClass() == null - || gwcConfig.getCacheProviderClass().isEmpty()) { - gwcConfig.setCacheProviderClass(GuavaCacheProvider.class.toString()); - configPersister.save(gwcConfig); - } - - // Setting default Cache Configuration - if (gwcConfig.getCacheConfigurations() == null) { - log.debug("Setting default CacheConfiguration"); - Map map = new HashMap<>(); - map.put(GuavaCacheProvider.class.toString(), new CacheConfiguration()); - gwcConfig.setCacheConfigurations(map); - configPersister.save(gwcConfig); - } else { - log.debug("CacheConfiguration loaded"); - } - - // Change ConfigurableBlobStore behavior - String cacheProviderClass = gwcConfig.getCacheProviderClass(); - Map cacheProviders = blobStore.getCacheProviders(); - if (!cacheProviders.containsKey(cacheProviderClass)) { - gwcConfig.setCacheProviderClass(GuavaCacheProvider.class.toString()); - configPersister.save(gwcConfig); - log.debug("Unable to find: {}, used default configuration", cacheProviderClass); - } - } - - private void setInMemoryLayerCaching(@NonNull String layerName) { - - layer(layerName) - .ifPresentOrElse(this::addUncachedLayer, () -> removeCachedLayer(layerName)); - } - - private void removeCachedLayer(String layerName) { - cacheProvider() - .ifPresent( - cache -> { - log.debug( - "TileLayer {} does not exist, notifying CacheProvider", - layerName); - cache.removeLayer(layerName); - cache.removeUncachedLayer(layerName); - }); - } - - private void addUncachedLayer(GeoServerTileLayer tl) { - if (!tl.getInfo().isInMemoryCached()) { - log.debug( - "TileLayer {} is not to be memory cached, notifying CacheProvider", - tl.getName()); - cacheProvider().ifPresent(cache -> cache.addUncachedLayer(tl.getName())); - } - } - - private Optional layer(String layerName) { - return geoseverTileLayers - .getLayer(layerName) - .filter(GeoServerTileLayer.class::isInstance) - .map(GeoServerTileLayer.class::cast); - } - - /** - * Private method for adding all the Layer that must not be cached to the {@link CacheProvider} - * instance. - */ - private void setUpNonMemoryCacheableLayers() { - cacheProvider() - .ifPresent( - cache -> { - // Add all the various Layers to avoid caching - log.info("Adding Layers to avoid In Memory Caching"); - // it is ok to use the ForkJoinPool.commonPool() here, there's no I/O - // involved - Stopwatch sw = Stopwatch.createStarted(); - Collection layers = geoseverTileLayers.getLayers(); - log.info("Queried {} tile layers in {}", layers.size(), sw.stop()); - layers.stream() - .filter(GeoServerTileLayer.class::isInstance) - .map(GeoServerTileLayer.class::cast) - .filter(l -> l.isEnabled() && !l.getInfo().isInMemoryCached()) - .map(GeoServerTileLayer::getName) - .forEach(cache::addUncachedLayer); - }); - } - - private Optional cacheProvider() { - return Optional.ofNullable(blobStore.getCache()); + @Override + protected Logger logger() { + return log; } } diff --git a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigTileLayerCatalogAutoConfiguration.java b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigTileLayerCatalogAutoConfiguration.java index a4ef5ef65..b2cc42f16 100644 --- a/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigTileLayerCatalogAutoConfiguration.java +++ b/src/gwc/autoconfigure/src/main/java/org/geoserver/cloud/autoconfigure/gwc/backend/PgconfigTileLayerCatalogAutoConfiguration.java @@ -44,6 +44,7 @@ * GeoServer Catalog in the Postgres database; * * @since 1.7 + * @see ConditionalOnPgconfigBackendEnabled */ @AutoConfiguration(after = PgconfigDataSourceAutoConfiguration.class) @ConditionalOnClass(PgconfigTileLayerCatalog.class) diff --git a/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/backend/GwcCoreAutoConfigurationTest.java b/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/backend/GwcCoreAutoConfigurationTest.java index 8dd3888b7..ea281eb3b 100644 --- a/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/backend/GwcCoreAutoConfigurationTest.java +++ b/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/backend/GwcCoreAutoConfigurationTest.java @@ -4,6 +4,8 @@ */ package org.geoserver.cloud.autoconfigure.gwc.backend; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; + import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; @@ -14,6 +16,7 @@ import com.google.common.base.Throwables; import org.geoserver.cloud.autoconfigure.gwc.GeoWebCacheContextRunner; +import org.geoserver.cloud.gwc.config.core.GeoWebCacheConfigurationProperties; import org.geoserver.cloud.gwc.repository.CloudDefaultStorageFinder; import org.geoserver.cloud.gwc.repository.CloudGwcXmlConfiguration; import org.geoserver.cloud.gwc.repository.CloudXMLResourceProvider; @@ -37,6 +40,7 @@ class GwcCoreAutoConfigurationTest { @BeforeEach void setUp() { + System.clearProperty("GEOWEBCACHE_CACHE_DIR"); runner = GeoWebCacheContextRunner.newMinimalGeoWebCacheContextRunner(tmpDir); } @@ -92,4 +96,54 @@ protected void assertContextLoadFails( assertThat(root.getMessage(), containsString(expectedMessage)); }); } + + /** + * Note this test will fail without {@code --add-opens=java.base/java.util=ALL-UNNAMED} JVM + * parameter (watch out if running it from the IDE, maven is configured to set it) + */ + @Test + void defaultCacheDirectoryFromEnvVariable() throws Exception { + File dir = new File(tmpDir, "env_cachedir"); + assertThat(dir).doesNotExist(); + String dirpath = dir.getAbsolutePath(); + withEnvironmentVariable("GEOWEBCACHE_CACHE_DIR", dirpath) + .execute( + () -> { + assertThat(System.getenv("GEOWEBCACHE_CACHE_DIR")).isEqualTo(dirpath); + runner.withPropertyValues( + "gwc.cache-directory: ${GEOWEBCACHE_CACHE_DIR}") + .run( + context -> { + assertThat(context).hasNotFailed(); + assertThat(dir).isDirectory(); + + var gwcConfigProps = + context.getBean( + GeoWebCacheConfigurationProperties + .class); + assertThat(gwcConfigProps.getCacheDirectory()) + .isEqualTo(dir.toPath()); + }); + }); + assertThat(System.getenv("GEOWEBCACHE_CACHE_DIR")).isNull(); + } + + @Test + void defaultCacheDirectoryFromSystemProperty() throws Exception { + File dir = new File(tmpDir, "sysprop_cachedir"); + assertThat(dir).doesNotExist(); + String dirpath = dir.getAbsolutePath(); + + System.setProperty("GEOWEBCACHE_CACHE_DIR", dirpath); + try { + runner.withPropertyValues("gwc.cache-directory: ${GEOWEBCACHE_CACHE_DIR}") + .run( + context -> { + assertThat(context).hasNotFailed(); + assertThat(dir).isDirectory(); + }); + } finally { + System.clearProperty("GEOWEBCACHE_CACHE_DIR"); + } + } } diff --git a/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/core/GwcCoreAutoConfigurationTest.java b/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/core/GwcCoreAutoConfigurationTest.java index 87f9136e9..dbc2d0bb5 100644 --- a/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/core/GwcCoreAutoConfigurationTest.java +++ b/src/gwc/autoconfigure/src/test/java/org/geoserver/cloud/autoconfigure/gwc/core/GwcCoreAutoConfigurationTest.java @@ -17,7 +17,7 @@ import org.geoserver.cloud.gwc.repository.CloudDefaultStorageFinder; import org.geoserver.cloud.gwc.repository.CloudGwcXmlConfiguration; import org.geoserver.cloud.gwc.repository.CloudXMLResourceProvider; -import org.geoserver.gwc.config.GwcGeoserverConfigurationInitializer; +import org.geoserver.gwc.config.DefaultGwcInitializer; import org.geoserver.platform.GeoServerExtensionsHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -72,11 +72,9 @@ void contextLoads() { GeoServerExtensionsHelper.init(context); assertThat(context) .hasNotFailed() - .hasBean("gwcGeoserverConfigurationInitializer") - .getBean( - "gwcGeoserverConfigurationInitializer", - GwcGeoserverConfigurationInitializer.class) - .isInstanceOf(GwcGeoserverConfigurationInitializer.class); + .hasBean("gwcInitializer") + .getBean("gwcInitializer") + .isInstanceOf(DefaultGwcInitializer.class); assertThat(context.isTypeMatch("gwcXmlConfig", CloudGwcXmlConfiguration.class)) .isTrue(); diff --git a/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/AbstractGwcInitializer.java b/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/AbstractGwcInitializer.java new file mode 100644 index 000000000..673b2cfdd --- /dev/null +++ b/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/AbstractGwcInitializer.java @@ -0,0 +1,210 @@ +/* + * (c) 2024 Open Source Geospatial Foundation - all rights reserved This code is licensed under the + * GPL 2.0 license, available at the root application directory. + */ +package org.geoserver.cloud.gwc.config.core; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Stopwatch; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import org.geoserver.cloud.gwc.event.TileLayerEvent; +import org.geoserver.cloud.gwc.repository.GeoServerTileLayerConfiguration; +import org.geoserver.config.GeoServer; +import org.geoserver.config.GeoServerReinitializer; +import org.geoserver.gwc.ConfigurableBlobStore; +import org.geoserver.gwc.config.GWCConfig; +import org.geoserver.gwc.config.GWCConfigPersister; +import org.geoserver.gwc.config.GWCInitializer; +import org.geoserver.gwc.layer.GeoServerTileLayer; +import org.geoserver.gwc.layer.TileLayerCatalog; +import org.geowebcache.layer.TileLayer; +import org.geowebcache.storage.blobstore.memory.CacheConfiguration; +import org.geowebcache.storage.blobstore.memory.CacheProvider; +import org.geowebcache.storage.blobstore.memory.guava.GuavaCacheProvider; +import org.slf4j.Logger; +import org.springframework.context.event.EventListener; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * Base class for replacements of {@link GWCInitializer}. + * + *

This is required because GeoServer Cloud may not set up a {@link TileLayerCatalog}, which + * {@link GWCInitializer} requires. + * + *

This {@link GeoServerReinitializer} is hence in charge of notifying {@link + * ConfigurableBlobStore#setChanged(org.geoserver.gwc.config.GWCConfig, boolean)} + * + *

This bean also listens to {@link TileLayerEvent}s and notifies the {@link CacheProvider} to + * either {@link CacheProvider#removeLayer(String) removeLayer} or {@link + * CacheProvider#removeUncachedLayer(String) removeUncachedLayer} on changes and deletions as + * appropriate, or to {@link CacheProvider#addUncachedLayer(String) addUncachedLayer} when a layer + * is created to changed to not be memory cached. + * + * @since 1.8 + */ +@RequiredArgsConstructor +public abstract class AbstractGwcInitializer implements GeoServerReinitializer { + + protected final @NonNull GWCConfigPersister configPersister; + protected final @NonNull ConfigurableBlobStore blobStore; + protected final @NonNull GeoServerTileLayerConfiguration geoseverTileLayers; + + protected abstract Logger logger(); + + /** + * @see org.geoserver.config.GeoServerInitializer#initialize(org.geoserver.config.GeoServer) + */ + @Override + public void initialize(final GeoServer geoServer) throws Exception { + logger().info("Initializing GeoServer specific GWC configuration from gwc-gs.xml"); + + final GWCConfig gwcConfig = configPersister.getConfig(); + checkNotNull(gwcConfig); + + configureInMemoryCacheProvider(gwcConfig); + + final boolean initialization = true; + blobStore.setChanged(gwcConfig, initialization); + + setUpNonMemoryCacheableLayers(); + } + + @EventListener(TileLayerEvent.class) + void onTileLayerEvent(TileLayerEvent event) { + cacheProvider().ifPresent(cache -> onTileLayerEvent(event, cache)); + } + + private void onTileLayerEvent(TileLayerEvent event, CacheProvider cache) { + @NonNull String layerName = event.getName(); + + switch (event.getEventType()) { + case DELETED: + logger().debug( + "TileLayer {} deleted, notifying in-memory CacheProvider", + layerName); + cache.removeUncachedLayer(layerName); + break; + case MODIFIED: + if (isRename(event)) { + String oldName = event.getOldName(); + logger().info( + "TileLayer {} renamed to {}, notifying in-memory CacheProvider", + oldName, + layerName); + cache.removeUncachedLayer(oldName); + } + setInMemoryLayerCaching(layerName); + break; + default: + setInMemoryLayerCaching(layerName); + break; + } + } + + private boolean isRename(TileLayerEvent event) { + String layerName = event.getName(); + String oldName = event.getOldName(); + return oldName != null && !Objects.equals(oldName, layerName); + } + + private void configureInMemoryCacheProvider(final GWCConfig gwcConfig) throws IOException { + // Setting default CacheProvider class if not present + if (!StringUtils.hasText(gwcConfig.getCacheProviderClass())) { + gwcConfig.setCacheProviderClass(GuavaCacheProvider.class.toString()); + configPersister.save(gwcConfig); + } + + // Setting default Cache Configuration + if (gwcConfig.getCacheConfigurations() == null) { + logger().debug("Setting default CacheConfiguration"); + Map map = new HashMap<>(); + map.put(GuavaCacheProvider.class.toString(), new CacheConfiguration()); + gwcConfig.setCacheConfigurations(map); + configPersister.save(gwcConfig); + } else { + logger().debug("CacheConfiguration loaded"); + } + + // Change ConfigurableBlobStore behavior + String cacheProviderClass = gwcConfig.getCacheProviderClass(); + Map cacheProviders = blobStore.getCacheProviders(); + if (!cacheProviders.containsKey(cacheProviderClass)) { + gwcConfig.setCacheProviderClass(GuavaCacheProvider.class.toString()); + configPersister.save(gwcConfig); + logger().debug("Unable to find: {}, used default configuration", cacheProviderClass); + } + } + + private void setInMemoryLayerCaching(@NonNull String layerName) { + + layer(layerName) + .ifPresentOrElse(this::addUncachedLayer, () -> removeCachedLayer(layerName)); + } + + private void removeCachedLayer(String layerName) { + cacheProvider() + .ifPresent( + cache -> { + logger().debug( + "TileLayer {} does not exist, notifying CacheProvider", + layerName); + cache.removeLayer(layerName); + cache.removeUncachedLayer(layerName); + }); + } + + private void addUncachedLayer(GeoServerTileLayer tl) { + if (!tl.getInfo().isInMemoryCached()) { + logger().debug( + "TileLayer {} is not to be memory cached, notifying CacheProvider", + tl.getName()); + cacheProvider().ifPresent(cache -> cache.addUncachedLayer(tl.getName())); + } + } + + private Optional layer(String layerName) { + return geoseverTileLayers + .getLayer(layerName) + .filter(GeoServerTileLayer.class::isInstance) + .map(GeoServerTileLayer.class::cast); + } + + /** + * Private method for adding all the Layer that must not be cached to the {@link CacheProvider} + * instance. + */ + private void setUpNonMemoryCacheableLayers() { + cacheProvider() + .ifPresent( + cache -> { + // Add all the various Layers to avoid caching + logger().info("Adding Layers to avoid In Memory Caching"); + // it is ok to use the ForkJoinPool.commonPool() here, there's no I/O + // involved + Stopwatch sw = Stopwatch.createStarted(); + Collection layers = geoseverTileLayers.getLayers(); + logger().info("Queried {} tile layers in {}", layers.size(), sw.stop()); + layers.stream() + .filter(GeoServerTileLayer.class::isInstance) + .map(GeoServerTileLayer.class::cast) + .filter(l -> l.isEnabled() && !l.getInfo().isInMemoryCached()) + .map(GeoServerTileLayer::getName) + .forEach(cache::addUncachedLayer); + }); + } + + private Optional cacheProvider() { + return Optional.ofNullable(blobStore.getCache()); + } +} diff --git a/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/DefaultTileLayerCatalogConfiguration.java b/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/DefaultTileLayerCatalogConfiguration.java index 91a82d120..b57c58fff 100644 --- a/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/DefaultTileLayerCatalogConfiguration.java +++ b/src/gwc/core/src/main/java/org/geoserver/cloud/gwc/config/core/DefaultTileLayerCatalogConfiguration.java @@ -4,12 +4,18 @@ */ package org.geoserver.cloud.gwc.config.core; +import org.geoserver.GeoServerConfigurationLock; import org.geoserver.catalog.Catalog; import org.geoserver.cloud.gwc.event.TileLayerEvent; import org.geoserver.cloud.gwc.repository.CachingTileLayerCatalog; import org.geoserver.cloud.gwc.repository.CloudCatalogConfiguration; import org.geoserver.cloud.gwc.repository.GeoServerTileLayerConfiguration; import org.geoserver.cloud.gwc.repository.ResourceStoreTileLayerCatalog; +import org.geoserver.gwc.ConfigurableBlobStore; +import org.geoserver.gwc.config.DefaultGwcInitializer; +import org.geoserver.gwc.config.GWCConfigPersister; +import org.geoserver.gwc.config.GWCInitializer; +import org.geoserver.gwc.layer.CatalogConfiguration; import org.geoserver.gwc.layer.TileLayerCatalog; import org.geoserver.platform.resource.ResourceStore; import org.geowebcache.grid.GridSetBroker; @@ -31,6 +37,26 @@ @Configuration(proxyBeanMethods = false) public class DefaultTileLayerCatalogConfiguration { + /** + * Replaces {@link GWCInitializer} + * + *

+ * + *