From 9af5cd1486275392511b5f33dd4936d105488de8 Mon Sep 17 00:00:00 2001 From: rng Date: Thu, 30 Oct 2025 12:41:14 +1100 Subject: [PATCH 1/2] Cache some heavy load repeat operation --- .../core/configuration/CacheConfig.java | 13 +++++++- .../server/core/mapper/StacToCollections.java | 3 +- .../core/mapper/StacToFeatureCollection.java | 2 +- .../server/core/util/GeometryUtils.java | 30 ++++++++++++++++--- 4 files changed, 40 insertions(+), 8 deletions(-) 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 575c47d0..7a3d3a4e 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,9 +1,11 @@ package au.org.aodn.ogcapi.server.core.configuration; import au.org.aodn.ogcapi.server.core.service.CacheNoLandGeometry; +import au.org.aodn.ogcapi.server.core.util.GeometryUtils; import org.ehcache.config.builders.*; import org.ehcache.config.units.MemoryUnit; import org.ehcache.jsr107.EhcacheCachingProvider; +import org.locationtech.jts.geom.Geometry; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.context.annotation.Bean; @@ -27,6 +29,7 @@ public class CacheConfig { public static final String ALL_NO_LAND_GEOMETRY = "all-noland-geometry"; public static final String ALL_PARAM_VOCABS = "parameter-vocabs"; public static final String ELASTIC_SEARCH_UUID_ONLY = "elastic-search-uuid-only"; + public static final String STRING_TO_GEOMETRY = "string-to-geometry"; @Bean public CacheNoLandGeometry createCacheNoLandGeometry() { @@ -74,9 +77,15 @@ public JCacheCacheManager cacheManager() throws IOException { .withCache(ELASTIC_SEARCH_UUID_ONLY, CacheConfigurationBuilder.newCacheConfigurationBuilder( Object.class, Object.class, - ResourcePoolsBuilder.heap(200) + ResourcePoolsBuilder.heap(50) ).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(5))) ) + .withCache(STRING_TO_GEOMETRY, + CacheConfigurationBuilder.newCacheConfigurationBuilder( + String.class, Geometry.class, + ResourcePoolsBuilder.heap(20000) + ).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(24))) + ) .withCache(GET_CAPABILITIES_WMS_LAYERS, CacheConfigurationBuilder.newCacheConfigurationBuilder( Object.class, Object.class, @@ -95,6 +104,8 @@ public JCacheCacheManager cacheManager() throws IOException { config ); + GeometryUtils.setCacheManager(jCacheManager); + return new JCacheCacheManager(jCacheManager); } } diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToCollections.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToCollections.java index cd956200..cb0f2b77 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToCollections.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToCollections.java @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; import java.util.List; -import java.util.stream.Collectors; @Service @Mapper(componentModel = "spring") @@ -23,7 +22,7 @@ public abstract class StacToCollections implements Converter model, Filter filter) { - List collections = model.getCollections().parallelStream() + List collections = model.getCollections().stream() .map(m -> getCollection(m, filter, hostname)) .toList(); diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToFeatureCollection.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToFeatureCollection.java index 29fa4070..f08c7b07 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToFeatureCollection.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/mapper/StacToFeatureCollection.java @@ -22,7 +22,7 @@ public FeatureCollectionGeoJSON convert(ElasticSearch.SearchResult features = model.getCollections().parallelStream() + List features = model.getCollections().stream() .map(i -> { FeatureGeoJSON feature = new FeatureGeoJSON(); feature.setType(FeatureGeoJSON.TypeEnum.FEATURE); 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 966390d9..0a32d5c5 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 @@ -20,6 +20,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.cache.Cache; +import javax.cache.CacheManager; import java.io.IOException; import java.io.StringWriter; import java.math.BigDecimal; @@ -27,10 +29,15 @@ import java.util.*; import java.util.concurrent.*; +import static au.org.aodn.ogcapi.server.core.configuration.CacheConfig.STRING_TO_GEOMETRY; + 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); @@ -212,13 +219,28 @@ public static String convertToGeoJson(LiteralExpressionImpl literalExpression, C */ public static Optional readGeometry(Object input) { try { + String j; if (!(input instanceof String)) { - input = mapper.writeValueAsString(input); + j = mapper.writeValueAsString(input); + } else { + j = (String) input; } - return Optional.of(json.read(input)); - } catch (IOException e) { - return Optional.empty(); + + 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); + } + } + catch (IOException e) { + // Do nothing } + return Optional.empty(); } /** From 093a8d12576aa906302ad4f0e57963923360ddfe Mon Sep 17 00:00:00 2001 From: rng Date: Thu, 30 Oct 2025 13:44:06 +1100 Subject: [PATCH 2/2] Check null on test where cache manager isn't there --- .../server/core/util/GeometryUtils.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) 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 0a32d5c5..bc838369 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 @@ -226,15 +226,21 @@ public static Optional readGeometry(Object input) { j = (String) input; } - 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); + 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); } - return Optional.of(geometry); + } + else { + // We have not setup cache manager in test + return Optional.of(json.read(j)); } } catch (IOException e) {