Pyramid Cron

Scott Torborg - Cart Logic

Provides the ability to register simple tasks (callback functions) for scheduled execution with a cron-like syntax.

Why it’s better than a typical task queue like Celery, Resque, etc:

  • No user permissions to worry about: everything is run inside a web request, so the task has all the same permissions as your web app.
  • Very simple setup, no additional daemons required.
  • The API follows Pyramid idioms.

Why it’s worse:

  • It’s not well suited to long-running tasks: everything is run inside a web request.
  • It does not distribute jobs across workers.
  • It does not allow for prioritization of jobs, or have any support for non-synchronous tasks.

Contents

Quick Start

Install

Install with pip:

$ pip install pyramid_cron

For each web app which uses pyramid_cron, you’ll need to fire the cron handler from a whitelisted IP once per minute. An easy way to do this is by adding a cron job on the app server:

* * * * *   curl -o /dev/null http://localhost/cron

Integrate with a Pyramid App

Include pyramid_cron, by calling config.include('pyramid_cron') or adding pyramid_cron to pyramid.includes.

Register a Task

Register at least one task, using the config.add_cron_task() directive. You can also pass a dotted string (e.g. myapp.tasks.some_task) which will be resolved relative to the calling module.

Tasks are functions which accept a single system argument. system is a dict with two keys: request and registry, both of which refer to the Pyramid objects of that name.

def my_task(system):
    registry = system['registry']
    request = system['request']
    # do stuff

# Run every 3 hours.
config.add_cron_task(my_task, hour=(0, 24, 3))

See API Reference for more details.

Request Scope Caveats

All tasks that are run during a given minute will be run in the scope of the same request. This may impose constraints on your tasks, for example:

  • Depending on your transaction management infrastructure, tasks will share the same SQL session.
  • An accumulation of slow tasks may lead to an abnormally long HTTP request, tying up resources or exceeding your webserver’s timeout threshold.
  • Ideally, tasks which are on the slower side should be staggered so that they’re unlikely to run at the same time.

Logging

Information about task execution (and timing) is logged to the pyramid_cron handler. If you wish to record it, you should configure logging explicitly for that handler in your app.

API Reference

pyramid_cron.add_cron_task(config, f, min='*', hour='*', day='*', month='*', dow='*')[source]

Register a function for execution by the scheduler.

Task functions must have the following signature:

def mytask(system):
    request = system['request']
    registry = system['registry']
    # do stuff

Additional keys may be added in the future: the single-arg signature ensures that task functions will be forward-compatible.

In addition to the callback function, you can specify a schedule, using a cron-like syntax. For the time periods of min, hour, day, month, and dow (day of week), you can specify an integer, a set of integers, or the ‘*’ wildcard character. The default argument is ‘*’. Hours are specified in 24-hour time.

For example, this will run the task every day, at 2:00:

config.add_cron_task(..., hour=2)

This will run the task every day at 2:00, 10:00, and 18:00:

config.add_cron_task(..., hour=[2, 10, 18])

To run the task ‘every 2 hours’, you can use range():

config.add_cron_task(..., hour=range(0, 24, 2))
Parameters:
  • f – The function to execute. Task functions must have accept a single argument, which will be a system dict containing keys for the Pyramid request and registry.
  • min – Specify which minutes to run the task.
  • hour – Specify which hours to run the task.
  • day – Specify which days to run the task.
  • month – Specify which months to run the task.
  • dow – Specify which days of the week to run the task.

Contributing

Patches and suggestions are strongly encouraged! GitHub pull requests are preferred, but other mechanisms of feedback are welcome.

pyramid_cron has a comprehensive test suite with 100% line and branch coverage, as reported by the excellent coverage module. To run the tests, simply run in the top level of the repo:

$ tox

This will also ensure that the Sphinx documentation builds correctly, and that there are no PEP8 or Pyflakes warnings in the codebase.

Any pull requests should preserve all of these things.

Indices and Tables