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 7dd058b5f1 FINERACT-2181: Made Add Accrual Transactions job parallel 
on a loan-basis
7dd058b5f1 is described below

commit 7dd058b5f1ff9391888792c73401514b4dd015b1
Author: Arnold Galovics <[email protected]>
AuthorDate: Tue Mar 25 19:17:27 2025 +0100

    FINERACT-2181: Made Add Accrual Transactions job parallel on a loan-basis
---
 .../service/LoanAccrualsProcessingServiceImpl.java | 40 +++++++++++++++++++---
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
index ac399c9188..553add8a4d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
@@ -36,6 +36,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Future;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
@@ -43,11 +44,14 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.accounting.common.AccountingRuleType;
 import 
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
 import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
+import org.apache.fineract.infrastructure.core.config.TaskExecutorConstant;
 import org.apache.fineract.infrastructure.core.domain.ExternalId;
+import org.apache.fineract.infrastructure.core.domain.FineractContext;
 import 
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import 
org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualAdjustmentTransactionBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
@@ -78,8 +82,11 @@ import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionTemplate;
 
 @Slf4j
 @Component
@@ -100,6 +107,10 @@ public class LoanAccrualsProcessingServiceImpl implements 
LoanAccrualsProcessing
     private final LoanScheduleGeneratorFactory loanScheduleFactory;
     private final LoanRepaymentScheduleTransactionProcessorFactory 
transactionProcessorFactory;
 
+    @Qualifier(TaskExecutorConstant.CONFIGURABLE_TASK_EXECUTOR_BEAN_NAME)
+    private final ThreadPoolTaskExecutor taskExecutor;
+    private final TransactionTemplate transactionTemplate;
+
     /**
      * method adds accrual for batch job "Add Periodic Accrual Transactions" 
and add accruals api for Loan
      */
@@ -143,13 +154,34 @@ public class LoanAccrualsProcessingServiceImpl implements 
LoanAccrualsProcessing
     public void addAccruals(@NotNull LocalDate tillDate) throws 
JobExecutionException {
         List<Loan> loans = 
loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC,
 tillDate,
                 !isChargeOnDueDate());
+
+        List<Future<?>> loanTasks = new ArrayList<>();
+
+        FineractContext context = ThreadLocalContextUtil.getContext();
+
+        loans.forEach(outerLoan -> {
+            loanTasks.add(taskExecutor.submit(() -> {
+                ThreadLocalContextUtil.init(context);
+                transactionTemplate.executeWithoutResult(status -> {
+                    Loan loan = 
loanRepositoryWrapper.findOneWithNotFoundDetection(outerLoan.getId());
+                    setSetHelpers(loan);
+                    try {
+                        log.debug("Adding accruals for loan '{}'", 
loan.getId());
+                        addAccruals(loan, tillDate, false, false, true);
+                        log.debug("Successfully processed loan: '{}' for 
accrual entries", loan.getId());
+                    } catch (Exception e) {
+                        log.error("Failed to add accrual for loan {}", 
loan.getId(), e);
+                        throw new RuntimeException("Failed to add accrual for 
loan " + loan.getId(), e);
+                    }
+                });
+            }));
+        });
+
         List<Throwable> errors = new ArrayList<>();
-        for (Loan loan : loans) {
+        for (Future<?> task : loanTasks) {
             try {
-                setSetHelpers(loan);
-                addAccruals(loan, tillDate, false, false, true);
+                task.get();
             } catch (Exception e) {
-                log.error("Failed to add accrual for loan {}", loan.getId(), 
e);
                 errors.add(e);
             }
         }

Reply via email to