Search code examples
pythonflaskapscheduler

Apscheduler on localhost Flask missed scheduled task by 2 seconds


I have the following apscheduler config in the init.py file of my Flask app:

from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore

jobstore = SQLAlchemyJobStore(url=database_string, tablename='apscheduler_jobs')
scheduler = BackgroundScheduler(jobstores={'default': jobstore})
if not scheduler.running:
    scheduler.start()
    print("Scheduler main started...")

I then have this Flask route (http://127.0.0.1:5000/profile/test-double-email), that if I go to, would schedule a task daily at a timezone:

@profile_blueprints.route('/test-double-email', methods=['POST'])
@login_required
def test_double_email():

    days = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']

 
    timezone_obj = get_timezone_from_ip_kien("49.181.220.210")

    for day in days:
  
        trigger = CronTrigger(day_of_week=day, hour=20, minute=8, timezone=timezone_obj)
 

        job_name = f'job_driver_test_double_email_daily__{day}'

        scheduler.add_job(
            sendemail,
            trigger=trigger,

            name=job_name,
            jobstore='default'
        )
    return redirect(url_for('Profile.profile'))


I was able to add the scheduled tasks fine, printing out my apschedular would get somethingn like:

--------------
Job ID: d844c5657cad4b4a916f3ebc8d4a1ced
Job Name: job_driver_test_double_email_daily__THU
Next Run Time: 2023-06-29 20:08:00+10:00
Job Function: <function sendemail at 0x13895fb50>
Job Arguments: ()
Job Keyword Arguments: {}
Job Trigger: cron[day_of_week='thu', hour='20', minute='8']
Job Misfire Grace Time: 1
Job Coalesce: True
Job Max Instances: 1

I have keep my flask app running (app.py) locally the whole time and at 20:08pm at the scheduled time, the task was not carried out and i would get this error on my local terminal:

Run time of job "job_driver_test_double_email_daily__THU (trigger: cron[day_of_week='thu', hour='20', minute='8'], next run at: 2023-06-29 20:08:00 AEST)" was missed by 0:00:02.344646

The thing I don't understand is that the task was just missed by 2 seconds, while the misfire grace time had been set defaulting to 1 minute... Can someone pls explain to me why this happens and how to fix this? Weirdly, I have a live AWS instance that is hosting a live website connected to the same mysql database that hosts the apschedular jobs table, and if i scheduled a task through the website, that task would still be carried out fine. Also, another question that I have is, my live server also didn't run the tasks I scheduled locally, so maybe locally scheduled tasks can only be run by the local server?

Update1 the apscheduler documentation said something about this "Limiting the number of concurrently executing instances of a job By default, only one instance of each job is allowed to be run at the same time. This means that if the job is about to be run but the previous run hasn’t finished yet, then the latest run is considered a misfire. It is possible to set the maximum number of instances for a particular job that the scheduler will let run concurrently, by using the max_instances keyword argument when adding the job.", so maybe i got error "no history of having subscription" because both my live and local server is trying to run the scheduled task at scheduled time? =>Nope, this did not work. setting max_instances to 2 didn't work.


Solution

  • After hours of debugging and plugging in different solution, to save you the trouble, the solution to my problem above is adding misfire_grace_time=1000 to scheduler.add_job. Cheers. Also I can confirm that local scheduler will only run jobs added through local host and that live server scheduler will only run jobs added through the live website. Why? I have no idea. If anyone know, pls tell.