Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ebean-profiling*.xml
/db
/mydb.db
!src/test/ddl-review/*.sql

.DS_Store

# Intellij project files
*.iml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,17 @@ default DataSourceBuilder minConnections(int minConnections) {
@Deprecated(forRemoval = true)
DataSourceBuilder setMinConnections(int minConnections);

/**
* Set the number of initial connections to create when starting.
* <p>
* When not set the initial number of connections will be min connections.
* <p>
* The benefit of setting an initial number of connections is for smoother
* deployment into an active production system where an application will get
* assigned production load.
*/
DataSourceBuilder initialConnections(int initialConnections);

/**
* Set the maximum number of connections the pool can reach. Defaults to 200 when not set.
*/
Expand Down Expand Up @@ -901,6 +912,11 @@ default String driverClassName() {
*/
int getMaxConnections();

/**
* Return the number of initial connections to create on startup.
*/
int getInitialConnections();

/**
* Return the alert implementation to use.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import java.util.Properties;
import java.util.function.Consumer;

import static java.lang.Math.max;
import static java.lang.Math.min;

/**
* Configuration information for a DataSource.
*
Expand Down Expand Up @@ -56,6 +59,7 @@ public class DataSourceConfig implements DataSourceBuilder.Settings {
*/
private String ownerPassword;
private int minConnections = UNSET; // defaults to 2
private int initialConnections = UNSET; // defaults to 2
private int maxConnections = UNSET; // defaults to 200
private int isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
private boolean autoCommit;
Expand Down Expand Up @@ -116,6 +120,7 @@ public DataSourceConfig copy() {
copy.driverClassName = driverClassName;
copy.applicationName = applicationName;
copy.minConnections = minConnections;
copy.initialConnections = initialConnections;
copy.maxConnections = maxConnections;
copy.isolationLevel = isolationLevel;
copy.autoCommit = autoCommit;
Expand Down Expand Up @@ -186,6 +191,9 @@ public DataSourceConfig setDefaults(DataSourceBuilder builder) {
if (minConnections == UNSET) {
minConnections = other.getMinConnections();
}
if (initialConnections == UNSET) {
initialConnections = other.getInitialConnections();
}
if (maxConnections == UNSET) {
maxConnections = other.getMaxConnections();
}
Expand Down Expand Up @@ -423,6 +431,19 @@ public DataSourceConfig setMinConnections(int minConnections) {
return this;
}

@Override
public int getInitialConnections() {
int min = getMinConnections();
int max = getMaxConnections();
return initialConnections == UNSET ? min : min(max(min, initialConnections), max);
}

@Override
public DataSourceConfig initialConnections(int initialConnections) {
this.initialConnections = initialConnections;
return this;
}

@Override
public int getMaxConnections() {
return maxConnections == UNSET ? 200 : maxConnections;
Expand Down Expand Up @@ -810,6 +831,7 @@ private void loadSettings(ConfigPropertiesHelper properties) {
trimPoolFreqSecs = properties.getInt("trimPoolFreqSecs", trimPoolFreqSecs);
maxAgeMinutes = properties.getInt("maxAgeMinutes", maxAgeMinutes);
minConnections = properties.getInt("minConnections", minConnections);
initialConnections = properties.getInt("initialConnections", initialConnections);
maxConnections = properties.getInt("maxConnections", maxConnections);
pstmtCacheSize = properties.getInt("pstmtCacheSize", pstmtCacheSize);
cstmtCacheSize = properties.getInt("cstmtCacheSize", cstmtCacheSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ public void isEmpty() {
assertThat(config.isEmpty()).isFalse();
}

@Test
void initial_expect_inRangeMinMax() {
DataSourceConfig readOnly = new DataSourceConfig();
readOnly.setMinConnections(10);
readOnly.setMaxConnections(30);

readOnly.initialConnections(1);
assertThat(readOnly.getInitialConnections()).isEqualTo(10);

readOnly.initialConnections(100);
assertThat(readOnly.getInitialConnections()).isEqualTo(30);
}

@Test
public void copy() {

Expand Down Expand Up @@ -134,6 +147,7 @@ public void copy() {
assertEquals("sch", copy.getSchema());
assertEquals("cat", copy.catalog());
assertEquals(42, copy.getMinConnections());
assertEquals(42, copy.getInitialConnections());
assertEquals(45, copy.getMaxConnections());

customSource.put("a", "modifiedA");
Expand All @@ -148,6 +162,7 @@ public void copy() {
public void defaults() {

DataSourceConfig config = create();
config.initialConnections(6);

var readOnly = new DataSourceConfig().setDefaults(config);

Expand All @@ -158,6 +173,7 @@ public void defaults() {
assertThat(readOnly.getSchema()).isEqualTo(config.getSchema());
assertThat(readOnly.catalog()).isEqualTo(config.catalog());
assertThat(readOnly.getMinConnections()).isEqualTo(config.getMinConnections());
assertThat(readOnly.getInitialConnections()).isEqualTo(config.getInitialConnections());
assertThat(readOnly.getCustomProperties()).containsKeys("useSSL");
}

Expand All @@ -166,17 +182,20 @@ void setDefaults_expect_connectionsDefault() {
DataSourceConfig readOnly = new DataSourceConfig();
readOnly.setDefaults(create());
assertThat(readOnly.getMinConnections()).isEqualTo(1);
assertThat(readOnly.getInitialConnections()).isEqualTo(1);
assertThat(readOnly.getMaxConnections()).isEqualTo(20);
}

@Test
void setDefaults_when_explicit() {
DataSourceConfig readOnly = new DataSourceConfig();
readOnly.setMinConnections(21);
readOnly.setMaxConnections(22);
readOnly.initialConnections(25);
readOnly.setMaxConnections(32);
readOnly.setDefaults(create());
assertThat(readOnly.getMinConnections()).isEqualTo(21);
assertThat(readOnly.getMaxConnections()).isEqualTo(22);
assertThat(readOnly.getInitialConnections()).isEqualTo(25);
assertThat(readOnly.getMaxConnections()).isEqualTo(32);
}

@Test
Expand All @@ -189,6 +208,7 @@ void setDefaults_when_explicitSameAsNormalDefaults() {
readOnly.setDefaults(create());

assertThat(readOnly.getMinConnections()).isEqualTo(2);
assertThat(readOnly.getInitialConnections()).isEqualTo(2);
assertThat(readOnly.getMaxConnections()).isEqualTo(200);
}

Expand All @@ -210,6 +230,7 @@ public void defaults_someOverride() {
assertThat(readOnly.getUrl()).isEqualTo("jdbc:postgresql://127.0.0.2:5432/unit");
assertThat(readOnly.getUsername()).isEqualTo("foo2");
assertThat(readOnly.getMinConnections()).isEqualTo(3);
assertThat(readOnly.getInitialConnections()).isEqualTo(3);
assertThat(readOnly.getMaxConnections()).isEqualTo(20);
assertThat(readOnly.isShutdownOnJvmExit()).isFalse();
assertThat(readOnly.isValidateOnHeartbeat()).isFalse();
Expand Down Expand Up @@ -269,6 +290,7 @@ public void from_prefix() throws IOException {

var builder = DataSourceBuilder.from(props, "bar");
assertConfigValues(builder.settings());
assertThat(builder.settings().getInitialConnections()).isEqualTo(12);
}

@Test
Expand All @@ -288,16 +310,19 @@ public void alsoIf() {

assertThat(builder.settings().getMaxConnections()).isEqualTo(100);
assertThat(builder.settings().getMinConnections()).isEqualTo(3);
assertThat(builder.settings().getInitialConnections()).isEqualTo(3);
}

@Test
public void alsoIf_notApplied() {
var builder = DataSourceBuilder.create()
.alsoIf(() -> false, this::myConfig)
.minConnections(3);
.minConnections(3)
.initialConnections(6);

assertThat(builder.settings().getMaxConnections()).isEqualTo(200);
assertThat(builder.settings().getMinConnections()).isEqualTo(3);
assertThat(builder.settings().getInitialConnections()).isEqualTo(6);
}

private void myConfig(DataSourceBuilder.Settings builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ bar.url=myUrl
bar.readOnlyUrl=myReadOnlyUrl
bar.applicationName=myApp
bar.clientInfo=ClientUser=ciu;ClientHostname=cih
bar.initialConnections=12
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ interface Heartbeat {
private final AtomicBoolean dataSourceUp = new AtomicBoolean(false);
private SQLException dataSourceDownReason;
private final int minConnections;
private final int initialConnections;
private int maxConnections;
private final int waitTimeoutMillis;
private final int pstmtCacheSize;
Expand Down Expand Up @@ -121,6 +122,7 @@ interface Heartbeat {
this.maxStackTraceSize = params.getMaxStackTraceSize();
this.pstmtCacheSize = params.getPstmtCacheSize();
this.minConnections = params.getMinConnections();
this.initialConnections = params.getInitialConnections();
this.maxConnections = params.getMaxConnections();
this.waitTimeoutMillis = params.getWaitTimeoutMillis();
this.heartbeatFreqSecs = params.getHeartbeatFreqSecs();
Expand Down Expand Up @@ -175,7 +177,7 @@ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedE
private void tryEnsureMinimumConnections() {
notifyLock.lock();
try {
queue.ensureMinimumConnections();
queue.createConnections(initialConnections);
// if we successfully come up without an exception, send datasource up
// notification. This makes it easier, because the application needs not
// to implement special handling, if the db comes up the first time or not.
Expand All @@ -193,7 +195,7 @@ private void initialiseConnections() throws SQLException {
long start = System.currentTimeMillis();
dataSourceUp.set(true);
if (failOnStart) {
queue.ensureMinimumConnections();
queue.createConnections(initialConnections);
} else {
tryEnsureMinimumConnections();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,13 @@ private int totalConnections() {
return freeList.size() + busyList.size();
}

void ensureMinimumConnections() throws SQLException {
void createConnections(int numberToAdd) throws SQLException {
lock.lock();
try {
int add = minSize - totalConnections();
if (add > 0) {
for (int i = 0; i < add; i++) {
freeList.add(pool.createConnectionForQueue(connectionId++));
}
notEmpty.signal();
for (int i = 0; i < numberToAdd; i++) {
freeList.add(pool.createConnectionForQueue(connectionId++));
}
notEmpty.signal();
} finally {
lock.unlock();
}
Expand Down Expand Up @@ -360,7 +357,11 @@ void trim(long maxInactiveMillis, long maxAgeMillis) {
try {
if (trimInactiveConnections(maxInactiveMillis, maxAgeMillis)) {
try {
ensureMinimumConnections();
// ensure there are the min connections
int add = minSize - totalConnections();
if (add > 0) {
createConnections(add);
}
} catch (SQLException e) {
Log.error("Error trying to ensure minimum connections", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private ConnectionPool createPool() {
config.setUsername("sa");
config.setPassword("");
config.setMinConnections(1);
config.initialConnections(3);
config.setMaxConnections(10);
config.setMaxInactiveTimeSecs(1);
config.setTrimPoolFreqSecs(1);
Expand All @@ -32,7 +33,7 @@ private ConnectionPool createPool() {
public void test() throws SQLException, InterruptedException {

ConnectionPool pool = createPool();
assertThat(pool.size()).isEqualTo(1);
assertThat(pool.size()).isEqualTo(3);
try {
Connection con1 = pool.getConnection();
Connection con2 = pool.getConnection();
Expand Down
Loading