My mental model on how this application should work is to be able to separate the process that calls add_job to the one that sits manages the process.
When I add the job before starting the schedule this works fine, though when I try to separate it into separate functions it does not. Why? Is there a commit function after add_job I need to call
I was using sqlite and BlockingScheduler that makes more sense for my purpose though moved to postgresql for debugging.
from datetime import datetime, timedelta
from time import sleep
import logging
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.schedulers.background import BackgroundScheduler
import click
from crontab import CronTab
import pytz
logging.basicConfig()
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
jobstores = {
'default': SQLAlchemyJobStore(url='postgresql+psycopg2://myusername:mypassword@localhost/mydb')
}
executors = {
'default': ThreadPoolExecutor(5),
'processpool': ProcessPoolExecutor(5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
sched = BackgroundScheduler(jobstores=jobstores, timezone=pytz.timezone('Australia/Sydney'))
def my_job(text):
now = datetime.now()
print(f'{now} text: {text}')
@click.group()
def cli():
pass
@click.command()
@click.option('--message', default='<BLANK>', help='to display when ')
@click.option('--crontab', default='*/1 * * * *', help='Timestamp of ')
def add_job(message, crontab):
# entry = CronTab('0 0 ? * TUE,THU')
entry = CronTab(crontab)
number_of_seconds = entry.next()
timestamp = datetime.now(pytz.timezone('Australia/Sydney')) + timedelta(seconds=number_of_seconds)
move_service_message = f'Service {message} will be moved @ {timestamp}'
sched.add_job(
my_job,
'date',
run_date=timestamp,
args=[move_service_message]
)
print('added job:' + move_service_message)
@click.command()
def start():
# this will wait forever
sched.start()
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
sleep(10)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
sched.shutdown()
cli.add_command(start)
cli.add_command(add_job)
if __name__ == "__main__":
exit_code = 0 # assume it will be okay
time_started = datetime.now()
try:
cli()
except Exception as e:
print('Exception:', e)
exit_code = 1
finally:
exit(exit_code)
My packages are upto date including
APScheduler 3.6.0
SQLAlchemy 1.3.1
Appears what I was thinking it may be possible isn't as documented in FAQ. I'll still use it though just modified my expectations.