Skip to main content

Custom Celery result backend for SurrealDB

Project description

SurrealDB Celery Backend

PyPI version Python versions License: MIT

A custom Celery result backend that uses SurrealDB for storing task results, states, and metadata.

Features

  • ✅ Full Celery result backend implementation
  • ✅ Secure parameterized queries (prevents injection attacks)
  • ✅ Configurable connection settings
  • ✅ Automatic cleanup of expired results
  • ✅ Support for all task states (SUCCESS, FAILURE, PENDING, etc.)
  • ✅ Comprehensive test coverage (unit + integration tests)
  • ✅ Production-ready with proper error handling

Installation

Using uv (recommended)

uv add surrealdb-celery-backend

Using pip

pip install surrealdb-celery-backend

This will automatically install the required dependencies: celery and surrealdb.

Quick Start

1. Start SurrealDB

# Using Docker
docker run --rm -p 8000:8000 surrealdb/surrealdb:latest start \
  --user root --pass root

# OR using local installation
surreal start --user root --pass root

2. Configure Celery

from celery import Celery

app = Celery(
    'myapp',
    broker='redis://localhost:6379/0',
    backend='surrealdb_celery_backend:SurrealDBBackend'
)

# Configure SurrealDB connection
app.conf.update(
    surrealdb_url='ws://localhost:8000/rpc',
    surrealdb_namespace='celery',
    surrealdb_database='results',
    surrealdb_username='root',
    surrealdb_password='root',
    result_expires=86400,  # 1 day in seconds
)

3. Define Tasks

@app.task
def add(x, y):
    return x + y

4. Use Tasks

# Send task to worker
result = add.delay(4, 6)

# Get result
print(result.get())  # 10

# Check state
print(result.state)  # SUCCESS

Configuration Options

Configure the backend through your Celery app's configuration:

Option Default Description
surrealdb_url ws://localhost:8000/rpc WebSocket URL for SurrealDB
surrealdb_namespace celery SurrealDB namespace to use
surrealdb_database results SurrealDB database to use
surrealdb_username root Authentication username
surrealdb_password root Authentication password
result_expires 86400 Result expiration time (seconds)

⚠️ Security Note: The default credentials (root/root) are for development and testing only. Always use secure credentials in production:

import os

app.conf.update(
    surrealdb_url=os.environ['SURREALDB_URL'],
    surrealdb_namespace='production',
    surrealdb_database='celery_results',
    surrealdb_username=os.environ['SURREALDB_USERNAME'],
    surrealdb_password=os.environ['SURREALDB_PASSWORD'],
)

Testing

Quick Start with Just

If you have just installed:

# List all available commands
just

# Run unit tests (no services needed)
just test-unit

# Run integration tests (automatically starts/stops SurrealDB)
just test-integration-auto

# Start services for examples
just services-start

Manual Testing

Unit Tests (No services required):

uv run pytest tests/test_backend_unit.py -v

Integration Tests (Requires SurrealDB only):

# Start SurrealDB with docker-compose
docker-compose -f docker-compose.tests.yml up -d

# Run integration tests
uv run pytest tests/test_backend_integration.py -v -m integration

# Stop SurrealDB
docker-compose -f docker-compose.tests.yml down

All Tests:

uv run pytest -v

See tests/README.md for detailed testing documentation and justfile for all available commands.

Examples

Complete working examples are available in the examples/ directory:

  • celery_app.py - Configured Celery application
  • tasks.py - Sample tasks
  • test_tasks.py - End-to-end test script

See examples/README.md for detailed usage instructions.

How It Works

The backend stores task results in SurrealDB using the following structure:

Record ID: task:{task_id}
Fields:
  - task_id: Unique task identifier
  - status: Task state (SUCCESS, FAILURE, etc.)
  - result: Serialized task result
  - traceback: Exception traceback (if failed)
  - date_done: Completion timestamp

Data Flow

Storing Results:

  1. Task completes → Celery calls _store_result()
  2. Backend encodes result using Celery's serialization
  3. Executes parameterized UPSERT query to SurrealDB
  4. Result persisted with task:{task_id} record ID

Retrieving Results:

  1. Client requests result → Celery calls _get_task_meta_for()
  2. Backend executes parameterized SELECT query
  3. Decodes result and returns metadata
  4. Celery handles caching and state management

