5.6 Task Scheduling

Draco features an integrated event scheduling service that you can use to execute certain tasks at predefined times. Often these tasks will be cleanup or expiration tasks, but this need not be of course. With Draco, there is no need for an external cron!

To define a new task, you must subclass Draco's Task class (found in draco.task) and put it in a file named __tasks__.py in the document root of your web site. All Task subclasses in this file are automatically loaded and scheduled to be executed by Draco. If this file changes it is automatically reloaded.

class Task( )
Base class of all scheduled tasks.

Its public methods are:

schedule( [minute][, hour][, dow])
Schedule this task at hour:minute of weekday dow. Every one of the parameters can be either an integer, a tuple of integers or None. If an integer is passed, the task is run at the specified time. If a tuple of integers is passed, the task is run at every time specified in the tuple. If None is passed, this is equivalent to a tuple from 0 to the highest value possible for that parameter. The arguments hour, minute and dow all start from zero. A value of 0 for dow means monday.

run( )
Perform the actual task. This method is abstract must be implemented by a subclass.

The next example illustrates how to define a new task and how to schedule it so that it runs every four hours. The call to schedule() is made in the constructor:

from draco.task import Task

class MyTask(Task):

    def __init__(self):
        Task.__init__(self)
        self.schedule(hour=(0,4,8,12,16,20))

    def run(self):
        pass

To define multiple tasks, just put multiple Task subclasses in __tasks__.py. Because tasks are run in an external process (more about this later), they cannot access all global draco object. The following objects are available: logger, config and database.

At every http request, Draco looks if a scheduled task is ready to run. If it finds runnable tasks, they are executed in separate processes in order not to hold up the request processing. Because the Draco handler is only run when an http request is made, it is possible that scheduled tasks are run late or not run at all. Normally this should not be a big problem because even moderately busy web sites will have many requests. If this is a problem for you, you can use an external cron to run the tasks at better defined times. To do this, leave the tasks in __tasks__.py but don't call schedule() for them. Instead, when you want to run a task, execute the shell command

$ dracotask.py DOCROOT TASKNAME

with DOCROOT the document root of the web application and TASKNAME the name of the task to run. By default, the dracotask.py script resides in /usr/local/bin, but this can be changed at installation time. It is the same script that is used internally by draco to run tasks in an external process.