From 7efec3791c5bd8cccc833afce081716b9f3d457d Mon Sep 17 00:00:00 2001 From: rng Date: Fri, 31 Oct 2025 10:05:28 +1100 Subject: [PATCH] refactor to make warm cache in same location --- .../core/configuration/CacheConfig.java | 13 ++++-- .../server/core/configuration/Config.java | 6 +++ .../core/configuration/WfsWmsConfig.java | 6 --- .../core/service/CacheNoLandGeometry.java | 6 --- .../core/service/{wms => }/CacheWarm.java | 24 ++++++++++- .../server/core/util/GeometryUtils.java | 41 ++++++++----------- 6 files changed, 55 insertions(+), 41 deletions(-) rename server/src/main/java/au/org/aodn/ogcapi/server/core/service/{wms => }/CacheWarm.java (63%) diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/CacheConfig.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/CacheConfig.java index 7a3d3a4e..25d82cc7 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/CacheConfig.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/CacheConfig.java @@ -1,6 +1,8 @@ package au.org.aodn.ogcapi.server.core.configuration; import au.org.aodn.ogcapi.server.core.service.CacheNoLandGeometry; +import au.org.aodn.ogcapi.server.core.service.CacheWarm; +import au.org.aodn.ogcapi.server.core.service.wms.WmsServer; import au.org.aodn.ogcapi.server.core.util.GeometryUtils; import org.ehcache.config.builders.*; import org.ehcache.config.units.MemoryUnit; @@ -18,6 +20,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import java.util.Map; @Configuration @EnableCaching @@ -82,7 +85,7 @@ public JCacheCacheManager cacheManager() throws IOException { ) .withCache(STRING_TO_GEOMETRY, CacheConfigurationBuilder.newCacheConfigurationBuilder( - String.class, Geometry.class, + Map.class, Geometry.class, ResourcePoolsBuilder.heap(20000) ).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(24))) ) @@ -104,8 +107,12 @@ public JCacheCacheManager cacheManager() throws IOException { config ); - GeometryUtils.setCacheManager(jCacheManager); - return new JCacheCacheManager(jCacheManager); } + + @Bean + public CacheWarm createCacheWarm(WmsServer wmsServer, CacheNoLandGeometry cacheNoLandGeometry, GeometryUtils geometryUtils) { + GeometryUtils.setSelf(geometryUtils); + return new CacheWarm(wmsServer, cacheNoLandGeometry, geometryUtils); + } } diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java index 58605698..723b3f97 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java @@ -1,6 +1,7 @@ package au.org.aodn.ogcapi.server.core.configuration; import au.org.aodn.ogcapi.server.core.util.ConstructUtils; +import au.org.aodn.ogcapi.server.core.util.GeometryUtils; import au.org.aodn.ogcapi.server.core.util.RestTemplateUtils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; @@ -43,4 +44,9 @@ public RestTemplate createRestTemplate() { public RestTemplateUtils createRestTemplateUtils(RestTemplate restTemplate) { return new RestTemplateUtils(restTemplate); } + + @Bean + public GeometryUtils createGeometryUtils() { + return new GeometryUtils(); + } } diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/WfsWmsConfig.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/WfsWmsConfig.java index 933b6fd2..ed61437a 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/WfsWmsConfig.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/WfsWmsConfig.java @@ -1,7 +1,6 @@ package au.org.aodn.ogcapi.server.core.configuration; import au.org.aodn.ogcapi.server.core.service.wfs.WfsServer; -import au.org.aodn.ogcapi.server.core.service.wms.CacheWarm; import au.org.aodn.ogcapi.server.core.service.wms.WmsServer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,9 +17,4 @@ public WfsServer createWfsServer() { public WmsServer createWmsServer() { return new WmsServer(); } - - @Bean - public CacheWarm createCacheWarm(WmsServer wmsServer) { - return new CacheWarm(wmsServer); - } } diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheNoLandGeometry.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheNoLandGeometry.java index cedf563a..c032c0ac 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheNoLandGeometry.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheNoLandGeometry.java @@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Lazy; -import org.springframework.scheduling.annotation.Scheduled; import java.util.List; import java.util.Map; @@ -25,15 +24,10 @@ public class CacheNoLandGeometry { @Autowired ElasticSearch elasticSearch; - @Autowired - @Lazy - private CacheNoLandGeometry self; - /** * Init cache after 1 second but then never call again due to Long.MAX_VALUE * @return A Map include the uuid and the noloand geometry */ - @Scheduled(initialDelay = 1000, fixedDelay = Long.MAX_VALUE) @Cacheable(ALL_NO_LAND_GEOMETRY) public Map getAllNoLandGeometry() { ElasticSearchBase.SearchResult result = elasticSearch.searchCollectionBy( diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/CacheWarm.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java similarity index 63% rename from server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/CacheWarm.java rename to server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java index 2d5ca5c3..8dce97c5 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/CacheWarm.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java @@ -1,11 +1,15 @@ -package au.org.aodn.ogcapi.server.core.service.wms; +package au.org.aodn.ogcapi.server.core.service; +import au.org.aodn.ogcapi.server.core.model.StacCollectionModel; +import au.org.aodn.ogcapi.server.core.service.wms.WmsServer; +import au.org.aodn.ogcapi.server.core.util.GeometryUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import java.util.List; +import java.util.Map; /** * Some WMS server response very slow for GetCapabilities operation, so we warm some @@ -18,12 +22,18 @@ public class CacheWarm { "https://data.aad.gov.au/geoserver/underway/wms" ); protected WmsServer wmsServer; + protected GeometryUtils geometryUtils; + protected CacheNoLandGeometry cacheNoLandGeometry; @Lazy @Autowired protected CacheWarm self; - public CacheWarm(WmsServer wmsServer) { + public CacheWarm(WmsServer wmsServer, + CacheNoLandGeometry cacheNoLandGeometry, + GeometryUtils geometryUtils) { + this.cacheNoLandGeometry = cacheNoLandGeometry; + this.geometryUtils = geometryUtils; this.wmsServer = wmsServer; } /** @@ -38,6 +48,16 @@ public void evictSpecificCacheEntries() { }); } + @Scheduled(initialDelay = 1000, fixedRate = 23 * 60 * 60 * 1000) + public void keepWarmNoLandGeometryAndGeometryUtil() { + Map value = cacheNoLandGeometry.getAllNoLandGeometry(); + value.values() + .stream() + .filter(collection -> collection.getSummaries() != null && collection.getSummaries().getGeometryNoLand() != null) + .forEach(collection -> geometryUtils.readCachedGeometry(collection.getSummaries().getGeometryNoLand())); + } + + @CacheEvict(value = au.org.aodn.ogcapi.server.core.configuration.CacheConfig.GET_CAPABILITIES_WMS_LAYERS, key = "#key") protected void evictGetCapabilities(String key){ // @CacheEvict handles the eviction diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/util/GeometryUtils.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/util/GeometryUtils.java index bc838369..f9748070 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/util/GeometryUtils.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/util/GeometryUtils.java @@ -19,9 +19,8 @@ import org.opengis.referencing.operation.TransformException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.cache.annotation.Cacheable; -import javax.cache.Cache; -import javax.cache.CacheManager; import java.io.IOException; import java.io.StringWriter; import java.math.BigDecimal; @@ -35,9 +34,6 @@ public class GeometryUtils { protected static final int PRECISION = 15; - @Setter - protected static volatile CacheManager cacheManager; - @Getter protected static GeometryFactory factory = new GeometryFactory(new PrecisionModel(), 4326); @@ -45,6 +41,10 @@ public class GeometryUtils { // This number of decimal is needed to do some accurate protected static GeometryJSON json = new GeometryJSON(PRECISION); + @Getter + @Setter + protected static GeometryUtils self = new GeometryUtils(); // Avoid testing fail, it will be replaced by bean instance + @Getter @Setter protected static int centroidScale = 5; @@ -210,14 +210,23 @@ public static String convertToGeoJson(LiteralExpressionImpl literalExpression, C return r; } } - + /** + * Many code require static access to this function, hence we will init it somewhere as bean and then + * set it to the static instance for sharing + * @param input - A geometry text input + * @return - The converted geometry + */ + public static Optional readGeometry(Object input) { + return self.readCachedGeometry(input); + } /** * Please use this function as it contains the parser with enough decimal to make it work. * * @param input - A Json of GeoJson * @return - An GeometryCollection that represent the GeoJson */ - public static Optional readGeometry(Object input) { + @Cacheable(STRING_TO_GEOMETRY) + public Optional readCachedGeometry(Object input) { try { String j; if (!(input instanceof String)) { @@ -225,23 +234,7 @@ public static Optional readGeometry(Object input) { } else { j = (String) input; } - - if (cacheManager != null) { - Cache cache = cacheManager.getCache(STRING_TO_GEOMETRY); - - if (cache != null) { - Geometry geometry = cache.get(j); - if (geometry == null) { - geometry = json.read(j); - cache.put(j, geometry); - } - return Optional.of(geometry); - } - } - else { - // We have not setup cache manager in test - return Optional.of(json.read(j)); - } + return Optional.of(json.read(j)); } catch (IOException e) { // Do nothing