Skip to content

Commit 6b500e2

Browse files
authored
Merge branch 'release' into chore/15380/usage_info
2 parents 0987566 + 3bf3f67 commit 6b500e2

20 files changed

Lines changed: 232 additions & 35 deletions

File tree

app/client/cypress/support/commands.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,17 @@ Cypress.Commands.add("startServerAndRoutes", () => {
770770
});
771771
});
772772

773+
// Stub the BetterBugs recording-link scripts that index.html injects on every
774+
// page load. They play no role in tests, and when the fetch from the external
775+
// CDN flakes the browser evaluates the error response as JS and throws a
776+
// "SyntaxError: Unexpected token" that fails unrelated specs across shards.
777+
// Serve an empty body so the fetch never leaves the CI network.
778+
cy.intercept("GET", "https://pkg.betterbugs.io/**", {
779+
statusCode: 200,
780+
body: "",
781+
headers: { "content-type": "application/javascript" },
782+
});
783+
773784
cy.intercept("PUT", "/api/v1/admin/env", (req) => {
774785
// GHSA-j9gf-vw2f-9hrw: server-side strict-mode now requires Origin to match
775786
// APPSMITH_BASE_URL. Use the live Cypress baseUrl instead of the legacy

app/server/appsmith-interfaces/src/main/java/com/appsmith/external/configurations/connectionpool/ConnectionPoolConfigCE.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44

55
public interface ConnectionPoolConfigCE {
66
Mono<Integer> getMaxConnectionPoolSize();
7+
8+
Mono<Integer> getSocketTimeoutSeconds();
79
}

app/server/appsmith-plugins/mssqlPlugin/src/main/java/com/external/plugins/MssqlPlugin.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,14 +372,14 @@ private Set<String> populateHintMessages(List<String> columnNames) {
372372
@Override
373373
public Mono<HikariDataSource> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
374374
log.debug(Thread.currentThread().getName() + ": datasourceCreate() called for MSSQL plugin.");
375-
return Mono.defer(
376-
() -> connectionPoolConfig.getMaxConnectionPoolSize().flatMap(maxPoolSize -> {
377-
return Mono.fromCallable(() -> {
378-
log.debug(Thread.currentThread().getName() + ": Connecting to SQL Server db");
379-
return createConnectionPool(datasourceConfiguration, maxPoolSize);
380-
})
381-
.subscribeOn(scheduler);
382-
}));
375+
return Mono.defer(() -> Mono.zip(
376+
connectionPoolConfig.getMaxConnectionPoolSize(),
377+
connectionPoolConfig.getSocketTimeoutSeconds())
378+
.flatMap(tuple -> Mono.fromCallable(() -> {
379+
log.debug(Thread.currentThread().getName() + ": Connecting to SQL Server db");
380+
return createConnectionPool(datasourceConfiguration, tuple.getT1(), tuple.getT2());
381+
})
382+
.subscribeOn(scheduler)));
383383
}
384384

385385
@Override
@@ -581,7 +581,8 @@ public static long getPort(Endpoint endpoint) {
581581
* @return connection pool
582582
*/
583583
private static HikariDataSource createConnectionPool(
584-
DatasourceConfiguration datasourceConfiguration, Integer maxPoolSize) throws AppsmithPluginException {
584+
DatasourceConfiguration datasourceConfiguration, Integer maxPoolSize, Integer socketTimeoutSeconds)
585+
throws AppsmithPluginException {
585586

586587
DBAuth authentication = null;
587588
StringBuilder urlBuilder = null;
@@ -600,6 +601,14 @@ private static HikariDataSource createConnectionPool(
600601
// should get tracked (may be falsely for long running queries) as leaked connection
601602
hikariConfig.setLeakDetectionThreshold(LEAK_DETECTION_TIME_MS);
602603

604+
// Send a TCP keepalive probe on idle connections every 150s. Prevents half-open
605+
// sockets caused by NAT idle-eviction (AWS NAT Gateway default is 350s).
606+
hikariConfig.setKeepaliveTime(150_000);
607+
608+
// Bound any single socket read so a half-open connection cannot wedge the pool's
609+
// single-threaded connection-adder. mssql-jdbc takes socketTimeout in milliseconds.
610+
hikariConfig.addDataSourceProperty("socketTimeout", String.valueOf(socketTimeoutSeconds * 1000));
611+
603612
authentication = (DBAuth) datasourceConfiguration.getAuthentication();
604613
if (authentication.getUsername() != null) {
605614
hikariConfig.setUsername(authentication.getUsername());

app/server/appsmith-plugins/mssqlPlugin/src/test/java/com/external/plugins/MssqlTestDBContainerManager.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ private static class MockConnectionPoolConfig implements ConnectionPoolConfig {
2626
public Mono<Integer> getMaxConnectionPoolSize() {
2727
return Mono.just(5);
2828
}
29+
30+
@Override
31+
public Mono<Integer> getSocketTimeoutSeconds() {
32+
return Mono.just(600);
33+
}
2934
}
3035

3136
static MssqlPlugin.MssqlPluginExecutor mssqlPluginExecutor =

app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/plugins/MySQLDatasourceValidationTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ private static class MockConnectionPoolConfig implements ConnectionPoolConfig {
3232
public Mono<Integer> getMaxConnectionPoolSize() {
3333
return Mono.just(5);
3434
}
35+
36+
@Override
37+
public Mono<Integer> getSocketTimeoutSeconds() {
38+
return Mono.just(600);
39+
}
3540
}
3641

3742
static MySqlPlugin.MySqlPluginExecutor pluginExecutor =

app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/plugins/MySqlPluginTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ private static class MockConnectionPoolConfig implements ConnectionPoolConfig {
8383
public Mono<Integer> getMaxConnectionPoolSize() {
8484
return Mono.just(5);
8585
}
86+
87+
@Override
88+
public Mono<Integer> getSocketTimeoutSeconds() {
89+
return Mono.just(600);
90+
}
8691
}
8792

8893
static MySqlPlugin.MySqlPluginExecutor pluginExecutor =

app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/plugins/MySqlStaleConnectionErrorMessageTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ private static class MockConnectionPoolConfig implements ConnectionPoolConfig {
3333
public Mono<Integer> getMaxConnectionPoolSize() {
3434
return Mono.just(5);
3535
}
36+
37+
@Override
38+
public Mono<Integer> getSocketTimeoutSeconds() {
39+
return Mono.just(600);
40+
}
3641
}
3742

3843
static MySqlPlugin.MySqlPluginExecutor pluginExecutor =

app/server/appsmith-plugins/oraclePlugin/src/main/java/com/external/plugins/OraclePlugin.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.external.plugins;
22

3+
import com.appsmith.external.configurations.connectionpool.ConnectionPoolConfig;
34
import com.appsmith.external.constants.DataType;
45
import com.appsmith.external.dtos.ExecuteActionDTO;
56
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
@@ -92,6 +93,12 @@ public OraclePlugin(PluginWrapper wrapper) {
9293
public static class OraclePluginExecutor implements SmartSubstitutionInterface, PluginExecutor<HikariDataSource> {
9394
public static final Scheduler scheduler = Schedulers.boundedElastic();
9495

96+
private final ConnectionPoolConfig connectionPoolConfig;
97+
98+
public OraclePluginExecutor(ConnectionPoolConfig connectionPoolConfig) {
99+
this.connectionPoolConfig = connectionPoolConfig;
100+
}
101+
95102
@Override
96103
public Mono<HikariDataSource> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
97104
log.debug(Thread.currentThread().getName() + ": datasourceCreate() called for Oracle plugin.");
@@ -104,11 +111,12 @@ public Mono<HikariDataSource> datasourceCreate(DatasourceConfiguration datasourc
104111
e.getMessage()));
105112
}
106113

107-
return Mono.fromCallable(() -> {
108-
log.debug(Thread.currentThread().getName() + ": Connecting to Oracle db");
109-
return createConnectionPool(datasourceConfiguration);
110-
})
111-
.subscribeOn(scheduler);
114+
return connectionPoolConfig.getSocketTimeoutSeconds().flatMap(socketTimeoutSeconds -> Mono.fromCallable(
115+
() -> {
116+
log.debug(Thread.currentThread().getName() + ": Connecting to Oracle db");
117+
return createConnectionPool(datasourceConfiguration, socketTimeoutSeconds);
118+
})
119+
.subscribeOn(scheduler));
112120
}
113121

114122
@Override

app/server/appsmith-plugins/oraclePlugin/src/main/java/com/external/plugins/utils/OracleDatasourceUtils.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ private static String getSampleColumnData(String type) {
378378
}
379379
}
380380

381-
public static HikariDataSource createConnectionPool(DatasourceConfiguration datasourceConfiguration)
381+
public static HikariDataSource createConnectionPool(
382+
DatasourceConfiguration datasourceConfiguration, Integer socketTimeoutSeconds)
382383
throws AppsmithPluginException {
383384
HikariConfig config = new HikariConfig();
384385

@@ -444,6 +445,14 @@ public static HikariDataSource createConnectionPool(DatasourceConfiguration data
444445
// should get tracked (may be falsely for long running queries) as leaked connection
445446
config.setLeakDetectionThreshold(LEAK_DETECTION_TIME_MS);
446447

448+
// Send a TCP keepalive probe on idle connections every 150s. Prevents half-open
449+
// sockets caused by NAT idle-eviction (AWS NAT Gateway default is 350s).
450+
config.setKeepaliveTime(150_000);
451+
452+
// Bound any single socket read so a half-open connection cannot wedge the pool's
453+
// single-threaded connection-adder. Oracle thin driver takes oracle.jdbc.ReadTimeout in milliseconds.
454+
config.addDataSourceProperty("oracle.jdbc.ReadTimeout", String.valueOf(socketTimeoutSeconds * 1000));
455+
447456
// Now create the connection pool from the configuration
448457
HikariDataSource datasource = null;
449458
try {

app/server/appsmith-plugins/oraclePlugin/src/test/java/com/external/plugins/OracleConnectionRateLimitTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.external.plugins;
22

3+
import com.appsmith.external.configurations.connectionpool.ConnectionPoolConfig;
34
import com.appsmith.external.models.DatasourceConfiguration;
45
import org.junit.jupiter.api.Test;
56
import org.testcontainers.containers.OracleContainer;
@@ -16,7 +17,20 @@
1617
@Testcontainers
1718
public class OracleConnectionRateLimitTest {
1819

19-
OraclePlugin.OraclePluginExecutor oraclePluginExecutor = new OraclePlugin.OraclePluginExecutor();
20+
private static class MockConnectionPoolConfig implements ConnectionPoolConfig {
21+
@Override
22+
public Mono<Integer> getMaxConnectionPoolSize() {
23+
return Mono.just(5);
24+
}
25+
26+
@Override
27+
public Mono<Integer> getSocketTimeoutSeconds() {
28+
return Mono.just(600);
29+
}
30+
}
31+
32+
OraclePlugin.OraclePluginExecutor oraclePluginExecutor =
33+
new OraclePlugin.OraclePluginExecutor(new MockConnectionPoolConfig());
2034

2135
@SuppressWarnings("rawtypes") // The type parameter for the container type is just itself and is pseudo-optional.
2236
@Container

0 commit comments

Comments
 (0)