Cleanup:

  1. Periodic call to cleanup() (via Celery beat)
  2. Deletes tasks where date_done < now - result_expires
  3. Uses SurrealQL time functions for accurate expiration

Security

  • ✅ All queries use parameter binding to prevent SQL injection
  • ✅ No string interpolation of user-provided data
  • ✅ Safe record ID construction using type::thing()

Performance

  • Persistent WebSocket connections (reused across operations)
  • Lazy connection initialization
  • Atomic UPSERT operations
  • Efficient cleanup using SurrealDB time functions

Requirements

  • Python 3.10+
  • Celery 5.x+
  • SurrealDB 2+
  • Message broker (Redis, RabbitMQ, etc.)

Architecture

See specs/surrealdb-celery-backend/architecture.md for detailed technical architecture.

Development

Setup Development Environment

# Clone repository
git clone <repo-url>
cd surrealdb-celery-backend

# Install dependencies
uv sync --extra test

# Run tests
uv run pytest -v

Project Structure

surrealdb-celery-backend/
├── surrealdb_celery_backend/  # Main package
│   ├── __init__.py
│   └── backend.py             # Backend implementation
├── tests/                     # Test suite
│   ├── conftest.py           # Pytest fixtures
│   ├── test_backend_unit.py  # Unit tests
│   └── test_backend_integration.py  # Integration tests
├── examples/                  # Usage examples
│   ├── celery_app.py
│   ├── tasks.py
│   └── test_tasks.py
└── specs/                     # Design documentation

Troubleshooting

Connection Errors

Problem: Connection refused or Cannot connect to SurrealDB

Solution:

  • Verify SurrealDB is running: lsof -i :8000
  • Check URL format: Must be ws:// or wss:// (WebSocket)
  • Test connection manually using SurrealDB CLI

Tasks Not Storing Results

Problem: Results not appearing in SurrealDB

Solution:

  • Check worker logs for errors
  • Verify namespace and database exist
  • Ensure credentials are correct
  • Check task_ignore_result is not True

Import Errors

Problem: ModuleNotFoundError: No module named 'surrealdb_celery_backend'

Solution:

  • Ensure the package is in your Python path
  • Install in development mode: uv sync
  • Check imports: from surrealdb_celery_backend import SurrealDBBackend

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass (uv run pytest -v)
  6. Commit your changes (git commit -m 'feat: add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/lfnovo/surrealdb-celery-backend.git
cd surrealdb-celery-backend

# Install dependencies (including test dependencies)
uv sync --all-extras

# Run tests
uv run pytest -v

# Run integration tests (requires SurrealDB)
SURREALDB_TEST_URL=ws://localhost:8000/rpc uv run pytest -v -m integration

Publishing

See PUBLISHING.md for instructions on publishing new versions to PyPI.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Created by Luis Novo as a custom Celery backend for SurrealDB integration.

Links

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

surrealdb_celery_backend-0.2.1.tar.gz (116.5 kB view details)

Uploaded Source

Built Distribution

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

surrealdb_celery_backend-0.2.1-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file surrealdb_celery_backend-0.2.1.tar.gz.

File metadata

  • Download URL: surrealdb_celery_backend-0.2.1.tar.gz
  • Upload date:
  • Size: 116.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for surrealdb_celery_backend-0.2.1.tar.gz
Algorithm Hash digest
SHA256 78af34af210ea15c94a8f82f420450babbb6a4ce0035d81ed379005c91f9e703
MD5 0c390d384f62e0edf294f732b535c16c
BLAKE2b-256 b335771791a271b83c55ce97a12d8da1b28e4edc2e8d35b882b1c89d1065b101

See more details on using hashes here.

File details

Details for the file surrealdb_celery_backend-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: surrealdb_celery_backend-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for surrealdb_celery_backend-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dc65bc31adf05a32c6692afd3164c774752f88c9ac9ede414b2dc5cdc3e9c4a1
MD5 b29b6df5cd0143056c8289ac9aa23d21
BLAKE2b-256 15e7eee5805e28802b41d5ba8d6c49dcaada1eefadbfa72e1b4e8a1b212160eb

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