I have a flask application with peewee and a pooled postgresql database.
Everything works with the app setup until I added an APScheduler job. I want the job to run when app starts and every 8 hours after.
config bits for flask-apscheduler and peewee:
class Config(object):
JOBS = [
{
'id': 'myjob',
'func': 'app.jobs:do_something_job',
'trigger': 'interval',
'hours': 8
}
]
SCHEDULER_API_ENABLED = True
DATABASE = 'postgresext+pool://user:password@localhost:5432/dev?max_connections=32&stale_timeout=300'
app.py:
scheduler = APScheduler()
db = FlaskDB()
def create_app(config_object=Config):
"""Application Factory Pattern"""
app = Flask(__name__.split('.')[0])
app.config.from_object(config_object)
db.init_app(app)
scheduler.init_app(app)
scheduler.start()
# RUN the job on application creation:
scheduler.run_job('myjob') # <--- exception thrown here
return app
app = create_app(Config)
the line scheduler.run_job('myjob')
results in a peewee.OperationalError: Connection already opened.
right after the app is launched (if i visit the page shortly after starting the app)
Although, it appears the initial job run still works fine
The do_something_job looks something like:
def do_something_job():
new = NewModel(seed=new_seed())
new.save()
old_list = NewModel.select()
for old in old_list:
if old.id != new.id:
expired = OldModel(seed=old.seed,
created_at=old.created_at,
expired_at=datetime.datetime.utcnow())
expired.save()
old.delete_instance()
I'm just not sure exactly what I'm missing, I'm a bit novice when it comes to peewee/flask still.
Thanks!
I'll wait awhile before accepting my own answer because I'm sure there's a potentially better/proper solution.
But I basically setup Flask-APScheduler to run the initial job 30 seconds in the future and removed it from my create_app().
I'm not sure if it's because the database isn't initialized yet at the point the code runs or what exactly and i'm sure this is hackish but it did clear up the exception
Basically added a second job to config (and explicit timezone)
class Config(object):
SCHEDULER_TIMEZONE = 'UTC'
JOBS = [
{
'id': 'myinitialjob',
'func': 'app.jobs:do_something_job',
'trigger': 'date',
'run_date': datetime.datetime.utcnow() + datetime.timedelta(seconds=30)
},
{
'id': 'myjob',
'func': 'app.jobs:do_something_job',
'trigger': 'interval',
'hours': 8
}
]
SCHEDULER_API_ENABLED = True
Removed the initial run from the create_app func
def create_app(config_object=Config):
"""Application Factory Pattern"""
app = Flask(__name__.split('.')[0])
app.config.from_object(config_object)
db.init_app(app)
scheduler.init_app(app)
scheduler.start()
# scheduler.run_job('myjob') # <--- removed this
return app