galovics commented on code in PR #3120:
URL: https://github.com/apache/fineract/pull/3120#discussion_r1166402604


##########
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/TomcatJdbcDataSourcePerTenantService.java:
##########
@@ -73,4 +83,31 @@ public DataSource retrieveDataSource() {
 
         return actualDataSource;
     }
+
+    @Override
+    public void onApplicationEvent(ContextRefreshedEvent event) {
+        final List<FineractPlatformTenant> allTenants = 
tenantDetailsService.findAllTenants();
+        for (final FineractPlatformTenant tenant : allTenants) {
+            initializeDataSourceConnection(tenant);
+        }
+    }
+
+    private void initializeDataSourceConnection(FineractPlatformTenant tenant) 
{
+        log.debug("Initializing database connection for {}", tenant.getName());
+        final FineractPlatformTenantConnection tenantConnection = 
tenant.getConnection();
+        synchronized (TENANT_TO_DATA_SOURCE_MAP) {

Review Comment:
   @ruchiD this is still not thread-safe since the other accesses are not 
synchronized. 
   
   Let me give you a hint how this should be implemented.
   
   First change the map to be a ConcurrentHashMap
   ```
   private static final Map<Long, DataSource> TENANT_TO_DATA_SOURCE_MAP = new 
ConcurrentHashMap<>();
   ```
   
   Then let's use an atomic operation on the HashMap to prevent the race 
conditions happening due to the check-then-act approach (where one thread is 
seeing a stale value and the other is not).
   
   ```
   String key = tenantConnection.getConnectionId();
   TENANT_TO_DATE_SOURCE_MAP.computeIfAbsent(key, (key) -> {
                   DataSource tenantSpecificDataSource = 
dataSourcePerTenantServiceFactory.createNewDataSourceFor(tenantConnection);
                   try (Connection connection = 
tenantSpecificDataSource.getConnection()) {
                       String url = connection.getMetaData().getURL();
                       log.debug("Established database connection with URL {}", 
url);
                       return tenantSpecificDataSource;
                   } catch (SQLException e) {
                       log.error("Error while initializing database connection 
for {}", tenant.getName(), e);
                   }
   });
   ```
   
   And similarly, you have to do the same at the other points where the map is 
accessed. The key thing is to use operations where ConcurrentHashMap provides 
atomicity guarantess (computeIfAbsent/Present/putIfAbsent/Present/etc)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to