Use this file to discover all available pages before exploring further.
HexCore’s task-queue integration is built around a single interface — ITaskEnqueuer — that your command bus, event bus, and scheduler call to offload work to a background worker. Two adapter implementations are provided out of the box: CeleryEnqueuer for Redis/RabbitMQ-backed queues, and ProcrastinateEnqueuer for PostgreSQL-native queuing. This guide covers both adapters, the universal CQRSConsumer that runs on the worker side, and a complete wiring example.
Called automatically by InMemoryCommandBus when the command class is decorated with @background_command. Sends the serialised command payload to the worker.
Called when a generic async function decorated with @background_task is enqueued. The payload dict becomes the **kwargs of the task function on the worker.
CeleryEnqueuer wraps celery.Celery.send_task (a synchronous call) inside asyncio.to_thread so it never blocks the FastAPI event loop. Pass your Celery app instance to the constructor:
Call this on the worker side to register the three task routes in the Celery app. It wires CQRSConsumer methods as Celery task handlers using asyncio.run():
CQRSConsumer is the universal worker-side dispatcher. It receives serialised payloads from the queue backend, deserialises them, and routes them to the correct local bus or handler.
from hexcore.infrastructure.workers.consumer import CQRSConsumerconsumer = CQRSConsumer( command_bus=command_bus, # AbstractCommandBus with handlers registered event_bus=event_bus, # AbstractEventBus with subscribers registered serializer=serializer, # ISerializer (e.g. PydanticSerializer))
Use the CQRS decorators to mark which commands, handlers, and tasks should run in the background. HexCore reads these annotations at runtime to call the correct ITaskEnqueuer method automatically:
src/domain/notifications/commands.py
from hexcore.domain.cqrs.decorators import background_command, background_handler, background_taskfrom hexcore.domain.cqrs.commands import Commandfrom src.domain.users.events import UserCreatedEvent# Entire command goes to a background worker@background_command(queue="notifications")class SendWelcomeEmailCommand(Command): user_id: str email: str# Only this handler runs in background; other handlers for the same event run inline@background_handler(queue="analytics")async def track_signup_analytics(event: UserCreatedEvent) -> None: # expensive analytics call ...# Generic background task not tied to a command or event@background_task(queue="maintenance")async def purge_expired_sessions(days: int) -> None: ...
The @background_command and @background_handler decorators attach __cqrs_task_name__ and __cqrs_queue__ attributes to the decorated class or function. HexCore’s buses read these automatically — you never call enqueue_command or enqueue_handler directly.