ok, got the "issue". We check for last_run_time and add n = period seconds to it, that is different from what you'd like, i.e. adding n = period seconds * times_run to start_time.
The wording in the book is correct: you get your task queued to be executed n period seconds after the first execution.
The concept is subtle however... that actually means e.g. :
- today the task got queued to be executed at 9:00am...but has been picked up at 9:01am (e.g., that the worker was sleeping or busy processing other tasks) --> the task will be requeued for tomorrow at 9:01am.
- tomorrow, at 9:01am, scheduler "sees" the task that has to be executed, but once again the scheduler is processing another queued task and it gets actually executed at 9:02am...it will be scheduled for the next day at 9:02am.
This "behaviour" was meant with a slightly different logic then the one you mean (yours is valid too, actually, and is making me think on how to solve it)... basically with the scheduler we "drifted" from a "millisecond-perfect cron replacement" to a different approach....... Let's cut the story, here it goes for the summary of the current logic:
- I want to schedule a task that polls a database/external service once every 5*60 seconds (5 minutes)
- I want to be sure that two consecutive executions will never take place unless 5*60 seconds passed
This basically assures you that if your task was scheduled at 09:00 but the worker was caught up doing something else, you won't have a first execution at 09:03 and a second at 09:05 because it would mean "breaking" the assumption that at least 5*60 seconds pass before each execution, and that's good for a lot of cases, but not yours.
Yours is different: you have a task and you want it to start it after 09:00, but every day at 09:00.
Scheduler instead "assumes/figures out/calculates/interprets" your wishes as "you want your emails sent at 24hours intervals", hence the delay you're observing when a few days pass by.
To support your wishes, ATM you should then have a "cleanup" task that sets "future" next_run_time(s) to start_time(s) + n = period seconds (multiplied by times_run), or a task that queues once a day a single execution at 09:00.
We can figure out another "boolean" column for the scheduler_task table that's more or less named "cron_style" (default=False), that if set to True will calculate the next_run_time as the behaviour you want instead of the original one. Let me check with the developers and we'll see what can we do.