This commit is contained in:
2026-04-07 12:44:06 +05:30
parent 7f81fc64c1
commit 5dd4196014
49 changed files with 2795 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
import logging
import os
from datetime import datetime
from zoneinfo import ZoneInfo
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.jobstores.memory import MemoryJobStore
from app_core.services.daily_report import main as run_daily_report
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class SchedulerService:
def __init__(self):
self.scheduler = None
self.ist = ZoneInfo("Asia/Kolkata")
def start_scheduler(self):
"""Start the background scheduler for daily email reports."""
if self.scheduler and self.scheduler.running:
logger.info("Scheduler is already running")
return
# Configure job stores and executors
jobstores = {
'default': MemoryJobStore()
}
executors = {
'default': ThreadPoolExecutor(20)
}
job_defaults = {
'coalesce': False,
'max_instances': 1
}
self.scheduler = BackgroundScheduler(
jobstores=jobstores,
executors=executors,
job_defaults=job_defaults,
timezone=self.ist
)
# Schedule daily email at 8:00 PM IST (20:00)
self.scheduler.add_job(
func=self._send_daily_report,
trigger=CronTrigger(hour=20, minute=0, timezone=self.ist),
id='daily_email_report',
name='Daily Email Report',
replace_existing=True
)
# Start the scheduler
self.scheduler.start()
logger.info("Daily email scheduler started - will send reports at 8:00 PM IST")
def stop_scheduler(self):
"""Stop the background scheduler."""
if self.scheduler and self.scheduler.running:
self.scheduler.shutdown()
logger.info("Daily email scheduler stopped")
def _send_daily_report(self):
"""Internal method to send daily report."""
try:
logger.info(f"Starting daily report at {datetime.now(self.ist)}")
result = run_daily_report()
if result == 0:
logger.info("Daily report sent successfully")
else:
logger.warning(f"Daily report failed with exit code: {result}")
except Exception as e:
logger.error(f"Error sending daily report: {str(e)}")
def get_next_run_time(self):
"""Get the next scheduled run time for the daily report."""
if not self.scheduler or not self.scheduler.running:
return None
job = self.scheduler.get_job('daily_email_report')
if job:
return job.next_run_time
return None
def is_running(self):
"""Check if scheduler is running."""
return self.scheduler is not None and self.scheduler.running