Skip to main content

Redis-based statedb persistence for Celery workers

Project description

Celery Redis StateDB

Tests Coverage Python License

Redis-based state persistence for Celery workers in containerized environments.

This package provides a Redis-based backend for Celery's worker state persistence, replacing the default filesystem-based shelve storage. It's designed to:

  • ✅ Persist revoked task state across container restarts
  • ✅ Isolate state per worker using unique key prefixes
  • ✅ Eliminate concurrency issues through per-worker key isolation
  • ✅ Handle Redis connection failures gracefully
  • ✅ Integrate seamlessly with existing Celery applications

Features

  • Distributed State Persistence: Store revoked tasks in Redis instead of local files
  • Per-Worker Isolation: Each worker maintains its own state using unique key prefixes based on hostname
  • Concurrency-Safe: No race conditions since workers never write to the same keys
  • Easy Integration: Simple Celery bootstep that works with existing applications

Installation

# Using pip
pip install celery-redis-statedb

# Using uv
uv add celery-redis-statedb

Quick Start

Method 1: Command Line (Easiest)

The easiest way to use Redis state persistence is via the --redis-statedb command line option:

celery -A myapp worker --redis-statedb=redis://localhost:6379/0

Method 2: Programmatic Installation (Recommended)

Use the install_redis_statedb() convenience function in your app:

Basic usage (with defaults):

from celery import Celery
from celery_redis_statedb import install_redis_statedb

app = Celery('myapp')

# Install Redis state persistence
install_redis_statedb(app)

# Start worker with Redis statedb
# celery -A myapp worker --redis-statedb=redis://localhost:6379/0

With custom configuration:

from celery import Celery
from celery_redis_statedb import install_redis_statedb

app = Celery('myapp')

# Optional: Configure via app.conf
app.conf.redis_state_key_prefix = 'myapp:worker:state:'

# Install bootstep
install_redis_statedb(app)

# Start worker
# celery -A myapp worker --redis-statedb=redis://localhost:6379/0

Method 3: Environment Variables

Configure additional settings via environment variables:

# Optional: Custom key prefix (default: celery:worker:state:)
export CELERY_REDIS_STATE_KEY_PREFIX=myapp:worker:state:

# Start worker
celery -A myapp worker --redis-statedb=redis://localhost:6379/0 --loglevel=info

Configuration Options

Configuration can be set via Celery app configuration (app.conf) or environment variables:

Configuration Key Environment Variable Default Description
redis_state_key_prefix CELERY_REDIS_STATE_KEY_PREFIX celery:worker:state: Base prefix for Redis keys (worker hostname is appended)

Example using app.conf:

app.conf.redis_state_key_prefix = 'myapp:worker:state:'

Example using environment variables:

export CELERY_REDIS_STATE_KEY_PREFIX=myapp:worker:state:

Revoked Task Persistence

