added throttling and batch size to processing overdue loans

This commit was merged in pull request #62.
This commit is contained in:
Chinenye Nmoh
2026-01-20 14:03:39 +01:00
parent 46b3c856b1
commit f048dd99ba
4 changed files with 39 additions and 6 deletions
+6 -1
View File
@@ -54,7 +54,12 @@ class Config:
MAIL_USE_SSL = os.getenv('MAIL_USE_SSL', 'False').lower() in ('true', '1', 'yes')
MAIL_DEFAULT_SENDER = ('FirstAdvance', 'firstadvance@dynamikservices.tech')
MAIL_RECEIVER= os.getenv('MAIL_RECEIVER', 'chinenyeumeaku@gmail.com,umeakuchinenye@gmail.com')
OVERDUE_LOAN_BATCH_SIZE = int(os.getenv("OVERDUE_LOAN_BATCH_SIZE", 10))
OVERDUE_LOAN_DELAY_SECONDS = int(os.getenv("OVERDUE_LOAN_DELAY_SECONDS", 5))
OVERDUE_LOAN_BATCH_DELAY_SECONDS = int(
os.getenv("OVERDUE_LOAN_BATCH_DELAY_SECONDS", 5)
)
BANK_CALL_API_TIME_OUT = os.getenv("BANK_CALL_API_TIME_OUT", 100)
BANK_CALL_BASE_URL = os.getenv("BANK_CALL_BASE_URL", "https://bank-emulator.dev.simbrellang.net/api")
BANK_CALL_SMS_BASE_URL= os.getenv("BANK_CALL_SMS_BASE_URL","https://first-advance-middleware-develop.fbn-devops-dev-asenv.appserviceenvironment.net/SMS")
+3 -1
View File
@@ -2,4 +2,6 @@ from enum import Enum
class RepaymentScheduleStatus(str, Enum):
PARTIALLY_PAID = "partially_paid"
REPAID = "repaid"
REPAID = "repaid"
ACTIVE = "active"
OVERDUE = "overdue"
+7 -1
View File
@@ -53,5 +53,11 @@ class CollectLoanHelper:
"countryId": "NG",
"comment": "COLLECT LOAN"
}
@staticmethod
def chunk_list(data, chunk_size):
"""Yield successive chunk_size chunks from data."""
for i in range(0, len(data), chunk_size):
yield data[i:i + chunk_size]
+23 -3
View File
@@ -1,8 +1,10 @@
import time as time_module
from flask import Blueprint, request, jsonify, current_app
import requests
from app.extensions import db
from app.config import settings
from app.helpers.response_helper import ResponseHelper
from app.helpers.collect_loan_helper import CollectLoanHelper
from app.utils.auth import get_headers
from app.utils.logger import logger
from app.integrations.simbrella import SimbrellaClient
@@ -450,15 +452,33 @@ def overdue_loans():
if not overdue_loans:
logger.info("No overdue loans found.")
return ResponseHelper.success(message="No overdue loans found", status_code=200)
#get batch size from settings
loan_delay_seconds = max(0, settings.OVERDUE_LOAN_DELAY_SECONDS)
batch_delay_seconds = max(0, settings.OVERDUE_LOAN_BATCH_DELAY_SECONDS)
batch_size = max(1, settings.OVERDUE_LOAN_BATCH_SIZE)
loan_chunks = list(CollectLoanHelper.chunk_list(overdue_loans, batch_size))
logger.info(f"Found {len(loan_chunks)} loan chunks to process.")
# Step 2: Process each loan
for loan in overdue_loans:
process_overdue_loan(loan)
for chunk_index, loan_chunk in enumerate(loan_chunks):
logger.info(f"Processing chunk {chunk_index + 1} of {len(loan_chunks)} with {len(loan_chunk)} loans.")
for loan in loan_chunk:
try:
process_overdue_loan(loan)
except Exception:
logger.exception(f"Failed processing loan {loan.id}")
finally:
time_module.sleep(loan_delay_seconds)
if chunk_index < len(loan_chunks) - 1:
logger.info(f"Waiting {batch_delay_seconds} seconds before processing next chunk...")
time_module.sleep(batch_delay_seconds) # Delay between chunks
return ResponseHelper.success(message="Processed overdue loans successfully", status_code=200)
except Exception as e:
logger.error(f"Error fetching overdue loans: {e}")
logger.exception(f"Error fetching overdue loans: {e}")
return ResponseHelper.error("Failed to fetch overdue loans", status_code=500, error=str(e))