Background Tasks triggered by current date and time

What I’m trying to do:
Create a collection of background tasks, which can be triggered to run when the current date and time passes. Example pseudocode:

task1 = Task('8/15/2021: 12 PM', print_hello_function)
task2 = Task('8/15/2021: 1 PM', print_goodbye_function)
task_collection = TaskCollection(task1, task2)
task_collection.launch_tasks()

# 12 PM rolls around on 8/15/2021, and task1 is started
# 1 PM rolls around on 8/15/2021, and task2 is started

The simple way I could think to accomplish this is to just create some sort of background task wrapper, that constantly checks the current date and time, and checks an in memory structure, but that seems really wasteful.

1 Like

Have you tried starting a background task with something like this?

print('waiting for the right time...')
time.sleep((task_time - datetime.datetime.now()).seconds)
print('the time has arrived!')
do_the_job()

I wouldn’t trust it to manage delays of days or weeks, but it should work just fine with hours.

Background Tasks can run for a long time, but they can’t run forever - if you keep a Background Task running for long enough, sooner or later the hardware node(s) it’s running on will die or get rebooted, so I wouldn’t recommend that approach!

The best way to do this is a Scheduled Task which runs regularly (eg every 15 minutes, or even every 5) and checks for jobs in a Data Table.

2 Likes

Thanks, @meredydd. I think I’ll probably go this route, but that does bring up a separate question, namely, what strategy do I use to ensure that all the work in a background task gets done?

For example, lets say I have a task that is supposed to send emails to 1,000 people, and for sake of argument, the time it takes to send those emails is longer than the lifetime of the background task that the email send function loops lives. I could put in checkpoints for every little piece of work, or save the work done every 5 emails sent or so, but that seems to require custom work save logic for every task.

How would you generalize this?

That’s why I said “I wouldn’t trust it to manage delays of days or weeks”.

Obviously the risk of failure due to server reboot if you wait 99 minutes to execute a 1 minute task is 99% higher than if you run the task on schedule as you suggest. This is should be enough to put this argument to rest.

But if I can’t trust a background task sleeping for an hour before starting a job, then I can’t trust any background task running for an hour.

I would say that using a scheduled task is the correct way in general, it’s the only way when you really need the tasks to run when you need them to run (or as close as possible), but there are cases where long running background tasks waiting for something to happen (sleep or uplink) are good enough, or even better than using scheduled tasks.

I have an app in which a background task running on the server starts an uplink function that runs for hours and waits for it to be finished. When the uplink is done the background task does some cleanup. If the background task is killed before the uplink has finished is not a problem because the cleanup will be picked up by the next background task.

The background task used to be started both on request (so the user sees it running immediately) and on schedule every 10 minutes for this very reason: to make sure everything is ok in case the previous background task didn’t finish its job. But I removed the scheduled run because I would rather be annoyed by a few rows waiting to be cleaned up in case of failure rather than seeing a log cluttered with useless scheduled tasks.

In other words, using the scheduled task could render the log useless. So if you think the log has a value and if your background task can skip some beats without hurting anything, then go ahead without scheduler.

I removed the scheduled execution months ago from my app, I finally enjoy a clean log and I have never noticed a failure. Here is a piece of the log with long running tasks:
image

The other option which I have migrated to is to create a new app just for scheduled tasks (with shared data tables) then you can eliminate the main app’s log getting clogged and still get the benefit of the scheduled tasks.

1 Like