Skip to content

Commit 6bb3d4c

Browse files
committed
jdbc: make sure default pool size is never less than 10 fix #915
1 parent 7bec702 commit 6bb3d4c

File tree

3 files changed

+83
-31
lines changed

3 files changed

+83
-31
lines changed

modules/jooby-jdbc/src/main/java/org/jooby/jdbc/Jdbc.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,8 @@ public final class Jdbc implements Jooby.Module {
442442
.orElse(parts.get(parts.size() - 1)));
443443
};
444444

445+
private static final int DEFAULT_POOL_SIZE = 10;
446+
445447
@SuppressWarnings("rawtypes")
446448
private final List<BiConsumer> callback = new ArrayList<>();
447449

@@ -594,7 +596,7 @@ private Config dbConfig(final String key, final Config source) {
594596
}
595597

596598
private HikariConfig hikariConfig(final String url, final String key, final String db,
597-
final Config config) {
599+
final Config conf) {
598600
Properties props = new Properties();
599601

600602
BiConsumer<String, Entry<String, ConfigValue>> dumper = (prefix, entry) -> {
@@ -604,15 +606,15 @@ private HikariConfig hikariConfig(final String url, final String key, final Stri
604606
};
605607

606608
Throwing.Function<String, Config> dbconf = Throwing.<String, Config>throwingFunction(
607-
path -> config.getConfig(path))
609+
path -> conf.getConfig(path))
608610
.orElse(ConfigFactory.empty());
609611

610612
Config $hikari = dbconf.apply(key + ".hikari")
611613
.withFallback(dbconf.apply("db." + db + ".hikari"))
612614
.withFallback(dbconf.apply("hikari"));
613615

614616
// figure it out db type.
615-
dbtype = dbtype(url, config);
617+
dbtype = dbtype(url, conf);
616618

617619
/**
618620
* dump properties from less to higher precedence
@@ -621,7 +623,7 @@ private HikariConfig hikariConfig(final String url, final String key, final Stri
621623
* # db.* -> dataSource.*
622624
* # hikari.* -> * (no prefix)
623625
*/
624-
dbtype.ifPresent(type -> dbconf(config, type)
626+
dbtype.ifPresent(type -> dbconf(conf, type)
625627
.entrySet().forEach(entry -> dumper.accept("dataSource.", entry)));
626628

627629
dbconf.apply(key)
@@ -642,6 +644,10 @@ private HikariConfig hikariConfig(final String url, final String key, final Stri
642644
// set pool name
643645
props.setProperty("poolName", dbtype.map(type -> type + "." + db).orElse(db));
644646

647+
Integer defaultPoolSize = Math.max(DEFAULT_POOL_SIZE, conf.getInt("runtime.processors-x2") + 1);
648+
props.setProperty("maximumPoolSize",
649+
props.getOrDefault("maximumPoolSize", defaultPoolSize.toString()).toString());
650+
645651
return new HikariConfig(props);
646652
}
647653

modules/jooby-jdbc/src/main/resources/org/jooby/jdbc/jdbc.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,6 @@ databases {
130130
}
131131
}
132132

133-
hikari.maximumPoolSize = ${runtime.processors-x2}
133+
##
134+
# hikari.maximumPoolSize = Math.max(10, ${runtime.processors-x2})
134135

modules/jooby-jdbc/src/test/java/org/jooby/jdbc/JdbcTest.java

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
System.class})
3333
public class JdbcTest {
3434

35-
static String POOL_SIZE = "9";
35+
static String POOL_SIZE = "12";
3636

3737
private Block onStop = unit -> {
3838
Env env = unit.get(Env.class);
@@ -72,7 +72,35 @@ public void memdb() throws Exception {
7272
.expect(currentTimeMillis(123))
7373
.expect(props("org.h2.jdbcx.JdbcDataSource", "jdbc:h2:mem:123;DB_CLOSE_DELAY=-1", "h2.123",
7474
"sa", "", false))
75-
.expect(hikariConfig())
75+
.expect(hikariConfig(null))
76+
.expect(hikariDataSource())
77+
.expect(serviceKey("db", "h2"))
78+
.expect(serviceKey("123"))
79+
.expect(onStop)
80+
.run(unit -> {
81+
new Jdbc().configure(unit.get(Env.class), dbconf, unit.get(Binder.class));
82+
});
83+
}
84+
85+
@Test
86+
public void minpoolsize() throws Exception {
87+
Config config = ConfigFactory.parseResources(getClass(), "jdbc.conf");
88+
Config dbconf = config.withValue("db", ConfigValueFactory.fromAnyRef("mem"))
89+
.withValue("application.charset", fromAnyRef("UTF-8"))
90+
.withValue("application.name", fromAnyRef("jdbctest"))
91+
.withValue("application.tmpdir", fromAnyRef("target"))
92+
.withValue("runtime.processors-x2", fromAnyRef(2))
93+
.resolve();
94+
95+
new MockUnit(Env.class, Config.class, Binder.class)
96+
.expect(currentTimeMillis(123))
97+
.expect(props("org.h2.jdbcx.JdbcDataSource", "jdbc:h2:mem:123;DB_CLOSE_DELAY=-1", "h2.123",
98+
"sa", "", false, false))
99+
.expect(unit -> {
100+
Properties props = unit.get(Properties.class);
101+
expect(props.setProperty("maximumPoolSize", "10")).andReturn(null);
102+
})
103+
.expect(hikariConfig(2, null))
76104
.expect(hikariDataSource())
77105
.expect(serviceKey("db", "h2"))
78106
.expect(serviceKey("123"))
@@ -95,7 +123,7 @@ public void fsdb() throws Exception {
95123
new MockUnit(Env.class, Config.class, Binder.class)
96124
.expect(props("org.h2.jdbcx.JdbcDataSource", "jdbc:h2:target/jdbctest", "h2.jdbctest",
97125
"sa", "", false))
98-
.expect(hikariConfig())
126+
.expect(hikariConfig(null))
99127
.expect(hikariDataSource())
100128
.expect(serviceKey("db", "h2"))
101129
.expect(serviceKey("jdbctest"))
@@ -139,7 +167,7 @@ public void dbWithCallback() throws Exception {
139167
new MockUnit(Env.class, Config.class, Binder.class)
140168
.expect(props("org.h2.jdbcx.JdbcDataSource", "jdbc:h2:target/jdbctest", "h2.jdbctest",
141169
"sa", "", false))
142-
.expect(hikariConfig())
170+
.expect(hikariConfig(null))
143171
.expect(hikariDataSource())
144172
.expect(serviceKey("jdbctest"))
145173
.expect(serviceKey("db", "h2"))
@@ -174,7 +202,7 @@ public void databaseWithCredentials() throws Exception {
174202
.expect(props("com.mysql.jdbc.jdbc2.optional.MysqlDataSource", "jdbc:mysql://localhost/db",
175203
"mysql.db", "foo", "bar", false))
176204
.expect(mysql)
177-
.expect(hikariConfig())
205+
.expect(hikariConfig(null))
178206
.expect(hikariDataSource())
179207
.expect(serviceKey("db", "mysql"))
180208
.expect(onStop)
@@ -196,7 +224,7 @@ public void derby() throws Exception {
196224
new MockUnit(Env.class, Config.class, Binder.class)
197225
.expect(props("org.apache.derby.jdbc.ClientDataSource", "jdbc:derby:testdb", "derby.testdb",
198226
null, "", false))
199-
.expect(hikariConfig())
227+
.expect(hikariConfig(null))
200228
.expect(hikariDataSource())
201229
.expect(serviceKey("testdb"))
202230
.expect(serviceKey("db", "derby"))
@@ -218,7 +246,7 @@ public void connectionString() throws Exception {
218246
new MockUnit(Env.class, Config.class, Binder.class)
219247
.expect(props("org.apache.derby.jdbc.ClientDataSource", null, "derby.testdb",
220248
null, "", false))
221-
.expect(hikariConfig())
249+
.expect(hikariConfig(null))
222250
.expect(unit -> {
223251
Properties props = unit.mock(Properties.class);
224252
expect(props.setProperty("url", "jdbc:derby:testdb")).andReturn(null);
@@ -249,7 +277,7 @@ public void db2() throws Exception {
249277
new MockUnit(Env.class, Config.class, Binder.class)
250278
.expect(props("com.ibm.db2.jcc.DB2SimpleDataSource", "jdbc:db2://127.0.0.1:50000/SAMPLE",
251279
"db2.SAMPLE", null, "", false))
252-
.expect(hikariConfig())
280+
.expect(hikariConfig(null))
253281
.expect(hikariDataSource())
254282
.expect(serviceKey("SAMPLE"))
255283
.expect(serviceKey("db", "db2"))
@@ -273,7 +301,7 @@ public void hsql() throws Exception {
273301
new MockUnit(Env.class, Config.class, Binder.class)
274302
.expect(props("org.hsqldb.jdbc.JDBCDataSource", "jdbc:hsqldb:file",
275303
"hsqldb.file", null, "", false))
276-
.expect(hikariConfig())
304+
.expect(hikariConfig(null))
277305
.expect(hikariDataSource())
278306
.expect(serviceKey("file"))
279307
.expect(serviceKey("db", "hsqldb"))
@@ -297,7 +325,7 @@ public void mariadb() throws Exception {
297325
new MockUnit(Env.class, Config.class, Binder.class)
298326
.expect(props("org.mariadb.jdbc.MySQLDataSource", "jdbc:mariadb://localhost/db",
299327
"mariadb.db", null, "", false))
300-
.expect(hikariConfig())
328+
.expect(hikariConfig(null))
301329
.expect(hikariDataSource())
302330
.expect(serviceKey("db", "mariadb"))
303331
.expect(onStop)
@@ -322,7 +350,7 @@ public void mysql() throws Exception {
322350
.expect(props("com.mysql.jdbc.jdbc2.optional.MysqlDataSource", "jdbc:mysql://localhost/db",
323351
"mysql.db", null, "", false))
324352
.expect(mysql)
325-
.expect(hikariConfig())
353+
.expect(hikariConfig(null))
326354
.expect(hikariDataSource())
327355
.expect(serviceKey("db", "mysql"))
328356
.expect(onStop)
@@ -354,7 +382,7 @@ public void dbspecific() throws Exception {
354382
Properties props = unit.get(Properties.class);
355383
expect(props.setProperty("dataSource.cachePrepStmts", "false")).andReturn(null);
356384
})
357-
.expect(hikariConfig())
385+
.expect(hikariConfig(null))
358386
.expect(hikariDataSource())
359387
.expect(serviceKey("db", "mysql"))
360388
.expect(onStop)
@@ -366,7 +394,7 @@ public void dbspecific() throws Exception {
366394
@Test
367395
public void setHikariOptions() throws Exception {
368396
long connectionTimeout = 1000;
369-
int maximumPoolSize = 10;
397+
int maximumPoolSize = 12;
370398
long idleTimeout = 800000;
371399

372400
Config config = ConfigFactory.parseResources(getClass(), "jdbc.conf");
@@ -386,12 +414,13 @@ public void setHikariOptions() throws Exception {
386414
"sa", "", false, false))
387415
.expect(unit -> {
388416
Properties props = unit.get(Properties.class);
389-
expect(props.setProperty("maximumPoolSize", "10")).andReturn(null);
417+
expect(props.setProperty("maximumPoolSize", "12")).andReturn(null);
418+
expect(props.setProperty("maximumPoolSize", "12")).andReturn(null);
390419
expect(props.setProperty("connectionTimeout", "1000")).andReturn(null);
391420
expect(props.setProperty("idleTimeout", "800000")).andReturn(null);
392421
expect(props.setProperty("autoCommit", "false")).andReturn(null);
393422
})
394-
.expect(hikariConfig())
423+
.expect(hikariConfig(12))
395424
.expect(hikariDataSource())
396425
.expect(serviceKey("jdbctest"))
397426
.expect(serviceKey("db", "h2"))
@@ -420,7 +449,7 @@ public void overrideDataSource() throws Exception {
420449
expect(properties.setProperty("dataSourceClassName", "test.MyDataSource"))
421450
.andReturn(null);
422451
})
423-
.expect(hikariConfig())
452+
.expect(hikariConfig(null))
424453
.expect(hikariDataSource())
425454
.expect(serviceKey("jdbctest"))
426455
.expect(serviceKey("db", "h2"))
@@ -453,7 +482,7 @@ public void twoDatabases() throws Exception {
453482
expect(properties.setProperty("dataSourceClassName", "test.MyDataSource"))
454483
.andReturn(null);
455484
})
456-
.expect(hikariConfig())
485+
.expect(hikariConfig(null))
457486
.expect(hikariDataSource())
458487
.expect(serviceKey("audit"))
459488
.expect(serviceKey("db.audit", "h2"))
@@ -480,7 +509,7 @@ public void sqlserver() throws Exception {
480509
props("com.microsoft.sqlserver.jdbc.SQLServerDataSource",
481510
"jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks;integratedSecurity=true;",
482511
"sqlserver.AdventureWorks", null, "", false))
483-
.expect(hikariConfig())
512+
.expect(hikariConfig(null))
484513
.expect(hikariDataSource())
485514
.expect(serviceKey("AdventureWorks"))
486515
.expect(serviceKey("db", "sqlserver"))
@@ -505,7 +534,7 @@ public void oracle() throws Exception {
505534
new MockUnit(Env.class, Config.class, Binder.class)
506535
.expect(props("oracle.jdbc.pool.OracleDataSource", "jdbc:oracle:thin:@myhost:1521:orcl",
507536
"oracle.orcl", null, "", false))
508-
.expect(hikariConfig())
537+
.expect(hikariConfig(null))
509538
.expect(hikariDataSource())
510539
.expect(serviceKey("orcl"))
511540
.expect(serviceKey("db", "oracle"))
@@ -530,7 +559,7 @@ public void pgsql() throws Exception {
530559
.expect(
531560
props("com.impossibl.postgres.jdbc.PGDataSourceWithUrl", "jdbc:pgsql://server/database",
532561
"pgsql.database", null, "", false))
533-
.expect(hikariConfig())
562+
.expect(hikariConfig(null))
534563
.expect(hikariDataSource())
535564
.expect(serviceKey("database"))
536565
.expect(serviceKey("db", "pgsql"))
@@ -554,7 +583,7 @@ public void postgresql() throws Exception {
554583
new MockUnit(Env.class, Config.class, Binder.class)
555584
.expect(props("org.postgresql.ds.PGSimpleDataSource", "jdbc:postgresql://server/database",
556585
"postgresql.database", null, "", false))
557-
.expect(hikariConfig())
586+
.expect(hikariConfig(null))
558587
.expect(hikariDataSource())
559588
.expect(serviceKey("database"))
560589
.expect(serviceKey("db", "postgresql"))
@@ -578,7 +607,7 @@ public void sybase() throws Exception {
578607
new MockUnit(Env.class, Config.class, Binder.class)
579608
.expect(props("com.sybase.jdbcx.SybDataSource", "jdbc:jtds:sybase://server/database",
580609
"sybase.database", null, "", false))
581-
.expect(hikariConfig())
610+
.expect(hikariConfig(null))
582611
.expect(hikariDataSource())
583612
.expect(serviceKey("database"))
584613
.expect(serviceKey("db", "sybase"))
@@ -602,7 +631,7 @@ public void firebirdsql() throws Exception {
602631
new MockUnit(Env.class, Config.class, Binder.class)
603632
.expect(props("org.firebirdsql.pool.FBSimpleDataSource", "jdbc:firebirdsql:host:mydb",
604633
"firebirdsql.mydb", null, "", false))
605-
.expect(hikariConfig())
634+
.expect(hikariConfig(null))
606635
.expect(hikariDataSource())
607636
.expect(serviceKey("mydb"))
608637
.expect(serviceKey("db", "firebirdsql"))
@@ -626,7 +655,7 @@ public void sqlite() throws Exception {
626655
new MockUnit(Env.class, Config.class, Binder.class)
627656
.expect(props("org.sqlite.SQLiteDataSource", "jdbc:sqlite:testdb",
628657
"sqlite.testdb", null, "", false))
629-
.expect(hikariConfig())
658+
.expect(hikariConfig(null))
630659
.expect(hikariDataSource())
631660
.expect(serviceKey("testdb"))
632661
.expect(serviceKey("db", "sqlite"))
@@ -652,7 +681,7 @@ public void unknownDb() throws Exception {
652681
new MockUnit(Env.class, Config.class, Binder.class)
653682
.expect(props("custom.DS", "jdbc:custom:testdb",
654683
"custom.testdb", null, "", false))
655-
.expect(hikariConfig())
684+
.expect(hikariConfig(null))
656685
.expect(hikariDataSource())
657686
.expect(serviceKey("testdb"))
658687
.expect(serviceKey("db", "custom"))
@@ -688,9 +717,25 @@ private Block serviceKey(final String db, String dbtype) {
688717
};
689718
}
690719

691-
private Block hikariConfig() {
720+
private Block hikariConfig(Object poolsize) {
721+
return hikariConfig(Integer.parseInt(POOL_SIZE) + 1, poolsize);
722+
}
723+
724+
private Block hikariConfig(Integer defpoolsize, Object poolsize) {
692725
return unit -> {
693726
Properties properties = unit.get(Properties.class);
727+
if (poolsize == null) {
728+
if (defpoolsize < 10) {
729+
expect(properties.getOrDefault("maximumPoolSize", "10"))
730+
.andReturn("10");
731+
} else {
732+
expect(properties.getOrDefault("maximumPoolSize", defpoolsize.toString()))
733+
.andReturn(POOL_SIZE);
734+
}
735+
} else {
736+
expect(properties.getOrDefault("maximumPoolSize", defpoolsize.toString()))
737+
.andReturn(poolsize);
738+
}
694739
HikariConfig hikari = unit.constructor(HikariConfig.class)
695740
.build(properties);
696741
unit.registerMock(HikariConfig.class, hikari);

0 commit comments

Comments
 (0)