CelerySalt
A schema-driven event API on top of Celery: publish/subscribe (broadcast) and RPC with Pydantic validation and a schema registry.
Features
- Pydantic schemas: type-checked event payloads with validation.
- Broadcast: fire-and-forget pub/sub (one event to many subscribers).
- RPC: request/response with response and error schema validation.
- Schema registry: schema registration and lookup by topic/version.
- Versioning: topic stays stable; versions are metadata.
- Django integration: optional helpers for wiring queues and module discovery.
- Protocol compatibility: interoperates with
tchu-tchu(tchu_eventsexchange and_tchu_meta).
Quick Start
Installation
pip install celery-salt
Broadcast Example
from celery_salt import event, subscribe
# Define event schema
@event("user.signup.completed")
class UserSignupCompleted:
user_id: int
email: str
company_id: int
signup_source: str = "web"
# Publish event
UserSignupCompleted.publish(
user_id=123,
email="alice@example.com",
company_id=1,
signup_source="web"
)
# Subscribe to event
@subscribe("user.signup.completed")
def send_welcome_email(data: UserSignupCompleted):
print(f"Sending welcome email to {data.email}")
RPC Example
from celery_salt import event, subscribe, RPCError
# Define RPC request/response schemas
@event("rpc.calculator.add", mode="rpc")
class CalculatorAddRequest:
a: float
b: float
@event.response("rpc.calculator.add")
class CalculatorAddResponse:
result: float
operation: str = "add"
@event.error("rpc.calculator.add")
class CalculatorAddError:
error_code: str
error_message: str
# Handler
@subscribe("rpc.calculator.add")
def handle_add(data: CalculatorAddRequest) -> CalculatorAddResponse:
return CalculatorAddResponse(result=data.a + data.b, operation="add")
# Client call (returns SaltResponse: .event, .data, .payload, attribute access)
response = CalculatorAddRequest.call(a=10, b=5, timeout=10)
print(f"Result: {response.result}") # 15.0
# For DRF/JsonResponse: use response.payload (JSON-serializable dict/list)
Architecture
Publisher → RabbitMQ Exchange (tchu_events) → Subscribers
- Exchange:
tchu_events(topic exchange, protocol compatible) - Routing: Topic-based with wildcard support (
user.*,#) - Serialization: JSON with Pydantic validation;
datetime,UUID,Decimal, etc. are normalized to JSON-safe types automatically - Result Backend: Redis (required for RPC)
Documentation
- Examples: ./examples/
- Docs: ./docs/
- Unified API (SaltEvent / SaltResponse): ./docs/EVENT_CLASS_UNIFIED_API.md
- Typing subscriber payloads: ./docs/TYPING_SUBSCRIBER_EVENTS.md
- Celery config (Django): ./docs/CELERY_CONFIG_TEMPLATE.md
Requirements
- Python 3.10+
- Celery 5.3+
- RabbitMQ (message broker)
- Redis (optional, required for RPC)
Django is optional. The core library is Celery + Pydantic; events and validation do not require Django. Install with pip install celery-salt[django] only if you use the optional Django helpers below.
Django (optional)
If you use Django:
-
Wire the Celery app
Add'celery_salt.django'toINSTALLED_APPSand setCELERY_APP = "myproject.celery:app"in settings. Then.publish()and.call()work from views with no extra code. -
Configure the worker
In yourcelery.py, callsetup_salt_queue(app, queue_name="my_queue"). If your app usesCelery(..., include=[...]), that same list is used for subscriber modules; otherwise passsubscriber_modules=[...]. -
Optional: auto-publish on model save/delete
Use the@auto_publishdecorator on a Django model to publish events on create/update/delete.
Examples
See the examples directory for complete working examples:
- Basic Broadcast - Pub/sub messaging
- Basic RPC - Request/response pattern
Run examples with Docker Compose:
cd examples
docker-compose up -d # Starts RabbitMQ and Redis
Key Concepts
Event Schemas
Schemas are defined using Pydantic models and registered at import time:
@event("user.created")
class UserCreated:
user_id: int
email: str
created_at: datetime
Publishing Events
# Broadcast (fire-and-forget)
UserCreated.publish(user_id=123, email="user@example.com", created_at=datetime.now())
# RPC (synchronous)
response = CalculatorAddRequest.call(a=10, b=5, timeout=10)
Subscribing to Events
Handlers can use Celery task options (priority, retries, time limits, etc.) via **celery_options:
@subscribe("user.created", priority=5, autoretry_for=(Exception,), max_retries=3)
def handle_user_created(data: UserCreated):
# Process event
pass
For SaltEvent class-based handlers, subscribe with the event class to receive a full event instance and use event.respond() for RPC:
@subscribe(MyRpcEvent)
def handle_my_rpc(evt: MyRpcEvent):
# evt is MyRpcEvent; return validated response via event.respond()
return evt.respond(serializer.data) # or evt.respond(key=value, ...)
RPC Response Validation
@event.response("rpc.calculator.add")
class CalculatorAddResponse:
result: float
@event.error("rpc.calculator.add")
class CalculatorAddError:
error_code: str
error_message: str
Protocol Compatibility
CelerySalt maintains protocol compatibility with tchu-tchu:
- Same exchange name:
tchu_events - Same message format:
_tchu_metafield - Same routing key conventions
This allows gradual migration: apps using celery-salt can communicate with apps still using tchu-tchu.
Development
git clone https://github.com/sigularusrex/celery-salt.git
cd celery-salt
# tests
python -m pytest
License
MIT License - see LICENSE file for details.
Contributing
Please open an issue or pull request on GitHub.
Links
- GitHub:
https://github.com/sigularusrex/celery-salt - Issues:
https://github.com/sigularusrex/celery-salt/issues
Metadata
Release files for celery-salt 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| celery_salt-1.6.0.tar.gz | 44.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| celery_salt-1.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 100.2 kB
Release files / celery_salt-1.6.0.tar.gz
| Download URL | celery_salt-1.6.0.tar.gz |
|---|---|
| Size | 44.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3197068ed36761784f5f02c04d9ea9e2e18c525343645ccd43b79fad01af8498
|
|
BLAKE2b-256 checksum How to use checksums |
43b2b25ff31da68cf8b6b7eaa875be281c3525c260557c34b9dd80566359db40
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.5.1 CPython/3.11.3 Darwin/25.6.0
|
Release files / celery_salt-1.6.0-py3-none-any.whl
| Download URL | celery_salt-1.6.0-py3-none-any.whl |
|---|---|
| Size | 55.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
20fbb717e8021a725a68598ff59bfd0b48fd75baa3435006836156497e3a8337
|
|
BLAKE2b-256 checksum How to use checksums |
b6bca158117dccc955c24b7055452f9b4c86f1987bf3dda14fe6a81e179a7afd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.5.1 CPython/3.11.3 Darwin/25.6.0
|
Security for celery-salt 1.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.