英文:
Apscheduler on localhost Flask missed scheduled task by 2 seconds
问题
我在我的Flask应用的__init__.py文件中有以下的apscheduler配置:
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...")
然后我有一个Flask路由(http://127.0.0.1:5000/profile/test-double-email),如果我访问它,会在特定时区每天安排一个任务:
@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'))
我能够成功添加计划任务,打印出我的apscheduler会得到类似于以下的结果:
--------------
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
我一直保持我的Flask应用(app.py)在本地运行,到了20:08,预定的时间,任务没有执行,我会在本地终端上得到以下错误:
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
我不明白的是任务只是晚了2秒,而且默认的错失容忍时间被设定为1分钟... 有人可以解释一下为什么会发生这种情况以及如何修复吗? 奇怪的是,我有一个托管在AWS上的实例,连接到相同的MySQL数据库,托管着apscheduler的作业表,如果我通过网站安排了一个任务,那么任务会正常执行。 另外一个我有的问题是,我的实时服务器也没有运行我在本地安排的任务,所以也许本地安排的任务只能由本地服务器运行?
更新1
apscheduler文档中提到了这个:“限制同时执行的作业实例的数量,默认情况下,每个作业只允许同时运行一个实例。这意味着如果作业即将运行但上一次运行还没有结束,那么最新的运行将被视为错失。可以通过在添加作业时使用max_instances关键字参数来设置调度程序将允许同时运行的特定作业的最大实例数。”,所以也许我得到了“没有订阅历史记录”的错误,因为我的实时和本地服务器都试图在预定时间运行安排的任务?
=> 不好,这没有起作用。将max_instances设置为2也没有起作用。
英文:
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.
答案1
得分: 0
解决我的问题经过数小时的调试和尝试不同的解决方案后,为了节省您的麻烦,上述问题的解决方法是在scheduler.add_job中添加misfire_grace_time=1000
。干杯。此外,我可以确认本地调度程序只会运行通过本地主机添加的作业,而实时服务器调度程序只会运行通过实时网站添加的作业。为什么?我不知道。如果有人知道,请告诉我。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论