Django Tasks Scheduler

repository·master·Indexed 42 days ago

https://github.com/django-commons/django-tasks-scheduler

An async job scheduler for Django using Redis/Valkey brokers. Version 4.4.0 provides a database-backed system to run, monitor, and manage background jobs with support for ONCE, REPEATABLE, and CRON task types. It includes management commands for starting workers, importing/exporting tasks, and viewing real-time queue statistics.

Tokens
11.7K
Snippets
44
Records
53
Agent score
46%

What's inside Django Tasks Scheduler

  1. Configure SCHEDULER_QUEUES for multiple workers

    master

    The SCHEDULER_QUEUES dictionary allows you to define multiple queues. This enables you to have different workers listening to different queues, and allows different queues to use different Redis servers or connection settings.

    Each entry in the dictionary maps a queue name to a QueueConfiguration object.

    SCHEDULER_QUEUES = {
        "default": QueueConfiguration(HOST="localhost", PORT=6379, DB=0),
        "high": QueueConfiguration(URL="redis://high-priority-server:6379/0"),
        "low": QueueConfiguration(HOST="localhost", PORT=6379, DB=1, ASYNC=False),
    }
  2. How worker registration and job execution work

    master

    The worker process follows a specific lifecycle to ensure reliability and visibility:

    1. Registration: Upon startup, the worker validates that the requested queue names exist in the system. It then creates a WorkerKey containing its ID, assigned queues, and status, and adds itself to the WorkerList with a current heartbeat.
    2. Heartbeat: The worker continuously updates its last heartbeat to signal it is alive.
    3. Job Polling: The worker loops through its assigned queueKeys using a zrange+zpop pattern to find the next available job name.
    4. Execution Lifecycle:
      • When a job is found, the worker updates its status to busy.
      • It retrieves the job data and updates the job status to running.
      • After execution, it updates the job status to either done or failed.
      • Finally, it reverts its own status to idle.
    5. Idle State: If no jobs are pending in any assigned queues, the worker enters a sleep state.
  3. Understand the architecture and terminology of django-tasks-scheduler

    master

    django-tasks-scheduler is a database-backed asynchronous task scheduler for Django. It uses a central Task model to manage scheduling and a broker-based system to handle execution.

    Core Components:

    • Scheduled Task: A Django model instance representing the intent to run code. Tasks are categorized by type: ONCE, REPEATABLE, or CRON.
    • Job: A record in the broker containing the specific execution details (method reference, arguments, callbacks, and timeouts) required to run a task.
    • Queue: A collection of registries within the broker that track the lifecycle of jobs: scheduled, queued, active, finished, failed, and canceled.
    • Worker: A process that listens to queues for jobs to execute. It includes a thread for command listening and can run a Scheduler sub-process.
    • Scheduler: A sub-process of the Worker that periodically checks the database for enabled tasks and moves them from the scheduled registry to the queued registry so workers can pick them up.
  4. Important: Deprecation of old task models

    master

    Starting with version 3.0.0, the old models (ScheduledTask, RepeatableTask, and CronTask) are deprecated. While they still exist to facilitate migration, you cannot create new tasks using them.

    Warning: These old models will be completely removed in version 3.1. Ensure all tasks are migrated to the new Task model before upgrading beyond v3.0.

  5. How the Scheduler and Worker processes interact

    master

    The system relies on two main loop-based processes to move tasks from the database to successful execution:

    1. The Scheduler Loop

    The Scheduler process runs a loop that:

    1. Checks the database for enabled tasks that meet their scheduling criteria.
    2. Creates a Job for those tasks and adds them to the scheduled registry in the broker.
    3. Checks the scheduled registry and moves jobs into the queued registry to make them available for workers.
    4. Sleeps for an interval defined by SCHEDULER_INTERVAL.

    2. The Worker Loop

    The Worker process runs a loop that:

    1. Pulls the first available job from the queued registry.
    2. Moves the job to the active registry.
    3. Executes the job's method.
    4. On Success: Executes success callbacks, moves the job to the finished registry, and writes the result.
    5. On Failure: Executes failure callbacks, moves the job to the failed registry, and writes the result.
  6. Configure Task types: ONCE, REPEATABLE, and CRON

    master

    When creating a Task in the Django model, you can define how it is scheduled using one of three types:

    • ONCE: The task is scheduled to run exactly one time at a specific designated time.
    • REPEATABLE: The task runs multiple times based on a defined time interval. This can be configured to run for a limited number of times or infinitely.
    • CRON: The task runs indefinitely according to a standard cron string schedule.
  7. Start a worker process to execute jobs

    master

    To start a worker process that listens to specific queues, use the scheduler_worker management command. You must provide a unique --name for the worker and specify one or more queues it should monitor.

    Example command to start a worker named 'X' that monitors the high, default, and low queues:

    python manage.py scheduler_worker --name 'X' --queues high default low
  8. Install and configure django-tasks-scheduler

    master

    To integrate django-tasks-scheduler into your Django project, follow these four steps:

    1. Add to INSTALLED_APPS: Include "scheduler" in your settings.py.
    2. Configure SCHEDULER_CONFIG: Define a SchedulerConfiguration object in settings.py to set global execution parameters, broker types, and TTL (Time To Live) values.
    3. Configure SCHEDULER_QUEUES: Define a dictionary mapping queue names to QueueConfiguration objects (e.g., specifying the Redis URL).
    4. Register URLs: Include scheduler.urls in your project's urls.py to enable scheduler-related endpoints.
    5. Run Migrations: Execute python manage.py migrate to set up the necessary database tables.
    # settings.py
    INSTALLED_APPS = [
        "scheduler",
    ]
    
    from scheduler.types import SchedulerConfiguration, Broker, QueueConfiguration
    
    SCHEDULER_CONFIG = SchedulerConfiguration(
        EXECUTIONS_IN_PAGE=20,
        SCHEDULER_INTERVAL=10,
        BROKER=Broker.REDIS,
        CALLBACK_TIMEOUT=60,
        DEFAULT_SUCCESS_TTL=600,
        DEFAULT_FAILURE_TTL=31536000,
        DEFAULT_JOB_TTL=600,
        DEFAULT_JOB_TIMEOUT=300,
        DEFAULT_WORKER_TTL=600,
        DEFAULT_MAINTENANCE_TASK_INTERVAL=600,
        DEFAULT_JOB_MONITORING_INTERVAL=30,
        SCHEDULER_FALLBACK_PERIOD_SECS=120,
    )
    
    SCHEDULER_QUEUES = {
        "default": QueueConfiguration(URL="redis://localhost:6379/0"),
    }
    
    # urls.py
    from django.urls import path, include
    
    urlpatterns = [
        path("scheduler/", include("scheduler.urls")),
    ]
  9. Schedule tasks through the Django Admin

    master

    You can manage and schedule tasks via the Django Admin interface under the Tasks Scheduler section.

    Steps to schedule a task:

    1. Navigate to Tasks and click Add.
    2. Enter a unique Name.
    3. Select a Task Type:
      • Repeatable task: Requires an Interval (and unit) and an optional Repeat count (empty means run forever).
      • Cron task: Requires a cron string and an optional Repeat count.
    4. Enter the Callable using Python dot notation (e.g., myapp.jobs.count).
    5. Select a Queue (defined in SCHEDULER_QUEUES in your settings).
    6. Set the Scheduled time in UTC.

    Optional Fields:

    • at front: If selected, the job takes priority over existing queued jobs.
    • Timeout: Maximum seconds allowed for execution (blank for infinite).
    • Result TTL: Time to live for the job result (-1 for never expires, 0 for immediate deletion, n for $n$ seconds).
  10. Migrate from v2 to v3 using Export/Import commands

    master

    You can migrate your scheduled tasks from the old models to the new Task model using the provided management commands. This is useful for bulk migrations or when working outside the Django Admin interface.

    Run the following commands in your project directory:

    python manage.py export > scheduled_tasks.json
    python manage.py import --filename scheduled_tasks.json
  11. Configure django-tasks-scheduler in settings.py

    master

    All scheduler settings are configured using two main dictionaries in your Django settings.py: SCHEDULER_CONFIG (for global scheduler behavior) and SCHEDULER_QUEUES (for defining specific queue connections).

    Use SchedulerConfiguration to define global parameters like intervals, timeouts, and TTLs. Use QueueConfiguration to define how workers connect to specific queues (e.g., Redis hosts, ports, or URLs).

    import os
    from scheduler.types import SchedulerConfiguration, Broker, QueueConfiguration
    
    SCHEDULER_CONFIG = SchedulerConfiguration(
        EXECUTIONS_IN_PAGE=20,
        SCHEDULER_INTERVAL=10,
        BROKER=Broker.REDIS,
        CALLBACK_TIMEOUT=60,
        DEFAULT_SUCCESS_TTL=10 * 60,
        DEFAULT_FAILURE_TTL=365 * 24 * 60 * 60,
        DEFAULT_JOB_TTL=10 * 60,
        DEFAULT_JOB_TIMEOUT=5 * 60,
    )
    
    SCHEDULER_QUEUES = {
        "default": QueueConfiguration(
            HOST="localhost",
            PORT=6379,
            DB=0,
            USERNAME="some-user",
            PASSWORD="some-password",
            CONNECTION_KWARGS={
                "ssl_cert_reqs": "required",
                "ssl": True,
            },
        ),
        "high": QueueConfiguration(URL=os.getenv("REDISTOGO_URL", "redis://localhost:6379/0")),
        "low": QueueConfiguration(HOST="localhost", PORT=6379, DB=0, ASYNC=False),
    }