Skip to main content

Django-bgt

Django-orchestrated background threads for Python, built on bgt (a great way to reliably run background threads).

Define background tasks for your Django app.
Use the service decorator to configure how often and where they should run.
Run django runservices in as many places as makes sense.

Job done.

— It's pronounced "Django Beergut"
— It is now!

What is Django-bgt for?

Django apps usually have tasks that should run periodically or constantly in the background. Sometimes it's also important that a service is only run on a single host at a time. django-bgt simplifies these situations, and also ensures that if things go wrong your job is restarted, with exponential back-off between retries.

Install

1. Install the django-bgt package

Install django-bgt:

pip install 'django-bgt'

2. Add to INSTALLED_APPS

    INSTALLED_APPS = [
        ...,
        "django_bgt",
    ]

3. Create the database table

Run python manage.py migrate to create the Lease table.

4. Declare Services

Create a services.py file in an installed app folder, and define the jobs that you want to be run as functions. Use the service decorator to define how often you want the job to be run. Use leader=True if you only want the job running in a single place.

# Only one process at a time runs this.
@service(name="ticker", interval=1, leader=True, lease_ttl=15)
def tick() -> bool:


    return False

5. Run the service process

Use the runservices management command using one of the following approaches:

./manage.py runservices           # Run all services, until SIGINT/SIGTERM
./manage.py runservices ticker    # Run the "ticker" service, until SIGINT/SIGTERM
./manage.py runservices --list    # List the

Run one runservices process per host. Leader-elected services synchronise through the Lease table. Others run everywhere.

Example: Clean up session data

In a long-running Django application, you should periodically clear your session data from your database. Many developers don't do this, and their session data never gets cleared up!

The traditional way to clear sessions is to run the clearsessions management command from some kind of scheduler like cron. But configuring cron gives you another system to manage. django-bgt allows you to manage these kinds of tasks with Python code.

A function to call that management command from looks a bit like this:

from django.core.management import call_command

def clear_expired_sessions():
    call_command("clearsessions")

You can configure django-bgt to run this as a regular background task with a few lines of code.

Step One: Install django-bgt

Here are the instructions to install django-bgt. Come back here when you're ready to define your background services.

Step Two: Create a services.py file in one of your Django apps.

Add the above code to services.py and decorate it with the service decorator:

from django.core.management import call_command

from django_bgt import service

ONE_MINUTE = 60             # in seconds.
ONE_HOUR = 60 * ONE_MINUTE  # The number of seconds in an hour.

@service(interval=ONE_HOUR)
def clear_expired_sessions():
    """ Clear expired sessions, once every hour. """
    call_command("clearsessions")

Now you need to run the runservices management command somewhere. A background thread will be created for each service you've defined.

# Run all services defined in the Django project:
python ./manage.py runservices

Thanks to the magic of bgt, Your service will be immediately restarted if your service function returns True. (If you return False it will wait interval seconds.) If your service function raises an exception, the service will be restarted, but with exponential back-off, so that it doesn't overwhelm your system if there's a persistent problem.

If you're running in an environment with any sort of redundancy, you should probably run runservices on multiple hosts. In this case, the clear_expired_sessions service will run once every hour everywhere runservices is being run. This may not be desirable, so in this case pass leader=True to the service decorator, and only one host will run this service at any time. If that host fails or is simply shut down, another will spawn a new copy of the service.

Other Examples

The following example is similar to the example above, but manually clears all expired Session objects from the database. This will only be useful if you're running database-backed sessions.

from django_bgt import service

# Define a periodic service to clean up old sessions.
# Will run every 60 seconds.
# Service name defaults to the function name.
# Returning False means nothing left to process. Will wait for next wakeup.
@service(interval=60)
def cleanup() -> bool:
    Session.objects.filter(expire_date__lt=timezone.now()).delete()
    return False

The following defines a service that will be run every second, only in one single process in the Django cluster.

# Services can by synchronised by declaring leader=True.
# Only one process at a time runs this.
@service(name="ticker", interval=1, leader=True, lease_ttl=15)
def tick() -> bool:
    ...
    return False

The lease_ttl parameter determines how quickly failover to other service instances may occur. Long running work units will have their lease periodically renewed, and so can outlive the lease_ttl. As per bgt's notes on thread cancellation, it is advisable to keep individual work units bounded in their runtime. For bigger workloads, try to batch the work, returning True to be run again immediately, unless the supervisor has been stopped.

Metadata

Release files for django-bgt 26.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-bgt 26.1
File Size Uploaded
django_bgt-26.1.tar.gz 16.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-bgt 26.1
File Interpreter ABI Platform
django_bgt-26.1-py3-none-any.whl Python 3 none any Details

Total release size: 28.6 kB

Release files / django_bgt-26.1.tar.gz

Download URL django_bgt-26.1.tar.gz
Size 16.2 kB
Tags Source
SHA-256 checksum
How to use checksums
13f9b925d8035bc038e9dfb84d9b14e4a901d0d7e3e7e61e844f1d4a603a9589
BLAKE2b-256 checksum
How to use checksums
83e7d22f4174698af1625c2ed7cd84259835e85c5c7e01a256b5722e348640a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.5

Release files / django_bgt-26.1-py3-none-any.whl

Download URL django_bgt-26.1-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d56482ee3084cb07ba53b67092677b606e5bd141fb90555e6fab285b34232873
BLAKE2b-256 checksum
How to use checksums
498ed9602765d14bed324b0efabee1251951f0511e2b11199978ac078ab09515
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.5

Release history Release notifications | RSS feed

This release

26.1 This release

2 release files

26.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page