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

arnold 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 dbfedf5cf FINERACT-1724: Optimizing the account locking for Loan COB
dbfedf5cf is described below

commit dbfedf5cfdffbddfd400f51498c02a88c0551bd1
Author: Arnold Galovics <[email protected]>
AuthorDate: Tue Mar 28 10:15:47 2023 +0200

    FINERACT-1724: Optimizing the account locking for Loan COB
---
 .../fineract/cob/loan/FetchAndLockLoanTasklet.java | 30 +++++++++++++++++-----
 .../cob/loan/LoanCOBManagerConfiguration.java      |  6 ++++-
 .../cob/loan/FetchAndLockLoanStepDefinitions.java  | 15 +++++++----
 3 files changed, 38 insertions(+), 13 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/FetchAndLockLoanTasklet.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/FetchAndLockLoanTasklet.java
index 80bb45c88..e7c758677 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/FetchAndLockLoanTasklet.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/FetchAndLockLoanTasklet.java
@@ -29,12 +29,16 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.cob.domain.LoanAccountLock;
 import org.apache.fineract.cob.domain.LoanAccountLockRepository;
 import org.apache.fineract.cob.domain.LockOwner;
+import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
 import org.springframework.batch.core.step.tasklet.Tasklet;
 import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 @Slf4j
 @RequiredArgsConstructor
