mitlist/be/app/core/scheduler.py
Mohamad.Elsena 5018ce02f7 feat: Implement recurring expenses feature with scheduling and management
- Added support for recurring expenses, allowing users to define recurrence patterns (daily, weekly, monthly, yearly) for expenses.
- Introduced `RecurrencePattern` model to manage recurrence details and linked it to the `Expense` model.
- Implemented background job scheduling using APScheduler to automatically generate new expenses based on defined patterns.
- Updated expense creation logic to handle recurring expenses, including validation and database interactions.
- Enhanced frontend components to allow users to create and manage recurring expenses through forms and lists.
- Updated documentation to reflect new features and usage guidelines for recurring expenses.
2025-05-22 16:37:14 +02:00

69 lines
2.1 KiB
Python

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.triggers.cron import CronTrigger
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from app.core.config import settings
from app.jobs.recurring_expenses import generate_recurring_expenses
from app.db.session import async_session
import logging
logger = logging.getLogger(__name__)
# Configure the scheduler
jobstores = {
'default': SQLAlchemyJobStore(url=settings.SQLALCHEMY_DATABASE_URI)
}
executors = {
'default': ThreadPoolExecutor(20)
}
job_defaults = {
'coalesce': False,
'max_instances': 1
}
scheduler = AsyncIOScheduler(
jobstores=jobstores,
executors=executors,
job_defaults=job_defaults,
timezone='UTC'
)
async def run_recurring_expenses_job():
"""Wrapper function to run the recurring expenses job with a database session."""
try:
async with async_session() as session:
await generate_recurring_expenses(session)
except Exception as e:
logger.error(f"Error running recurring expenses job: {str(e)}")
raise
def init_scheduler():
"""Initialize and start the scheduler."""
try:
# Add the recurring expenses job
scheduler.add_job(
run_recurring_expenses_job,
trigger=CronTrigger(hour=0, minute=0), # Run at midnight UTC
id='generate_recurring_expenses',
name='Generate Recurring Expenses',
replace_existing=True
)
# Start the scheduler
scheduler.start()
logger.info("Scheduler started successfully")
except Exception as e:
logger.error(f"Error initializing scheduler: {str(e)}")
raise
def shutdown_scheduler():
"""Shutdown the scheduler gracefully."""
try:
scheduler.shutdown()
logger.info("Scheduler shut down successfully")
except Exception as e:
logger.error(f"Error shutting down scheduler: {str(e)}")
raise