Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FINERACT-2081: Avoid creating unnecessary connection pools #4216

Merged
merged 1 commit into from
Dec 11, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.fineract.infrastructure.configuration.exception.GlobalConfigurationException;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.JdbcTemplateFactory;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
Expand All @@ -50,6 +51,7 @@ private void validateGlobalConfigurationNames() {

if (isNotEmpty(tenants)) {
for (FineractPlatformTenant tenant : tenants) {
ThreadLocalContextUtil.setTenant(tenant);
validateGlobalConfigurationForIndividualTenant(tenant);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
*/
package org.apache.fineract.infrastructure.core.service;

import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
Expand All @@ -30,15 +29,13 @@
@Component
public class JdbcTemplateFactory {

private final TenantDataSourceFactory tenantDataSourceFactory;
private final RoutingDataSource routingDataSource;

public JdbcTemplate create(FineractPlatformTenant tenant) {
DataSource tenantDataSource = tenantDataSourceFactory.create(tenant);
return new JdbcTemplate(tenantDataSource);
return new JdbcTemplate(routingDataSource);
}

public NamedParameterJdbcTemplate createNamedParameterJdbcTemplate(FineractPlatformTenant tenant) {
DataSource tenantDataSource = tenantDataSourceFactory.create(tenant);
return new NamedParameterJdbcTemplate(tenantDataSource);
return new NamedParameterJdbcTemplate(routingDataSource);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import static org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection.toProtocol;

import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
import org.apache.fineract.infrastructure.core.service.database.DatabasePasswordEncryptor;
Expand All @@ -48,7 +47,7 @@ public TenantDataSourceFactory(@Qualifier("hikariTenantDataSource") HikariDataSo
this.databasePasswordEncryptor = databasePasswordEncryptor;
}

public DataSource create(FineractPlatformTenant tenant) {
public HikariDataSource create(FineractPlatformTenant tenant) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(tenantDataSource.getDriverClassName());
dataSource.setDataSourceProperties(tenantDataSource.getDataSourceProperties());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.JdbcTemplateFactory;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
Expand Down Expand Up @@ -62,6 +63,7 @@ private void validateEventConfigurationForAllTenants() throws ExternalEventConfi

if (isNotEmpty(tenants)) {
for (FineractPlatformTenant tenant : tenants) {
ThreadLocalContextUtil.setTenant(tenant);
validateEventConfigurationForIndividualTenant(tenant, eventClasses);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import com.zaxxer.hikari.HikariDataSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -179,19 +180,20 @@ private ThreadPoolTaskExecutor createTenantUpgradeThreadPoolTaskExecutor() {
*/
private void upgradeIndividualTenant(FineractPlatformTenant tenant) throws LiquibaseException {
log.info("Upgrade for tenant {} has started", tenant.getTenantIdentifier());
DataSource tenantDataSource = tenantDataSourceFactory.create(tenant);
// 'initial_switch' and 'custom_changelog' contexts should be controlled by the application configuration
// settings, and we should not use them to control the script order
if (databaseStateVerifier.isFirstLiquibaseMigration(tenantDataSource)) {
ExtendedSpringLiquibase liquibase = liquibaseFactory.create(tenantDataSource, TENANT_DB_CONTEXT, CUSTOM_CHANGELOG_CONTEXT,
INITIAL_SWITCH_CONTEXT, tenant.getTenantIdentifier());
applyInitialLiquibase(tenantDataSource, liquibase, tenant.getTenantIdentifier(),
(ds) -> !databaseStateVerifier.isTenantOnLatestUpgradableVersion(ds));
try (HikariDataSource tenantDataSource = tenantDataSourceFactory.create(tenant)) {
// 'initial_switch' and 'custom_changelog' contexts should be controlled by the application configuration
// settings, and we should not use them to control the script order
if (databaseStateVerifier.isFirstLiquibaseMigration(tenantDataSource)) {
ExtendedSpringLiquibase liquibase = liquibaseFactory.create(tenantDataSource, TENANT_DB_CONTEXT, CUSTOM_CHANGELOG_CONTEXT,
INITIAL_SWITCH_CONTEXT, tenant.getTenantIdentifier());
applyInitialLiquibase(tenantDataSource, liquibase, tenant.getTenantIdentifier(),
(ds) -> !databaseStateVerifier.isTenantOnLatestUpgradableVersion(ds));
}
SpringLiquibase tenantLiquibase = liquibaseFactory.create(tenantDataSource, TENANT_DB_CONTEXT, CUSTOM_CHANGELOG_CONTEXT,
tenant.getTenantIdentifier());
tenantLiquibase.afterPropertiesSet();
log.info("Upgrade for tenant {} has finished", tenant.getTenantIdentifier());
}
SpringLiquibase tenantLiquibase = liquibaseFactory.create(tenantDataSource, TENANT_DB_CONTEXT, CUSTOM_CHANGELOG_CONTEXT,
tenant.getTenantIdentifier());
tenantLiquibase.afterPropertiesSet();
log.info("Upgrade for tenant {} has finished", tenant.getTenantIdentifier());
}

private void applyInitialLiquibase(DataSource dataSource, ExtendedSpringLiquibase liquibase, String id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ public void onApplicationEvent(ContextRefreshedEvent event) {
if (!jobRegistry.getJobNames().isEmpty()) {
List<FineractPlatformTenant> allTenants = tenantDetailsService.findAllTenants();
allTenants.forEach(tenant -> {
ThreadLocalContextUtil.setTenant(tenant);
NamedParameterJdbcTemplate namedParameterJdbcTemplate = jdbcTemplateFactory.createNamedParameterJdbcTemplate(tenant);
List<String> stuckJobNames = jobExecutionRepository.getStuckJobNames(namedParameterJdbcTemplate);
if (!stuckJobNames.isEmpty()) {
try {
ThreadLocalContextUtil.setTenant(tenant);
HashMap<BusinessDateType, LocalDate> businessDates = businessDateReadPlatformService.getBusinessDates();
ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
ThreadLocalContextUtil.setBusinessDates(businessDates);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import com.zaxxer.hikari.HikariDataSource;
import java.util.List;
import javax.sql.DataSource;
import liquibase.change.custom.CustomTaskChange;
import okhttp3.OkHttpClient;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
Expand All @@ -33,6 +32,7 @@
import org.apache.fineract.infrastructure.core.service.database.DatabasePasswordEncryptor;
import org.apache.fineract.infrastructure.core.service.database.DatabaseType;
import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.migration.ExtendedSpringLiquibaseFactory;
import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier;
Expand Down Expand Up @@ -94,8 +94,8 @@ public TenantDataSourceFactory tenantDataSourceFactory(DatabasePasswordEncryptor
return new TenantDataSourceFactory(null, databasePasswordEncryptor) {

@Override
public DataSource create(FineractPlatformTenant tenant) {
return mock(DataSource.class);
public HikariDataSource create(FineractPlatformTenant tenant) {
return mock(HikariDataSource.class);
}
};
}
Expand All @@ -111,8 +111,8 @@ public HikariDataSource tenantDataSource() {
* DataSource with Mockito RETURNS_MOCKS black magic.
*/
@Bean
public DataSource hikariTenantDataSource() {
HikariDataSource mockDataSource = mock(HikariDataSource.class, Mockito.RETURNS_MOCKS);
public RoutingDataSource hikariTenantDataSource() {
RoutingDataSource mockDataSource = mock(RoutingDataSource.class, Mockito.RETURNS_MOCKS);
return mockDataSource;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import com.zaxxer.hikari.HikariDataSource;
import io.cucumber.java8.En;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -66,7 +67,7 @@ public class LiquibaseStepDefinitions implements En {
private TenantDatabaseUpgradeService tenantDatabaseUpgradeService;
private List<FineractPlatformTenant> allTenants;
private SchemaUpgradeNeededException executionException;
private DataSource defaultTenantDataSource;
private HikariDataSource defaultTenantDataSource;
private Environment environment;

public LiquibaseStepDefinitions() {
Expand Down Expand Up @@ -174,7 +175,7 @@ private void initializeLiquibase(boolean liquibaseEnabled) {
initialTenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
tenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);

defaultTenantDataSource = mock(DataSource.class);
defaultTenantDataSource = mock(HikariDataSource.class);

TenantPasswordEncryptionTask tenantPasswordEncryptor = mock(TenantPasswordEncryptionTask.class);

Expand Down
Loading