@@ -48,6 +52,8 @@ public class FetchAndLockLoanTasklet implements Tasklet {
 
     private final FineractProperties fineractProperties;
 
+    private final JdbcTemplate jdbcTemplate;
+
     @Override
     public RepeatStatus execute(@NotNull StepContribution contribution, 
@NotNull ChunkContext chunkContext) throws Exception {
         String businessDateParameter = (String) 
contribution.getStepExecution().getJobExecution().getExecutionContext()
@@ -60,8 +66,7 @@ public class FetchAndLockLoanTasklet implements Tasklet {
         }
         List<Long> remainingIds = new ArrayList<>(allNonClosedLoanIds);
 
-        List<List<Long>> remainingIdPartitions = Lists.partition(remainingIds,
-                fineractProperties.getQuery().getInClauseParameterSizeLimit());
+        List<List<Long>> remainingIdPartitions = Lists.partition(remainingIds, 
getInClauseParameterSizeLimit());
         List<LoanAccountLock> loanAccountLocks = new ArrayList<>();
         remainingIdPartitions.forEach(
                 remainingIdPartition -> 
loanAccountLocks.addAll(loanAccountLockRepository.findAllByLoanIdIn(remainingIdPartition)));
@@ -87,10 +92,21 @@ public class FetchAndLockLoanTasklet implements Tasklet {
         return RepeatStatus.FINISHED;
     }
 
-    private void applySoftLock(List<Long> alreadySoftLockedAccounts) {
-        for (Long loanId : alreadySoftLockedAccounts) {
-            LoanAccountLock loanAccountLock = new LoanAccountLock(loanId, 
LockOwner.LOAN_COB_PARTITIONING);
-            loanAccountLockRepository.save(loanAccountLock);
-        }
+    private void applySoftLock(List<Long> accountsToLock) {
+        LocalDate cobBusinessDate = 
ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
+        jdbcTemplate.batchUpdate("""
+                    INSERT INTO m_loan_account_locks (loan_id, version, 
lock_owner, lock_placed_on, lock_placed_on_cob_business_date)
+                    VALUES (?, ?, ?, ?, ?)
+                """, accountsToLock, getInClauseParameterSizeLimit(), (ps, id) 
-> {
+            ps.setLong(1, id);
+            ps.setLong(2, 1);
+            ps.setString(3, LockOwner.LOAN_COB_PARTITIONING.name());
+            ps.setObject(4, DateUtils.getOffsetDateTimeOfTenant());
+            ps.setObject(5, cobBusinessDate);
+        });
+    }
+
+    private int getInClauseParameterSizeLimit() {
+        return fineractProperties.getQuery().getInClauseParameterSizeLimit();
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
index eb8b7695f..27a9cf91c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java
@@ -46,6 +46,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.integration.channel.DirectChannel;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 @Configuration
 @EnableBatchIntegration
@@ -83,6 +84,9 @@ public class LoanCOBManagerConfiguration {
     @Autowired
     private FineractProperties fineractProperties;
 
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
     @Bean
     @JobScope
     public LoanCOBPartitioner 
partitioner(@Value("#{jobExecutionContext['loanIds']}") List<Long> loanIds) {
@@ -114,7 +118,7 @@ public class LoanCOBManagerConfiguration {
     @Bean
     @JobScope
     public FetchAndLockLoanTasklet fetchAndLockLoanTasklet() {
-        return new FetchAndLockLoanTasklet(accountLockRepository, 
retrieveLoanIdService, fineractProperties);
+        return new FetchAndLockLoanTasklet(accountLockRepository, 
retrieveLoanIdService, fineractProperties, jdbcTemplate);
     }
 
     @Bean
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
index 9f893edff..3e82aef45 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java
@@ -20,7 +20,9 @@ package org.apache.fineract.cob.loan;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -43,6 +45,7 @@ import org.springframework.batch.core.JobExecution;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.StepExecution;
 import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 public class FetchAndLockLoanStepDefinitions implements En {
 
@@ -56,6 +59,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
     private FetchAndLockLoanTasklet fetchAndLockLoanTasklet;
     private String action;
     private RepeatStatus result;
+    private JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
 
     public FetchAndLockLoanStepDefinitions() {
         Given("/^The FetchAndLockLoanTasklet.execute method with action 
(.*)$/", (String action) -> {
@@ -97,7 +101,8 @@ public class FetchAndLockLoanStepDefinitions implements En {
             contribution = new StepContribution(stepExecution);
             
contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME,
                     LocalDate.now(ZoneId.systemDefault()).toString());
-            fetchAndLockLoanTasklet = new 
FetchAndLockLoanTasklet(loanAccountLockRepository, retrieveLoanIdService, 
fineractProperties);
+            fetchAndLockLoanTasklet = new 
FetchAndLockLoanTasklet(loanAccountLockRepository, retrieveLoanIdService, 
fineractProperties,
+                    jdbcTemplate);
         });
 
         When("FetchAndLockLoanTasklet.execute method executed", () -> {
@@ -108,7 +113,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
             if ("empty steps".equals(action)) {
                 assertEquals(RepeatStatus.FINISHED, result);
             } else if ("good".equals(action)) {
-                verify(loanAccountLockRepository, 
Mockito.times(3)).save(Mockito.any());
+                verify(jdbcTemplate).batchUpdate(anyString(), any(), anyInt(), 
any());
                 assertEquals(RepeatStatus.FINISHED, result);
                 assertEquals(3,
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
@@ -123,7 +128,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
                                 .get(2));
             } else if ("soft lock".equals(action)) {
-                verify(loanAccountLockRepository, 
Mockito.times(2)).save(Mockito.any());
+                verify(jdbcTemplate).batchUpdate(anyString(), any(), anyInt(), 
any());
                 assertEquals(RepeatStatus.FINISHED, result);
                 assertEquals(3,
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
@@ -138,7 +143,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
                                 .get(2));
             } else if ("inline cob".equals(action)) {
-                verify(loanAccountLockRepository, 
Mockito.times(2)).save(Mockito.any());
+                verify(jdbcTemplate).batchUpdate(anyString(), any(), anyInt(), 
any());
                 assertEquals(RepeatStatus.FINISHED, result);
                 assertEquals(2,
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
@@ -150,7 +155,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))
                                 .get(1));
             } else if ("chunk processing".equals(action)) {
-                verify(loanAccountLockRepository, 
Mockito.times(2)).save(Mockito.any());
+                verify(jdbcTemplate).batchUpdate(anyString(), any(), anyInt(), 
any());
                 assertEquals(RepeatStatus.FINISHED, result);
                 assertEquals(2,
                         ((List) 
contribution.getStepExecution().getJobExecution().getExecutionContext().get(LoanCOBConstant.LOAN_IDS))

Reply via email to