Search code examples
multithreadingflaskmod-wsgibackground-process

Run scheduled task with APScheduler with flask (using mod_wsgi)


I am trying to send an email in the background at a specific time everyday in flask. The app hangs just about when I add a job, and I think I am having an issue with threading. The config looks like this

jobstores = {
    'default': SQLAlchemyJobStore(url='path_to_my_db')
        }
executors = {
    'default': ThreadPoolExecutor(5),
    'processpool': ProcessPoolExecutor(3)
        }
job_defaults = {
    'coalesce': False,
    'max_instances': 3
        }
scheduler = BackgroundScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
scheduler.start()

then am adding my job

def send_reports():
     msg = Message("Microphone testing 1, 2",
     recipients=["me@mycompany.com"])
     mail.send(msg)
scheduler.add_job(send_reports, 'cron', hour=8, minute=23)

If i comment out scheduler.add_job line the app runs normally

In the virtual host I have the lines

WSGIDaemonProcess www.mycomapny.com processes=2 threads=5
WSGIScriptAlias / /var/www/html/myapp.wsgi

Will appreciate your assistance


Solution

  • I Finally managed to send emails with APSchedular.

    My settings in Apache Virtual host to allow multiple threads (am using mod_wsgi)

    WSGIDaemonProcess app threads=15 maximum-requests=10000
    WSGIScriptAlias / /var/www/html/myapp.wsgi
    WSGIProcessGroup app
    WSGIApplicationGroup %{GLOBAL}
    

    Then in my app, i first import background BackgroundScheduler

    from apscheduler.schedulers.background import BackgroundScheduler
    

    Instantiate my scheduler with a timezone, but use all other default configuration

    scheduler = BackgroundScheduler(timezone='Africa/Nairobi')
    

    Then before first request, i start the scheduler and add the send_reports job

    @app.before_first_request
    def initialize():
        scheduler.start()
        scheduler.add_job(send_reports, 'cron', hour=10, minute=10, end_date='2055-05-30')
    

    Sending the reports as pdf attachment using pdfkit and flask-email was another matter, but the gist of it is installing the right version of wkhtmltopdf and having the right env path, plus making sure you pass app context to flask-mail to send mail in a background thread.

    So this sends reports to specified emails everyday at 1010 am EAT. Hope someone finds this helpful