如何解决APScheduler 在 Heroku 上托管的 Flask 应用程序中复制作业
我有一个如下结构的应用程序,它允许用户安排任务来每天早上、下午等查询 FB API 以提取页面/发布数据(在这种情况下是凌晨 3 点)。
我遇到的问题是调度程序将每个作业执行两次,这显然是不可取的。奇怪的是,这个问题似乎不会在本地发生,只有在生产模式下,我在 Heroku 中托管这个,有 1 个 web dyno 和 1 个 worker dyno,每个只有 1 个进程。因此,我倾向于 Heroku 是问题所在。
我有一个页面来列出当前计划的作业,当我检查它时,刷新页面后,相同的作业实例将在两个不同的值之间滑动(下面的屏幕截图)。就好像有两个 BackgroundScheduler 的实例在运行。
我怀疑这是因为 BackgroundScheduler 被启动了两次(一次是在 flasky.py 中,一次是在 tasks.py 中)所以我创建了一个临时解决方案来停止 BackgroundScheduler 的双重初始化,但我仍然遇到同样的问题并且我现在卡住了。任何帮助将不胜感激。
-->app
-->__init__.py
-->decorators.py
-->models.py
-->tasks.py
-->auth
-->__init__.py
-->errors.py
-->forms.py
-->views.py
-->main
-->__init__.py
-->errors.py
-->forms.py
-->views.py
-->static
-->templates
-->migrations
config.py
flasky.py
procfile
requirements.txt
app/flasky.py
from flask import Flask,render_template,session,redirect,url_for,flash
import os
from app import create_app,db
from app.models import User,Role
from datetime import datetime
from flask_migrate import Migrate,upgrade
app = create_app(os.getenv('FLASK_CONfig') or 'default')
app/_ init _.py
from flask import Flask,render_template
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_migrate import Migrate
from flask_sqlalchemy import sqlAlchemy
from config import config
from flask_session import Session
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import sqlAlchemyJobStore
import rq
from redis import Redis
from flask_login import LoginManager
from worker import conn
import os
bootstrap = Bootstrap()
moment = Moment()
db = sqlAlchemy()
scheduler = BackgroundScheduler()
migrate = Migrate()
session= Session()
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
def create_app(config_name='default'):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)
bootstrap.init_app(app)
moment.init_app(app)
migrate.init_app(app,db)
session.init_app(app)
login_manager.init_app(app)
if not scheduler.running:
scheduler.start()
jobstore_url = os.environ.get('DATABASE_URL')
scheduler.add_jobstore(sqlAlchemyJobStore(url=jobstore_url),'sqlalchemy')
from .main import main as main_blueprint
from .auth import auth as auth_blueprint
app.register_blueprint(main_blueprint)
app.register_blueprint(auth_blueprint,url_prefix='/auth')
app.task_queue = rq.Queue('flasky',connection=Redis.from_url(os.environ.get(REdis_URL))
if app.config['SSL_REDIRECT']:
from flask_sslify import SSLify
sslify = SSLify(app)
return app
app/tasks.py
from . import create_app,db
from .models import User,Tokens,Files
from .decorators import token_getter
from flask_login import current_user
import requests
import datetime as dt
import urllib
import os
app = create_app(os.getenv('FLASK_CONfig') or 'default')
<FUNCTIONS HERE>
app/auth/views.py
from flask import render_template,request,flash,current_app,Response
from .. import db,scheduler
from . import auth
from ..models import User,Role,Files
from flask_login import login_user,logout_user,login_required
from ..decorators import admin_required,token_setter,token_getter,permission_required
import requests
import urllib
from .forms import LoginForm,SubmitConnection,ScheduleJobForm
from app.tasks import refreshed_google_client,test_context
app/main/views.py
from flask import render_template,request
from datetime import datetime
from . import main
from .. import db,scheduler
from ..models import User,Tokens
from .forms import NameForm,AnalyticsForm
from flask_login import login_required,current_user
from ..decorators import admin_required,permission_required
import requests
import rq
from redis import Redis
from app.tasks import refreshed_google_client,load_analytics
@main.route('/ig_sync',methods=['GET','POST'])
@login_required
@permission_required(4)
def ig_sync():
form = IGAnalyticsForm()
if request.method=='POST':
from app.tasks import load_ig_sync
if form.validate_on_submit():
if form.submit_analytics_schedule.data:
#GET VARIABLES FROM FORM
scheduler.add_job(func=load_ig_sync,args=[#VARIABLES HERE],trigger='cron',hour=3,id=f'SYNC_IG_{page_name}',jobstore='sqlalchemy')
return(redirect(url_for('main.job_schedule')))
return render_template('ig_sync.html',form=form)
应用程序/procfile
web: gunicorn flasky:app
worker: rq worker -u $REdis_URL flasky
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。