Worker Architecture and Dependencies
The worker shares code, models, and the database with the backend API, connected through a Redis broker.
Component Relationships
Backend-Worker Interdependencies
How Tasks Flow Through the System
- Backend API: Endpoints receive client requests and enqueue asynchronous tasks
- Broker: Redis-based queue stores pending tasks (with TLS support)
- Worker: Processes tasks from the queue and executes business logic
- Database: Shared between backend and worker for storing and retrieving application data
- SDK: Provides shared utilities and models used by both components
Code Dependencies
The worker depends on the backend code in several ways:
- Shared Models: The worker needs access to the same data models defined in the backend
- Database Access: Worker tasks use the same database connection/ORM layer as the backend
- Business Logic: Tasks often execute backend business logic in an asynchronous context
- Context Management: The worker needs to maintain the same multi-tenant context system
Example import hierarchy:
SDK Dependencies
Both the worker and backend depend on the Rhesis SDK for:
- Client Libraries: API clients for external services (e.g., LLM providers)
- Shared Utilities: Common functions used by both backend and worker
- Type Definitions: Shared type definitions and interfaces
- Configuration Management: Loading and accessing configuration
Deployment Considerations
Package Structure
When deploying the worker, it must include:
- The entire
rhesis.backendpackage - The
rhesis.sdkpackage - Worker-specific code (
rhesis.backend.tasksandrhesis.backend.worker)
Environment Configuration
The worker requires the same environment variables as the backend, plus additional worker-specific settings:
Managing Circular Dependencies
One challenge in the worker-backend relationship is avoiding circular dependencies. The system follows these patterns:
- Worker tasks can import backend modules
- Backend modules should not directly import worker tasks (use dynamic imports if needed)
- Shared dependencies go in the SDK package
- Base task classes, task organization, and worker configuration belong in
rhesis.backend.tasks
Task Context and State
Because the worker executes backend code asynchronously:
- The tenant context (organization/user IDs) must be explicitly passed to tasks
- Database sessions must be properly managed (opened and closed)
- Any state or context that would normally be available in an API request must be reconstructed
This is handled through: