0

I have a django application with a python AP scheduler running a specific job. I wish to run the job once every week. There might be subsequent deployments to the application and I do not want the scheduler to reset the jobs every time that happens. Is there any way to provide a past start date or check if a week has elapsed since the last run to ensure that the scheduler jobs run independent of deployments.

The scheduler code -

from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.add_job(send_weekly_email, 'interval', weeks=1)
scheduler.start()
P K
  • 162
  • 12

1 Answers1

0

The key challenge here is that your BackgroundScheduler does not persist job information across deployments/restarts. You could use the APScheduler's built-in job stores, like SQLAlchemyJobStore, to persist the job across different sessions. However, that will not handle the scenario where a deployment happens less than a week after the last job was scheduled, leading to jobs being sent out more frequently than intended.

For that, I would recommend tracking the date of the last sent email separately, for example in a database or a simple file. Then, when the job is about to execute, it could check if a week has actually passed since the last email was sent. If not, it would skip the execution.

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from datetime import datetime, timedelta
import os

# create a scheduler with SQLAlchemyJobStore
jobstores = {
    'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
scheduler = BackgroundScheduler(jobstores=jobstores)

def send_weekly_email():
    # path of the file storing the timestamp of last email sent
    last_sent_file = "/path/to/last_sent.txt"

    # check if it's time to send email again
    if os.path.exists(last_sent_file):
        with open(last_sent_file, "r") as f:
            last_sent = datetime.fromisoformat(f.read().strip())
            if datetime.now() - last_sent < timedelta(weeks=1):
                print("It's not yet time to send the email.")
                return

    # send the email here...
    
    # update the timestamp of last email sent
    with open(last_sent_file, "w") as f:
        f.write(datetime.now().isoformat())
    print("Email sent.")

# add the job
scheduler.add_job(send_weekly_email, 'interval', weeks=1)

# start the scheduler
scheduler.start()

Remember to replace "/path/to/last_sent.txt" with an appropriate path for your system.

Additionally, consider using the logging module instead of print for real-world applications. It would help you to keep track of when and why emails are (or aren't) sent.

Kevin.T
  • 52
  • 1
  • 9