Files
Krow-workspace/scripts/scheduler_standalone.py
2026-04-07 12:31:22 +05:30

98 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
Standalone scheduler service for Workolik daily email reports.
This runs independently of the Streamlit application to avoid multiple instances.
"""
import os
import sys
import logging
from datetime import datetime
from zoneinfo import ZoneInfo
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
# Add the project root to Python path (scripts/ -> project root)
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from app_core.services.daily_report import main as run_daily_report
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def send_daily_report():
"""Send the daily report with database-based deduplication using existing email_logs table."""
try:
# Check if we already sent today's report
today = datetime.now(ZoneInfo('Asia/Kolkata')).date()
today_str = today.strftime('%Y-%m-%d')
from app_core.db.database import SessionLocal
from sqlalchemy import text
db = SessionLocal()
try:
# Check if daily report was already sent today using existing email_logs table
# Match the exact subject we generate in daily_report.py ("Daily Digest - YYYY-MM-DD")
result = db.execute(
text("SELECT id FROM email_logs WHERE date_for = :date_for AND subject = :subject LIMIT 1"),
{"date_for": today_str, "subject": f"Daily Digest - {today_str}"}
).fetchone()
if result:
logger.info(f"Daily report already sent today ({today}), skipping...")
return
except Exception as e:
logger.error(f"Database error checking existing reports: {e}")
return
finally:
db.close()
logger.info(f"Starting daily report at {datetime.now(ZoneInfo('Asia/Kolkata'))}")
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 main():
"""Main scheduler function."""
logger.info("Starting Workolik Daily Email Scheduler")
# Create scheduler
scheduler = BlockingScheduler(timezone=ZoneInfo('Asia/Kolkata'))
# Schedule daily email at 8:00 PM IST (20:00)
scheduler.add_job(
func=send_daily_report,
trigger=CronTrigger(hour=20, minute=0, timezone=ZoneInfo('Asia/Kolkata')),
id='daily_email_report',
name='Daily Email Report',
replace_existing=True
)
logger.info("Daily email scheduler started - will send reports at 8:00 PM IST")
try:
# Keep the scheduler running
scheduler.start()
except KeyboardInterrupt:
logger.info("Scheduler stopped by user")
scheduler.shutdown()
except Exception as e:
logger.error(f"Scheduler error: {e}")
scheduler.shutdown()
if __name__ == "__main__":
main()