This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 7f5b87694 FINERACT-1724: Ability to override tenant datasource min/max 
configuration from env variables
7f5b87694 is described below

commit 7f5b87694b5a882c7507d810712fd9ee42cd5b06
Author: Arnold Galovics <[email protected]>
AuthorDate: Mon May 8 13:52:54 2023 +0200

    FINERACT-1724: Ability to override tenant datasource min/max configuration 
from env variables
---
 .../core/config/FineractProperties.java            |  21 +++++
 .../DataSourcePerTenantServiceFactory.java         |  26 ++++-
 .../migration/TenantDatabaseUpgradeService.java    |  27 +++---
 .../src/main/resources/application.properties      |   3 +
 .../DataSourcePerTenantServiceFactoryTest.java     | 105 +++++++++++++++++++++
 5 files changed, 168 insertions(+), 14 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index 2a38776f0..41c05d1f7 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -86,6 +86,27 @@ public class FineractProperties {
         private String readOnlyPassword;
         private String readOnlyParameters;
         private String readOnlyName;
+
+        private FineractConfigProperties config;
+    }
+
+    /**
+     * Configuration properties to override configurations stored in the 
tenants database
+     */
+    @Getter
+    @Setter
+    public static class FineractConfigProperties {
+
+        private int minPoolSize;
+        private int maxPoolSize;
+
+        public boolean isMinPoolSizeSet() {
+            return minPoolSize != -1;
+        }
+
+        public boolean isMaxPoolSizeSet() {
+            return maxPoolSize != -1;
+        }
     }
 
     @Getter
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DataSourcePerTenantServiceFactory.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DataSourcePerTenantServiceFactory.java
index e3e6bfc1b..410b3db96 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DataSourcePerTenantServiceFactory.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DataSourcePerTenantServiceFactory.java
@@ -92,8 +92,8 @@ public class DataSourcePerTenantServiceFactory {
         config.setPoolName(schemaName + "_pool");
         config.setUsername(schemaUsername);
         config.setPassword(databasePasswordEncryptor.decrypt(schemaPassword));
-        config.setMinimumIdle(tenantConnection.getInitialSize());
-        config.setMaximumPoolSize(tenantConnection.getMaxActive());
+        config.setMinimumIdle(getMinPoolSize(tenantConnection));
+        config.setMaximumPoolSize(getMaxPoolSize(tenantConnection));
         config.setValidationTimeout(tenantConnection.getValidationInterval());
         config.setDriverClassName(hikariConfig.getDriverClassName());
         config.setConnectionTestQuery(hikariConfig.getConnectionTestQuery());
@@ -111,4 +111,26 @@ public class DataSourcePerTenantServiceFactory {
         return hikariDataSourceFactory.create(config);
     }
 
+    private int getMaxPoolSize(FineractPlatformTenantConnection 
tenantConnection) {
+        FineractProperties.FineractConfigProperties configOverride = 
fineractProperties.getTenant().getConfig();
+        if (configOverride.isMaxPoolSizeSet()) {
+            int maxPoolSize = configOverride.getMaxPoolSize();
+            log.info("Overriding tenant datasource maximum pool size 
configuration to {}", maxPoolSize);
+            return maxPoolSize;
+        } else {
+            return tenantConnection.getMaxActive();
+        }
+    }
+
+    private int getMinPoolSize(FineractPlatformTenantConnection 
tenantConnection) {
+        FineractProperties.FineractConfigProperties configOverride = 
fineractProperties.getTenant().getConfig();
+        if (configOverride.isMinPoolSizeSet()) {
+            int minPoolSize = configOverride.getMinPoolSize();
+            log.info("Overriding tenant datasource minimum pool size 
configuration to {}", minPoolSize);
+            return minPoolSize;
+        } else {
+            return tenantConnection.getInitialSize();
+        }
+    }
+
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/migration/TenantDatabaseUpgradeService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/migration/TenantDatabaseUpgradeService.java
index 2a19c12aa..c65b6b101 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/migration/TenantDatabaseUpgradeService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/migration/TenantDatabaseUpgradeService.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.infrastructure.core.service.migration;
 
 import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
 
 import java.util.Arrays;
 import java.util.List;
@@ -29,7 +30,6 @@ import liquibase.exception.LiquibaseException;
 import liquibase.integration.spring.SpringLiquibase;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
 import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
@@ -102,19 +102,22 @@ public class TenantDatabaseUpgradeService implements 
InitializingBean {
     }
 
     private void logTenantStoreDetails() {
-        log.info("- fineract.tenant.username: {}", 
fineractProperties.getTenant().getUsername());
+        FineractProperties.FineractTenantProperties tenant = 
fineractProperties.getTenant();
+        log.info("- fineract.tenant.username: {}", tenant.getUsername());
         log.info("- fineract.tenant.password: ****");
-        log.info("- fineract.tenant.parameters: {}", 
fineractProperties.getTenant().getParameters());
-        log.info("- fineract.tenant.timezone: {}", 
fineractProperties.getTenant().getTimezone());
-        log.info("- fineract.tenant.description: {}", 
fineractProperties.getTenant().getDescription());
-        log.info("- fineract.tenant.identifier: {}", 
fineractProperties.getTenant().getIdentifier());
-        log.info("- fineract.tenant.name: {}", 
fineractProperties.getTenant().getName());
+        log.info("- fineract.tenant.parameters: {}", tenant.getParameters());
+        log.info("- fineract.tenant.timezone: {}", tenant.getTimezone());
+        log.info("- fineract.tenant.description: {}", tenant.getDescription());
+        log.info("- fineract.tenant.identifier: {}", tenant.getIdentifier());
+        log.info("- fineract.tenant.name: {}", tenant.getName());
 
-        log.info("- fineract.tenant.readonly.username: {}", 
fineractProperties.getTenant().getReadOnlyUsername());
-        log.info("- fineract.tenant.readonly.password: {}",
-                
StringUtils.isNotBlank(fineractProperties.getTenant().getReadOnlyPassword()) ? 
"****" : "");
-        log.info("- fineract.tenant.readonly.parameters: {}", 
fineractProperties.getTenant().getReadOnlyParameters());
-        log.info("- fineract.tenant.readonly.name: {}", 
fineractProperties.getTenant().getReadOnlyName());
+        String readOnlyUsername = tenant.getReadOnlyUsername();
+        if (isNotBlank(readOnlyUsername)) {
+            log.info("- fineract.tenant.readonly.username: {}", 
readOnlyUsername);
+            log.info("- fineract.tenant.readonly.password: {}", 
isNotBlank(tenant.getReadOnlyPassword()) ? "****" : "");
+            log.info("- fineract.tenant.readonly.parameters: {}", 
tenant.getReadOnlyParameters());
+            log.info("- fineract.tenant.readonly.name: {}", 
tenant.getReadOnlyName());
+        }
 
     }
 
diff --git a/fineract-provider/src/main/resources/application.properties 
b/fineract-provider/src/main/resources/application.properties
index 24252be91..009b11daf 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -44,6 +44,9 @@ 
fineract.tenant.read-only-password=${FINERACT_DEFAULT_TENANTDB_RO_PWD:}
 
fineract.tenant.read-only-parameters=${FINERACT_DEFAULT_TENANTDB_RO_CONN_PARAMS:}
 fineract.tenant.read-only-name=${FINERACT_DEFAULT_TENANTDB_RO_NAME:}
 
+fineract.tenant.config.min-pool-size=${FINERACT_CONFIG_MIN_POOL_SIZE:-1}
+fineract.tenant.config.max-pool-size=${FINERACT_CONFIG_MAX_POOL_SIZE:-1}
+
 fineract.mode.read-enabled=${FINERACT_MODE_READ_ENABLED:true}
 fineract.mode.write-enabled=${FINERACT_MODE_WRITE_ENABLED:true}
 fineract.mode.batch-worker-enabled=${FINERACT_MODE_BATCH_WORKER_ENABLED:true}
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java
index b099cd397..5ead9f5f0 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/DataSourcePerTenantServiceFactoryTest.java
@@ -155,9 +155,16 @@ public class DataSourcePerTenantServiceFactoryTest {
         
given(tenantHikariConfig.isAutoCommit()).willReturn(MASTER_DB_AUTO_COMMIT_ENABLED);
 
         
given(hikariDataSourceFactory.create(any())).willReturn(mock(HikariDataSource.class));
+
+        FineractProperties.FineractConfigProperties configProperties = new 
FineractProperties.FineractConfigProperties();
+        configProperties.setMinPoolSize(-1);
+        configProperties.setMaxPoolSize(-1);
+
         FineractProperties.FineractTenantProperties tenantPropertiesMock = 
mock(FineractProperties.FineractTenantProperties.class);
         
given(tenantPropertiesMock.getEncryption()).willReturn(MASTER_ENCRYPTION);
         
given(tenantPropertiesMock.getMasterPassword()).willReturn(MASTER_MASTER_PASSWORD);
+
+        given(tenantPropertiesMock.getConfig()).willReturn(configProperties);
         given(fineractProperties.getTenant()).willReturn(tenantPropertiesMock);
 
         
given(databasePasswordEncryptor.isMasterPasswordHashValid(any())).willReturn(true);
@@ -195,6 +202,104 @@ public class DataSourcePerTenantServiceFactoryTest {
         assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, 
hikariConfig.isAutoCommit());
     }
 
+    @Test
+    void 
testCreateNewDataSourceFor_ShouldOverridesMinPoolConfiguration_WhenConfigured() 
{
+        // given
+        FineractProperties.FineractModeProperties modeProperties = 
createModeProps(MASTER_DB_AUTO_COMMIT_ENABLED,
+                MASTER_DB_AUTO_COMMIT_ENABLED, MASTER_DB_AUTO_COMMIT_ENABLED, 
MASTER_DB_AUTO_COMMIT_ENABLED);
+        given(fineractProperties.getMode()).willReturn(modeProperties);
+
+        int minPoolSize = 10;
+
+        FineractProperties.FineractConfigProperties config = 
fineractProperties.getTenant().getConfig();
+        config.setMinPoolSize(minPoolSize);
+
+        // when
+        DataSource dataSource = 
underTest.createNewDataSourceFor(defaultTenant.getConnection());
+
+        // then
+        assertNotNull(dataSource);
+        verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture());
+        HikariConfig hikariConfig = hikariConfigCaptor.getValue();
+        assertFalse(hikariConfig.isReadOnly());
+        assertEquals(MASTER_DB_JDBC_URL, hikariConfig.getJdbcUrl());
+        assertEquals(MASTER_DB_SCHEMA_NAME + "_pool", 
hikariConfig.getPoolName());
+        assertEquals(MASTER_DB_USERNAME, hikariConfig.getUsername());
+        assertEquals(MASTER_DB_PASSWORD, hikariConfig.getPassword());
+        assertEquals(minPoolSize, hikariConfig.getMinimumIdle());
+        assertEquals(MASTER_DB_MAX_ACTIVE, hikariConfig.getMaximumPoolSize());
+        assertEquals(MASTER_DB_VALIDATION_INTERVAL, 
hikariConfig.getValidationTimeout());
+        assertEquals(MASTER_DB_DRIVER_CLASS_NAME, 
hikariConfig.getDriverClassName());
+        assertEquals(MASTER_DB_CONN_TEST_QUERY, 
hikariConfig.getConnectionTestQuery());
+        assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, 
hikariConfig.isAutoCommit());
+    }
+
+    @Test
+    void 
testCreateNewDataSourceFor_ShouldOverridesMaxPoolConfiguration_WhenConfigured() 
{
+        // given
+        FineractProperties.FineractModeProperties modeProperties = 
createModeProps(MASTER_DB_AUTO_COMMIT_ENABLED,
+                MASTER_DB_AUTO_COMMIT_ENABLED, MASTER_DB_AUTO_COMMIT_ENABLED, 
MASTER_DB_AUTO_COMMIT_ENABLED);
+        given(fineractProperties.getMode()).willReturn(modeProperties);
+
+        int maxPoolSize = 10;
+
+        FineractProperties.FineractConfigProperties config = 
fineractProperties.getTenant().getConfig();
+        config.setMaxPoolSize(maxPoolSize);
+
+        // when
+        DataSource dataSource = 
underTest.createNewDataSourceFor(defaultTenant.getConnection());
+
+        // then
+        assertNotNull(dataSource);
+        verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture());
+        HikariConfig hikariConfig = hikariConfigCaptor.getValue();
+        assertFalse(hikariConfig.isReadOnly());
+        assertEquals(MASTER_DB_JDBC_URL, hikariConfig.getJdbcUrl());
+        assertEquals(MASTER_DB_SCHEMA_NAME + "_pool", 
hikariConfig.getPoolName());
+        assertEquals(MASTER_DB_USERNAME, hikariConfig.getUsername());
+        assertEquals(MASTER_DB_PASSWORD, hikariConfig.getPassword());
+        assertEquals(MASTER_DB_INITIAL_SIZE, hikariConfig.getMinimumIdle());
+        assertEquals(maxPoolSize, hikariConfig.getMaximumPoolSize());
+        assertEquals(MASTER_DB_VALIDATION_INTERVAL, 
hikariConfig.getValidationTimeout());
+        assertEquals(MASTER_DB_DRIVER_CLASS_NAME, 
hikariConfig.getDriverClassName());
+        assertEquals(MASTER_DB_CONN_TEST_QUERY, 
hikariConfig.getConnectionTestQuery());
+        assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, 
hikariConfig.isAutoCommit());
+    }
+
+    @Test
+    void 
testCreateNewDataSourceFor_ShouldOverridesMinAndMaxPoolConfiguration_WhenBothConfigured()
 {
+        // given
+        FineractProperties.FineractModeProperties modeProperties = 
createModeProps(MASTER_DB_AUTO_COMMIT_ENABLED,
+                MASTER_DB_AUTO_COMMIT_ENABLED, MASTER_DB_AUTO_COMMIT_ENABLED, 
MASTER_DB_AUTO_COMMIT_ENABLED);
+        given(fineractProperties.getMode()).willReturn(modeProperties);
+
+        int minPoolSize = 10;
+        int maxPoolSize = 10;
+
+        FineractProperties.FineractConfigProperties config = 
fineractProperties.getTenant().getConfig();
+        config.setMinPoolSize(minPoolSize);
+        config.setMaxPoolSize(maxPoolSize);
+
+        // when
+        DataSource dataSource = 
underTest.createNewDataSourceFor(defaultTenant.getConnection());
+
+        // then
+        assertNotNull(dataSource);
+        verify(hikariDataSourceFactory).create(hikariConfigCaptor.capture());
+        HikariConfig hikariConfig = hikariConfigCaptor.getValue();
+        assertFalse(hikariConfig.isReadOnly());
+        assertEquals(MASTER_DB_JDBC_URL, hikariConfig.getJdbcUrl());
+        assertEquals(MASTER_DB_SCHEMA_NAME + "_pool", 
hikariConfig.getPoolName());
+        assertEquals(MASTER_DB_USERNAME, hikariConfig.getUsername());
+        assertEquals(MASTER_DB_PASSWORD, hikariConfig.getPassword());
+        assertEquals(minPoolSize, hikariConfig.getMinimumIdle());
+        assertEquals(maxPoolSize, hikariConfig.getMaximumPoolSize());
+        assertEquals(MASTER_DB_VALIDATION_INTERVAL, 
hikariConfig.getValidationTimeout());
+        assertEquals(MASTER_DB_DRIVER_CLASS_NAME, 
hikariConfig.getDriverClassName());
+        assertEquals(MASTER_DB_CONN_TEST_QUERY, 
hikariConfig.getConnectionTestQuery());
+        assertEquals(MASTER_DB_AUTO_COMMIT_ENABLED, 
hikariConfig.isAutoCommit());
+    }
+
     @Test
     void 
testCreateNewDataSourceFor_ShouldUseReadOnlyConfiguration_WhenInReadOnlyMode() {
         // given

Reply via email to