Revoked tasks persist indefinitely in Redis (matching Celery's default behavior with shelve). This ensures that once a task is revoked, it remains revoked even across worker restarts.

Celery's LimitedSet automatically purges expired items based on the maxlen parameter (default: 10000 items). When the set reaches this limit, the oldest items are automatically removed to maintain the size constraint.

Architecture

Per-Worker Key Isolation

Each worker maintains its own state using a unique key prefix based on the worker's hostname:

celery:worker:state:<worker-hostname>:zrevoked
celery:worker:state:<worker-hostname>:clock

This design eliminates concurrency issues since:

  • Workers never write to the same Redis keys
  • No locks or atomic operations needed
  • Simple, fast, and scalable
  • Each worker independently manages its own state persistence

When a worker restarts, it loads its own state from its dedicated keys in Redis.

Worker Hostname Configuration

Default Hostname Behavior

By default, Celery generates worker hostnames in the format celery@<system-hostname>. In containerized environments:

  • Docker: Uses the container ID (e.g., celery@f9207bc94b22)
  • Kubernetes: Uses the pod name (e.g., celery@worker-deployment-7d9f8b6c-xk2p5)
  • ECS: Uses the task ID or container hostname

Each container automatically gets a unique hostname, ensuring per-worker key isolation works correctly.

Customizing Worker Hostnames

For better visibility and debugging, you can set custom worker hostnames using the -n or --hostname option:

# Static name with system hostname
celery -A myapp worker -n worker1@%h --redis-statedb=redis://localhost:6379/0

# Using environment variable for replica number (Kubernetes)
celery -A myapp worker -n worker-$REPLICA_ID@%h --redis-statedb=redis://localhost:6379/0

# Custom name with domain
celery -A myapp worker -n myworker@example.com --redis-statedb=redis://localhost:6379/0

Hostname Variables:

  • %h - Full hostname with domain (e.g., george.example.com)
  • %n - Hostname only (e.g., george)
  • %d - Domain only (e.g., example.com)

Note: In Supervisor config files, escape % as %% (e.g., %%h).

Multiple Workers on Same Host

When running multiple workers on the same machine, ensure each has a unique hostname:

celery -A myapp worker -n worker1@%h --redis-statedb=redis://localhost:6379/0
celery -A myapp worker -n worker2@%h --redis-statedb=redis://localhost:6379/0
celery -A myapp worker -n worker3@%h --redis-statedb=redis://localhost:6379/0

⚠️ Important: If multiple workers share the same hostname, they will overwrite each other's state in Redis. Celery will also show a DuplicateNodenameWarning. Always ensure unique worker hostnames in production.

Container Deployments

AWS ECS Deployment

Example ECS task definition with custom worker hostname:

{
  "family": "celery-worker",
  "containerDefinitions": [
    {
      "name": "celery-worker",
      "image": "myapp:latest",
      "command": [
        "celery",
        "-A",
        "myapp",
        "worker",
        "-n", "worker@%h",
        "--redis-statedb=redis://redis.cluster.local:6379/0",
        "--loglevel=info"
      ]
    }
  ]
}

Best Practices for ECS:

  • Set stopTimeout to allow graceful shutdown (e.g., 120 seconds for 2-minute tasks)

Troubleshooting

Verify Worker Hostnames

To check that each worker has a unique hostname, inspect active workers:

# List all active workers
celery -A myapp inspect active

# Check worker stats (shows hostname for each worker)
celery -A myapp inspect stats

Check Redis Keys

To verify per-worker keys are being created correctly:

# Connect to Redis
redis-cli

# List all worker state keys
KEYS celery:worker:state:*:zrevoked

# Example output:
# 1) "celery:worker:state:worker1@host1:zrevoked"
# 2) "celery:worker:state:worker2@host2:zrevoked"
# 3) "celery:worker:state:worker3@host3:zrevoked"

# Check revoked tasks for a specific worker
GET celery:worker:state:worker1@host1:zrevoked

Common Issues

Issue: Workers overwriting each other's state

  • Cause: Multiple workers using the same hostname
  • Solution: Set unique hostnames with -n option (e.g., -n worker1@%h, -n worker2@%h)

Issue: DuplicateNodenameWarning on worker startup

  • Cause: Another worker with the same nodename is already registered
  • Solution: Ensure each worker has a unique hostname

Issue: State not persisting across restarts

  • Cause: Worker hostname changes between restarts
  • Solution: In containers, use stable hostnames or set custom static names

Testing

# Quick check - run all quality checks at once
make check-all

# Individual commands
make test        # Run tests with coverage
make lint        # Run ruff linter
make typecheck   # Run mypy and ty type checkers
make format      # Format code with ruff
make clean       # Clean up temporary files

# Or run commands directly
uv run pytest --cov=celery_redis_statedb
uv run ruff check celery_redis_statedb/
uv run mypy celery_redis_statedb/
uv run ty check celery_redis_statedb/

Documentation

For detailed information about Celery's state persistence format and how this package implements it:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

celery_redis_statedb-0.1.0.tar.gz (62.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

celery_redis_statedb-0.1.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file celery_redis_statedb-0.1.0.tar.gz.

File metadata

  • Download URL: celery_redis_statedb-0.1.0.tar.gz
  • Upload date:
  • Size: 62.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.04","id":"plucky","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for celery_redis_statedb-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0eaf20f534f1f1765754eca0690fcb52c5ad01453a7d30283516b79c561b73f8
MD5 43cbe133c6f8b03b61ce05f66f1fbcf2
BLAKE2b-256 462ad97baa51fe23b313297f30ce4ad910c8e9704d23ae61e9627b151d4d8d5e

See more details on using hashes here.

File details

Details for the file celery_redis_statedb-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: celery_redis_statedb-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.04","id":"plucky","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for celery_redis_statedb-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b36090e1129d0105268b0b36fb248bde627885deda23c120809fb954b57f023
MD5 69572bc7b657f6e317327bcd2d5f5fd0
BLAKE2b-256 e45cb414bfcec2a0aa3fc16d827d74498aca1bf8d95e651ab257d97f450af8e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page