diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 0564351ff1..d232f7f570 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { api(project(":polaris-persistence-nosql-api")) api(project(":polaris-persistence-nosql-impl")) + api(project(":polaris-persistence-nosql-standalone")) api(project(":polaris-persistence-nosql-testextension")) api(project(":polaris-persistence-nosql-inmemory")) diff --git a/gradle/projects.main.properties b/gradle/projects.main.properties index 11f74e681b..5e22b49fe8 100644 --- a/gradle/projects.main.properties +++ b/gradle/projects.main.properties @@ -65,6 +65,7 @@ polaris-nodes-spi=persistence/nosql/nodes/spi # persistence / database agnostic polaris-persistence-nosql-api=persistence/nosql/persistence/api polaris-persistence-nosql-impl=persistence/nosql/persistence/impl +polaris-persistence-nosql-standalone=persistence/nosql/persistence/standalone polaris-persistence-nosql-testextension=persistence/nosql/persistence/testextension polaris-persistence-nosql-varint=persistence/nosql/persistence/varint # persistence / database specific implementations diff --git a/persistence/nosql/persistence/standalone/build.gradle.kts b/persistence/nosql/persistence/standalone/build.gradle.kts new file mode 100644 index 0000000000..a1676c1810 --- /dev/null +++ b/persistence/nosql/persistence/standalone/build.gradle.kts @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ + +plugins { id("polaris-server") } + +description = + "Polaris NoSQL persistence, standalone non-CDI configuration helpers using smallrye-config" + +dependencies { + implementation(project(":polaris-persistence-nosql-api")) + implementation(project(":polaris-nodes-api")) + + implementation(libs.smallrye.config.core) + + implementation(libs.guava) + implementation(libs.slf4j.api) + + compileOnly(platform(libs.jackson.bom)) + compileOnly("com.fasterxml.jackson.core:jackson-annotations") + + compileOnly(libs.jakarta.annotation.api) + compileOnly(libs.jakarta.validation.api) +} diff --git a/persistence/nosql/persistence/standalone/src/main/java/org/apache/polaris/persistence/nosql/standalone/PersistenceConfigurer.java b/persistence/nosql/persistence/standalone/src/main/java/org/apache/polaris/persistence/nosql/standalone/PersistenceConfigurer.java new file mode 100644 index 0000000000..733b5018f1 --- /dev/null +++ b/persistence/nosql/persistence/standalone/src/main/java/org/apache/polaris/persistence/nosql/standalone/PersistenceConfigurer.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.polaris.persistence.nosql.standalone; + +import io.smallrye.config.PropertiesConfigSource; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; +import java.util.Map; +import org.apache.polaris.persistence.nosql.api.backend.Backend; +import org.apache.polaris.persistence.nosql.api.backend.BackendConfiguration; +import org.apache.polaris.persistence.nosql.api.backend.BackendFactory; +import org.apache.polaris.persistence.nosql.api.backend.BackendLoader; +import org.apache.polaris.persistence.nosql.nodeids.api.NodeManagementConfig; + +/** + * Leverages smallrye-config to get a {@link BackendConfiguration} instance populated with the + * necessary settings to build a {@link Backend} instance. + * + *

{@link #defaultBackendConfigurer()} is especially useful in standalone runnable Java code like + * JMH based benchmarks and in the manually run correctness tests. + */ +@SuppressWarnings({"unchecked", "rawtypes"}) +public class PersistenceConfigurer { + private final SmallRyeConfigBuilder smallRyeConfigBuilder; + private final String name; + + private PersistenceConfigurer(SmallRyeConfigBuilder smallRyeConfigBuilder) { + this.smallRyeConfigBuilder = smallRyeConfigBuilder; + + SmallRyeConfig rootConfig = + smallRyeConfigBuilder + .withMapping(BackendConfiguration.class) + .withMapping(NodeManagementConfig.class) + .build(); + + var backendConfiguration = rootConfig.getConfigMapping(BackendConfiguration.class); + + this.name = + backendConfiguration + .type() + .orElseThrow( + () -> + new IllegalArgumentException( + "No backend name provided, for example via the system property 'polaris.persistence.backend.type', available backend names: " + + BackendLoader.availableFactories() + .map(BackendFactory::name) + .toList())); + } + + public + BackendFactory buildBackendFactory() { + return (BackendFactory) BackendLoader.findFactoryByName(name); + } + + public Backend buildBackendFromConfiguration(BackendFactory factory) { + var configInterface = (Class) factory.configurationInterface(); + var backendConfigObject = + smallRyeConfigBuilder + .withMapping(configInterface) + .build() + .getConfigMapping(configInterface); + + Object backendConfig = factory.buildConfiguration(backendConfigObject); + return factory.buildBackend(backendConfig); + } + + /** + * Sets up a default {@link PersistenceConfigurer} instance that uses smallrye-config default + * sources, which include environment variables and Java system properties as config sources. + */ + public static PersistenceConfigurer defaultBackendConfigurer() { + return backendConfigurer(Map.of()); + } + + public static PersistenceConfigurer backendConfigurer(Map configMap) { + return new PersistenceConfigurer( + new SmallRyeConfigBuilder() + .setAddDefaultSources(true) + .setAddDiscoveredSources(true) + .withValidateUnknown(false) + .withSources(new PropertiesConfigSource(configMap, "configMap"))); + } +}