107 lines
4.0 KiB
Python
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)}") |