Skip to content

Commit 2e3c5d8

Browse files
author
Lukasz Myslinski
committed
R2dbc initial commit
1 parent f9f4aa1 commit 2e3c5d8

4 files changed

Lines changed: 163 additions & 0 deletions

File tree

modules/r2dbc/build.gradle

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
description = "Testcontainers :: r2dbc"
2+
3+
dependencies {
4+
compile project(':testcontainers')
5+
compile 'io.r2dbc:r2dbc-client:1.0.0.M6'
6+
compile 'io.r2dbc:r2dbc-spi:1.0.0.M6'
7+
}
8+
9+
repositories {
10+
mavenCentral()
11+
maven {
12+
url("https://repo.spring.io/milestone")
13+
}
14+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.testcontainers.containers;
2+
3+
public class R2dbcConnectionParams {
4+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package org.testcontainers.containers;
2+
3+
import io.r2dbc.client.Handle;
4+
import io.r2dbc.client.Query;
5+
import io.r2dbc.client.R2dbc;
6+
import io.r2dbc.spi.ConnectionFactoryMetadata;
7+
import io.r2dbc.spi.Result;
8+
import io.r2dbc.spi.Statement;
9+
import lombok.NonNull;
10+
import org.reactivestreams.Publisher;
11+
import org.rnorth.ducttape.unreliables.Unreliables;
12+
13+
import java.sql.Connection;
14+
import java.sql.Driver;
15+
import java.sql.SQLException;
16+
import java.time.Duration;
17+
import java.time.temporal.TemporalUnit;
18+
import java.util.Properties;
19+
import java.util.concurrent.Future;
20+
import java.util.concurrent.TimeUnit;
21+
22+
import io.r2dbc.spi.ConnectionFactory;
23+
import reactor.core.publisher.Mono;
24+
25+
/**
26+
* Base class for containers that expose a R2DBC connection
27+
*
28+
* @author humblehound
29+
*/
30+
public abstract class R2dbcDatabaseContainer<SELF extends R2dbcDatabaseContainer<SELF>> extends GenericContainer<SELF> {
31+
32+
private int startupTimeoutSeconds = 120;
33+
private int connectTimeoutSeconds = 120;
34+
35+
public R2dbcDatabaseContainer(@NonNull final String dockerImageName) {
36+
super(dockerImageName);
37+
}
38+
39+
public R2dbcDatabaseContainer(@NonNull final Future<String> image) {
40+
super(image);
41+
}
42+
43+
/**
44+
* @return the name of the actual JDBC driver to use
45+
*/
46+
public abstract String getDriverClassName();
47+
48+
/**
49+
* @return the host of the dockerized DB
50+
*/
51+
public abstract String getHost();
52+
53+
/**
54+
* @return the port of the containerized DB
55+
*/
56+
protected abstract String getPort();
57+
58+
/**
59+
* @return the database name
60+
*/
61+
public abstract String getDatabaseName();
62+
63+
/**
64+
* @return the standard database username that should be used for connections
65+
*/
66+
public abstract String getUsername();
67+
68+
/**
69+
* @return the standard password that should be used for connections
70+
*/
71+
public abstract String getPassword();
72+
73+
/**
74+
* @return a test query string suitable for testing that this particular database type is alive
75+
*/
76+
protected abstract String getTestQueryString();
77+
78+
@Override
79+
protected void waitUntilContainerStarted() {
80+
// Repeatedly try and open a connection to the DB and execute a test query
81+
82+
logger().info("Waiting for database connection to become available at {} using query '{}'", getHost(), getTestQueryString());
83+
Unreliables.retryUntilSuccess(startupTimeoutSeconds, TimeUnit.SECONDS, () -> {
84+
85+
if (!isRunning()) {
86+
throw new ContainerLaunchException("Container failed to start");
87+
}
88+
89+
R2dbc r2dbc = new R2dbc(createConnection(""));
90+
91+
int success = r2dbc.inTransaction(handle ->
92+
handle.createQuery(this.getTestQueryString()).mapResult(Result::getRowsUpdated)
93+
).blockFirst();
94+
95+
if (success > 0) {
96+
logger().info("Obtained a connection to container ({})", this.getTestQueryString());
97+
return null;
98+
} else {
99+
throw new SQLException("Failed to execute test query");
100+
}
101+
102+
});
103+
}
104+
105+
/**
106+
* Creates a connection to the underlying containerized database instance.
107+
*
108+
* @param queryString query string parameters that should be appended to the JDBC connection URL.
109+
* The '?' character must be included
110+
* @return a Connection
111+
* @throws SQLException if there is a repeated failure to create the connection
112+
*/
113+
public ConnectionFactory createConnection(String queryString) throws SQLException {
114+
return new ConnectionFactory() {
115+
@Override
116+
public Publisher<? extends io.r2dbc.spi.Connection> create() {
117+
return null;
118+
}
119+
120+
@Override
121+
public ConnectionFactoryMetadata getMetadata() {
122+
return null;
123+
}
124+
};
125+
// final Properties info = new Properties();
126+
// info.put("user", this.getUsername());
127+
// info.put("password", this.getPassword());
128+
// final String url = constructUrlForConnection(queryString);
129+
//
130+
// final Driver jdbcDriverInstance = getJdbcDriverInstance();
131+
//
132+
// try {
133+
// return Unreliables.retryUntilSuccess(getConnectTimeoutSeconds(), TimeUnit.SECONDS, () ->
134+
// DB_CONNECT_RATE_LIMIT.getWhenReady(() ->
135+
// jdbcDriverInstance.connect(url, info)));
136+
// } catch (Exception e) {
137+
// throw new SQLException("Could not create new connection", e);
138+
// }
139+
}
140+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.testcontainers.containers;
2+
3+
public class R2dbcDatabaseContainerProvider {
4+
5+
}

0 commit comments

Comments
 (0)