Files
email-organizer/app/scheduler.py
2025-08-11 19:26:40 -07:00

107 lines
4.0 KiB
Python

import logging
import time
from datetime import datetime, timedelta
from threading import Thread
from app.models import User
from app.email_processor import EmailProcessor
from app import create_app
class Scheduler:
"""
Background scheduler for email processing tasks.
Runs as a separate thread to process emails at regular intervals.
"""
def __init__(self, app=None, interval_minutes=5):
self.app = app
self.interval = interval_minutes * 60 # Convert to seconds
self.thread = None
self.running = False
self.logger = logging.getLogger(__name__)
if app:
self.init_app(app)
def init_app(self, app):
"""Initialize the scheduler with a Flask application."""
self.app = app
# Store scheduler in app extensions
if not hasattr(app, 'extensions'):
app.extensions = {}
app.extensions['scheduler'] = self
def start(self):
"""Start the background scheduler thread."""
if self.running:
self.logger.warning("Scheduler is already running")
return
self.running = True
self.thread = Thread(target=self._run, daemon=True)
self.thread.start()
self.logger.info(f"Scheduler started with {self.interval//60} minute interval")
def stop(self):
"""Stop the background scheduler."""
self.running = False
if self.thread:
self.logger.info("Scheduler stopped")
self.thread.join()
def _run(self):
"""Main loop for the scheduler."""
# Wait a moment before first run to allow app to start
time.sleep(5)
while self.running:
try:
self.logger.info("Starting scheduled email processing")
self.process_all_users()
# Calculate next run time
next_run = datetime.now() + timedelta(seconds=self.interval)
self.logger.info(f"Next run at {next_run.strftime('%Y-%m-%d %H:%M:%S')}")
# Sleep for the interval, checking every 10 seconds if we should stop
slept = 0
while self.running and slept < self.interval:
sleep_time = min(10, self.interval - slept)
time.sleep(sleep_time)
slept += sleep_time
except Exception as e:
self.logger.error(f"Error in scheduler: {str(e)}")
# Continue running even if there's an error
continue
def process_all_users(self):
"""Process emails for all users."""
with self.app.app_context():
try:
# Get all users
users = User.query.all()
if not users:
self.logger.info("No users found for processing")
return
self.logger.info(f"Processing emails for {len(users)} users")
# Process each user's emails
for user in users:
try:
processor = EmailProcessor(user)
result = processor.process_user_emails()
self.logger.info(f"Completed processing for user {user.email}: "
f"{result['success_count']} success, "
f"{result['error_count']} errors, "
f"{len(result['processed_folders'])} folders processed")
except Exception as e:
self.logger.error(f"Error processing emails for user {user.email}: {str(e)}")
continue
except Exception as e:
self.logger.error(f"Error in process_all_users: {str(e)}")