Skip to content

Commit

Permalink
Singlestore jdbc: Quarkus native support (#3)
Browse files Browse the repository at this point in the history
* Singlestore jdbc Quarkus native support
  • Loading branch information
Hemantkumar-Chigadani authored Oct 22, 2024
1 parent c9f1397 commit efdd503
Show file tree
Hide file tree
Showing 46 changed files with 1,592 additions and 54 deletions.
46 changes: 44 additions & 2 deletions deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.quarkiverse.jdbc-singlestore</groupId>
<groupId>io.quarkiverse.jdbc</groupId>
<artifactId>quarkus-jdbc-singlestore-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>
Expand All @@ -16,7 +16,7 @@
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.jdbc-singlestore</groupId>
<groupId>io.quarkiverse.jdbc</groupId>
<artifactId>quarkus-jdbc-singlestore</artifactId>
<version>${project.version}</version>
</dependency>
Expand All @@ -25,6 +25,48 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-deployment-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devservices-common</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devservices-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-datasource-deployment-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal-spi</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
<version>${assertj-core.version}</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
<version>${rest-assured.version}</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>jdbc</artifactId>
<version>${testcontainers.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.quarkiverse.jdbc.singlestore.deployment;

import static io.quarkiverse.jdbc.singlestore.runtime.SinglestoreConstants.DB_KIND;

import io.quarkiverse.jdbc.singlestore.runtime.SinglestoreAgroalConnectionConfigurer;
import io.quarkiverse.jdbc.singlestore.runtime.SinglestoreServiceBindingConverter;
import io.quarkus.agroal.spi.JdbcDriverBuildItem;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.processor.BuiltinScope;
import io.quarkus.datasource.deployment.spi.DefaultDataSourceDbKindBuildItem;
import io.quarkus.datasource.deployment.spi.DevServicesDatasourceConfigurationHandlerBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;

public class JDBCSinglestoreProcessor {

private static final String FEATURE = "jdbc-singlestore";

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

@BuildStep
void registerDriver(BuildProducer<JdbcDriverBuildItem> jdbcDriver, BuildProducer<DefaultDataSourceDbKindBuildItem> dbKind) {
jdbcDriver.produce(
new JdbcDriverBuildItem(DB_KIND, "com.singlestore.jdbc.Driver",
"com.singlestore.jdbc.SingleStoreDataSource"));

dbKind.produce(new DefaultDataSourceDbKindBuildItem(DB_KIND));
}

@BuildStep
DevServicesDatasourceConfigurationHandlerBuildItem devDbHandler() {
return DevServicesDatasourceConfigurationHandlerBuildItem.jdbc(DB_KIND);
}

@BuildStep
void configureAgroalConnection(BuildProducer<AdditionalBeanBuildItem> additionalBeans,
Capabilities capabilities) {
if (capabilities.isPresent(Capability.AGROAL)) {
additionalBeans
.produce(new AdditionalBeanBuildItem.Builder().addBeanClass(SinglestoreAgroalConnectionConfigurer.class)
.setDefaultScope(BuiltinScope.APPLICATION.getName())
.setUnremovable()
.build());
}
}

@BuildStep
void registerAuthenticationPlugins(BuildProducer<ServiceProviderBuildItem> serviceProvider) {
// make sure that all plugins are available
serviceProvider
.produce(
ServiceProviderBuildItem.allProvidersFromClassPath("com.singlestore.jdbc.plugin.AuthenticationPlugin"));
}

@BuildStep
void registerCodecs(BuildProducer<ServiceProviderBuildItem> serviceProvider) {
serviceProvider
.produce(ServiceProviderBuildItem.allProvidersFromClassPath("com.singlestore.jdbc.plugin.Codec"));
}

@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
void addNativeImageResources(BuildProducer<NativeImageResourceBuildItem> resources) {
// singlestore.properties is used by com.singlestore.jdbc.util.VersionFactory and is small enough.
// driver.properties is not added because it only provides optional descriptions for
// com.singlestore.jdbc.Driver.getPropertyInfo(), which is probably not even called.
resources.produce(new NativeImageResourceBuildItem("singlestore-jdbc-client.properties"));

// necessary when jdbcUrl contains useSsl=true
resources.produce(new NativeImageResourceBuildItem("deprecated.properties"));
}

@BuildStep
void registerServiceBinding(Capabilities capabilities,
BuildProducer<ServiceProviderBuildItem> serviceProvider) {
if (capabilities.isPresent(Capability.KUBERNETES_SERVICE_BINDING)) {
serviceProvider.produce(
new ServiceProviderBuildItem("io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter",
SinglestoreServiceBindingConverter.class.getName()));
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@

package io.quarkiverse.jdbc.singlestore.deployment;

import java.time.Duration;
import java.util.Set;

import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.startupcheck.MinimumDurationRunningStartupCheckStrategy;
import org.testcontainers.shaded.com.google.common.collect.Sets;
import org.testcontainers.utility.DockerImageName;

public class SinglestoreContainer extends JdbcDatabaseContainer<SinglestoreContainer> {
static final String FULL_IMAGE_NAME = "ghcr.io/singlestore-labs/singlestoredb-dev";
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse(FULL_IMAGE_NAME);
static final Integer SINGLESTORE_PORT = 3306;
private String databaseName;
private final String rootUsername;
private final String rootPassword;
private static final String ROOT_USER = "root";

public SinglestoreContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public SinglestoreContainer(DockerImageName dockerImageName) {
super(dockerImageName);
this.rootUsername = ROOT_USER;
this.rootPassword = ROOT_USER;
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
this.addExposedPort(SINGLESTORE_PORT);
}

public Set<Integer> getLivenessCheckPortNumbers() {
return Sets.newHashSet(SINGLESTORE_PORT);
}

@Override
public SinglestoreContainer withDatabaseName(String dbName) {
this.databaseName = dbName;
return this;
}

protected void configure() {
if (this.rootPassword != null && !this.rootPassword.isEmpty()) {
this.addEnv("ROOT_PASSWORD", this.rootPassword);
} else {
if (!"root".equalsIgnoreCase(this.rootUsername)) {
throw new ContainerLaunchException("Empty password can be used only with the root user");
}
}
this.setStartupCheckStrategy(new MinimumDurationRunningStartupCheckStrategy(Duration.ofSeconds(15)));
this.setStartupAttempts(3);
}

public String getDriverClassName() {
return "com.singlestore.jdbc.Driver";
}

public String getJdbcUrl() {
String additionalUrlParams = this.constructUrlParameters("?", "&");
return "jdbc:singlestore://" + this.getHost() + ":" + this.getMappedPort(SINGLESTORE_PORT) + "/" + getDatabaseName()
+ additionalUrlParams;
}

public String getUsername() {
return this.rootUsername;
}

public String getPassword() {
return this.rootPassword;
}

@Override
public String getDatabaseName() {
return databaseName;
}

public String getTestQueryString() {
return "SELECT 1";
}
}
Loading

0 comments on commit efdd503

Please sign in to comment.