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.