diff --git a/docs/tutorial/PreviewFeatures.md b/docs/tutorial/PreviewFeatures.md index 84cb60a0ee68ecd6a49a90899c3049e29277a217..bdc3dc8800c05ebd64c937911452c8dbd74a2a54 100644 --- a/docs/tutorial/PreviewFeatures.md +++ b/docs/tutorial/PreviewFeatures.md @@ -1,3 +1,15 @@ +## Geoshape Decimation + +In order to improve indexing and search performance for documents with large geometry, the geo-shape of the following +GeoJSON types in the original shape attribute and virtual shape attribute if exists are decimated +by implementing Ramer–Douglas–Peucker algorithm: +- LineString +- MultiLineString +- Polygon +- MultiPolygon + +The feature is enabled for all data partitions since M19. + ## Index extension OSDU Standard index extensions are defined by OSDU Data Definition work-streams with the intent to provide diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/geo/decimator/FeatureFlagCache.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/cache/FeatureFlagCache.java similarity index 94% rename from indexer-core/src/main/java/org/opengroup/osdu/indexer/util/geo/decimator/FeatureFlagCache.java rename to indexer-core/src/main/java/org/opengroup/osdu/indexer/cache/FeatureFlagCache.java index c24d200b7ce3452c89304213d69f0cde47112a9a..d57a5dbffda83a72c785a692da47d0bb3b756b64 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/geo/decimator/FeatureFlagCache.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/cache/FeatureFlagCache.java @@ -13,7 +13,7 @@ * limitations under the License. */ -package org.opengroup.osdu.indexer.util.geo.decimator; +package org.opengroup.osdu.indexer.cache; import org.opengroup.osdu.core.common.cache.VmCache; import org.springframework.stereotype.Component; diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/AugmenterSetting.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/AugmenterSetting.java index 84cc039fe58df7d12391640874a4424e0823794e..d11d41cc38f5b3c7aaf1cd63cfbafd38ca4250eb 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/AugmenterSetting.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/AugmenterSetting.java @@ -1,34 +1,16 @@ package org.opengroup.osdu.indexer.util; -import org.opengroup.osdu.core.common.feature.IFeatureFlag; -import org.opengroup.osdu.core.common.model.http.DpsHeaders; -import org.opengroup.osdu.indexer.util.geo.decimator.FeatureFlagCache; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @Component public class AugmenterSetting { private static final String PROPERTY_NAME = "index-augmenter-enabled"; - @Lazy @Autowired - private FeatureFlagCache cache; - - @Autowired - private DpsHeaders headers; - - @Autowired - private IFeatureFlag iFeatureFlag; + private BooleanFeatureFlagClient booleanFeatureFlagClient; public boolean isEnabled() { - String dataPartitionId = headers.getPartitionId(); - String cacheKey = String.format("%s-%s", dataPartitionId, PROPERTY_NAME); - if (cache != null && cache.containsKey(cacheKey)) - return cache.get(cacheKey); - - boolean isEnabled = iFeatureFlag.isFeatureEnabled(PROPERTY_NAME); - this.cache.put(cacheKey, isEnabled); - return isEnabled; + return booleanFeatureFlagClient.isEnabled(PROPERTY_NAME, false); } } diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClient.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClient.java new file mode 100644 index 0000000000000000000000000000000000000000..f21e0968d976de22c1f2f35daf4e33b17cbe7406 --- /dev/null +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClient.java @@ -0,0 +1,73 @@ +package org.opengroup.osdu.indexer.util; + +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.partition.*; +import org.opengroup.osdu.core.common.util.IServiceAccountJwtClient; +import org.opengroup.osdu.indexer.cache.FeatureFlagCache; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +@Component +public class BooleanFeatureFlagClient { + private static final String TOKEN_PREFIX = "Bearer "; + + @Lazy + @Autowired + private FeatureFlagCache cache; + + @Autowired + private JaxRsDpsLog logger; + + @Autowired + private DpsHeaders headers; + + @Autowired + private IPartitionFactory factory; + + @Autowired + private IServiceAccountJwtClient tokenService; + + public boolean isEnabled(String featureName, boolean defaultValue) { + String dataPartitionId = headers.getPartitionId(); + String cacheKey = String.format("%s-%s", dataPartitionId, featureName); + if (cache != null && cache.containsKey(cacheKey)) + return cache.get(cacheKey); + + boolean isEnabled = defaultValue; + try { + PartitionInfo partitionInfo = getPartitionInfo(dataPartitionId); + isEnabled = getFeatureValue(partitionInfo, featureName, defaultValue); + } catch (Exception e) { + this.logger.error(String.format("PartitionService: Error getting %s for dataPartition with Id: %s. Turn on the feature flag by default.", featureName, dataPartitionId), e); + } + this.cache.put(cacheKey, isEnabled); + return isEnabled; + } + + private PartitionInfo getPartitionInfo(String dataPartitionId) throws PartitionException { + try { + DpsHeaders partitionHeaders = DpsHeaders.createFromMap(headers.getHeaders()); + partitionHeaders.put(DpsHeaders.AUTHORIZATION, this.tokenService.getIdToken(dataPartitionId)); + + IPartitionProvider partitionProvider = this.factory.create(partitionHeaders); + PartitionInfo partitionInfo = partitionProvider.get(dataPartitionId); + return partitionInfo; + } catch (PartitionException e) { + logger.error(String.format("Error getting partition info for data-partition: %s", dataPartitionId), e); + throw e; + } + } + + private boolean getFeatureValue(PartitionInfo partitionInfo, String featureName, boolean defaultValue) { + if(partitionInfo == null || partitionInfo.getProperties() == null) + return defaultValue; + + if(partitionInfo.getProperties().containsKey(featureName)) { + Property property = partitionInfo.getProperties().get(featureName); + return Boolean.parseBoolean((String)property.getValue()); + } + return defaultValue; + } +} diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageIndexerPayloadMapperTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageIndexerPayloadMapperTest.java index 6b7e5027df1771ad4329a9ed20e5247aaa273b11..b56339a96f294e8c8035d7844354cf885a7f1f2d 100644 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageIndexerPayloadMapperTest.java +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageIndexerPayloadMapperTest.java @@ -12,13 +12,12 @@ import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.indexer.IndexSchema; import org.opengroup.osdu.core.common.model.indexer.JobStatus; +import org.opengroup.osdu.indexer.cache.FeatureFlagCache; import org.opengroup.osdu.indexer.schema.converter.config.SchemaConverterPropertiesConfig; import org.opengroup.osdu.indexer.schema.converter.exeption.SchemaProcessingException; import org.opengroup.osdu.indexer.schema.converter.interfaces.IVirtualPropertiesSchemaCache; import org.opengroup.osdu.indexer.schema.converter.tags.SchemaRoot; import org.opengroup.osdu.indexer.schema.converter.tags.VirtualProperties; -import org.opengroup.osdu.indexer.service.mock.PartitionFactoryMock; -import org.opengroup.osdu.indexer.service.mock.PartitionProviderMock; import org.opengroup.osdu.indexer.service.mock.ServiceAccountJwtClientMock; import org.opengroup.osdu.indexer.service.mock.VirtualPropertiesSchemaCacheMock; import org.opengroup.osdu.indexer.util.geo.decimator.*; @@ -46,7 +45,7 @@ import static org.junit.Assert.*; BooleanParser.class, DateTimeParser.class, GeoShapeParser.class, DouglasPeuckerReducer.class, GeoShapeDecimator.class, GeometryDecimator.class, GeometryConversionService.class, FeatureFlagCache.class, DpsHeaders.class, JobStatus.class, SchemaConverterPropertiesConfig.class, JaxRsDpsLog.class, - PartitionFactoryMock.class, PartitionProviderMock.class, ServiceAccountJwtClientMock.class, VirtualPropertiesSchemaCacheMock.class, }) + ServiceAccountJwtClientMock.class, VirtualPropertiesSchemaCacheMock.class, }) public class StorageIndexerPayloadMapperTest { public static final String FIRST_OBJECT_INNER_PROPERTY = "FirstObjectInnerProperty"; diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionFactoryMock.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionFactoryMock.java deleted file mode 100644 index dbe1ee22b0020d99eff0cc1b585c48400ce958e8..0000000000000000000000000000000000000000 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionFactoryMock.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © Schlumberger - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.opengroup.osdu.indexer.service.mock; - -import org.opengroup.osdu.core.common.model.http.DpsHeaders; -import org.opengroup.osdu.core.common.partition.IPartitionFactory; -import org.opengroup.osdu.core.common.partition.IPartitionProvider; - -public class PartitionFactoryMock implements IPartitionFactory { - @Override - public IPartitionProvider create(DpsHeaders dpsHeaders) { - return new PartitionProviderMock(); - } -} diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionProviderMock.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionProviderMock.java deleted file mode 100644 index 55767e8fd7841b2e1e9063fc240dab0cae6b8f22..0000000000000000000000000000000000000000 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/mock/PartitionProviderMock.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright © Schlumberger - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.opengroup.osdu.indexer.service.mock; - -import org.opengroup.osdu.core.common.partition.IPartitionProvider; -import org.opengroup.osdu.core.common.partition.PartitionException; -import org.opengroup.osdu.core.common.partition.PartitionInfo; -import org.opengroup.osdu.core.common.partition.Property; - -import java.util.List; - -public class PartitionProviderMock implements IPartitionProvider { - private static final String PROPERTY_NAME = "indexer-decimation-enabled"; - - @Override - public PartitionInfo get(String s) throws PartitionException { - PartitionInfo partitionInfo = new PartitionInfo(); - Property property = new Property(); - property.setSensitive(false); - property.setValue("true"); - partitionInfo.getProperties().put(PROPERTY_NAME, property); - return partitionInfo; - } - - @Override - public PartitionInfo create(String s, PartitionInfo partitionInfo) throws PartitionException { - return null; - } - - @Override - public void update(String s, PartitionInfo partitionInfo) throws PartitionException { - - } - - @Override - public void delete(String s) throws PartitionException { - - } - - @Override - public List<String> list() throws PartitionException { - return null; - } -} diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClientTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClientTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8b5fb420f4e1269ddcb0bd255a535a172869056d --- /dev/null +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/BooleanFeatureFlagClientTest.java @@ -0,0 +1,127 @@ +/* + * Copyright © Schlumberger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opengroup.osdu.indexer.util; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.partition.*; +import org.opengroup.osdu.core.common.util.IServiceAccountJwtClient; +import org.opengroup.osdu.indexer.cache.FeatureFlagCache; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.HashMap; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(SpringRunner.class) +public class BooleanFeatureFlagClientTest { + private static final String PROPERTY_NAME = "indexer-decimation-enabled"; + + @InjectMocks + private BooleanFeatureFlagClient sut; + + @Mock + private FeatureFlagCache cache; + + @Mock + private JaxRsDpsLog logger; + + @Mock + private DpsHeaders headers; + + @Mock + private IPartitionFactory factory; + + @Mock + private IServiceAccountJwtClient tokenService; + + @Mock + IPartitionProvider partitionProvider; + + @Before + public void setup() { + when(this.headers.getPartitionId()).thenReturn("dataPartitionId"); + when(this.headers.getHeaders()).thenReturn(new HashMap()); + when(this.factory.create(any())).thenReturn(partitionProvider); + when(this.tokenService.getIdToken(anyString())).thenReturn("token"); + } + + @Test + public void isDecimationEnabled_return_true() throws PartitionException { + PartitionInfo partitionInfo = new PartitionInfo(); + Property property = new Property(); + property.setSensitive(false); + property.setValue("true"); + partitionInfo.getProperties().put(PROPERTY_NAME, property); + when(this.partitionProvider.get(anyString())).thenReturn(partitionInfo); + + // Default value won't take any effect + boolean enabled = sut.isEnabled(PROPERTY_NAME, true); + Assert.assertTrue(enabled); + + enabled = sut.isEnabled(PROPERTY_NAME, false); + Assert.assertTrue(enabled); + } + + @Test + public void isDecimationEnabled_return_false_when_property_set_to_false() throws PartitionException { + PartitionInfo partitionInfo = new PartitionInfo(); + Property property = new Property(); + property.setSensitive(false); + property.setValue("false"); + partitionInfo.getProperties().put(PROPERTY_NAME, property); + when(this.partitionProvider.get(anyString())).thenReturn(partitionInfo); + + // Default value won't take any effect + boolean enabled = sut.isEnabled(PROPERTY_NAME, true); + Assert.assertFalse(enabled); + + enabled = sut.isEnabled(PROPERTY_NAME, false); + Assert.assertFalse(enabled); + } + + @Test + public void isDecimationEnabled_return_default_value_when_property_does_not_exist() throws PartitionException { + // The feature flag is enabled by default + PartitionInfo partitionInfo = new PartitionInfo(); + when(this.partitionProvider.get(anyString())).thenReturn(partitionInfo); + boolean enabled = sut.isEnabled(PROPERTY_NAME, true);; + Assert.assertTrue(enabled); + + enabled = sut.isEnabled(PROPERTY_NAME, false);; + Assert.assertFalse(enabled); + } + + @Test + public void isDecimationEnabled_return_default_value_when_partitionProvider_throws_exception() throws PartitionException { + // The feature flag is enabled by default + when(this.partitionProvider.get(anyString())).thenThrow(PartitionException.class); + boolean enabled = sut.isEnabled(PROPERTY_NAME, true);; + Assert.assertTrue(enabled); + + enabled = sut.isEnabled(PROPERTY_NAME, false);; + Assert.assertFalse(enabled); + } + +} diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/geo/decimator/DecimationSettingCacheTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/geo/decimator/DecimationSettingCacheTest.java index c32159b5e1186cefa6f72e4bc478d4095aa97bc9..8ff4451746260b56e9ec1413d89a5c3d5a4bd298 100644 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/geo/decimator/DecimationSettingCacheTest.java +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/geo/decimator/DecimationSettingCacheTest.java @@ -19,6 +19,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.opengroup.osdu.indexer.cache.FeatureFlagCache; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class)