Service Architecture
Understanding the service-oriented architecture in Zyeta
Zyeta employs a service-oriented architecture built on FastAPI that emphasizes modularity, discoverability, and maintainability. This document explains the core components and patterns used in the service layer.
Core Concepts
The service architecture is built around these key concepts:
- Service Classes: Self-contained modules that handle specific domain functionality
- Automatic Discovery: Services are automatically discovered and registered with the FastAPI application
- HTTP Exposure: Methods can be selectively exposed as HTTP endpoints
- Dependency Injection: Services receive dependencies through a centralized Acquire class
Service Structure
Each service in Zyeta follows a consistent pattern:
Key Components
- Service Class: Named with a
Service
suffix (e.g.,AuthService
,KBService
) - HTTP Exposure List: Lists methods to be exposed as HTTP endpoints
- Acquire Dependency: Receives centralized dependencies
- Method Naming: Follows
http_method_resource_name
pattern
Service Registration
Services are automatically discovered and registered with the FastAPI application through the Manager class:
The service discovery process:
- The Manager recursively searches for
service.py
files in all subdirectories - It captures the directory path segments (e.g., v1/auth) to build the API path
- It looks for classes ending with
Service
suffix - It instantiates the service with the Acquire dependency
- It creates a FastAPI router with the appropriate prefix (e.g., /api/v1/auth)
- It registers routes based on the
http_exposed
list - It includes the router in the main FastAPI application
API Versioning
Zyeta supports API versioning through its directory structure. The Manager class automatically handles versioning by including directory names in the API path:
The versioning system works by:
- Recursively scanning all subdirectories in the services directory
- Including all directory names in the API route path
- Creating appropriate routers with prefixes matching the directory structure
- Allowing multiple versions of the same service to coexist
This enables:
- API Evolution: Maintaining backward compatibility while adding new features
- Clean Migrations: Moving clients from one API version to another
- Feature Testing: Testing new API versions with limited users
For example, a method post_signup
in services/v1/auth/service.py
would be exposed at /api/v1/auth/signup
, while the same method in services/v2/auth/service.py
would be exposed at /api/v2/auth/signup
.
The following diagram illustrates how the service directory structure maps to API endpoints:
HTTP Endpoint Exposure
Services explicitly define which methods are exposed as HTTP endpoints using the http_exposed
list:
The format follows http_method=resource_name
pattern, which maps to method names of the form http_method_resource_name
(e.g., post_signup
).
The Acquire Pattern
The Acquire class serves as a centralized dependency container that provides services with:
- Access to database sessions
- References to other services
- Shared utilities and configurations
- Logging capabilities
- WebSocket management
This pattern enables:
- Service-to-service communication
- Dependency sharing across the application
- Testability through dependency mocking
- Consistent configuration access
Working with Versioned Services
When working with versioned services, the Acquire pattern provides access to different service versions:
This capability is especially useful when:
- Implementing gradual migrations from one API version to another
- Building composite responses that require features from multiple API versions
- Accessing versioned schemas for data validation
Core Services
Zyeta is organized around domain-specific services:
Service Schemas
Each service defines its own schemas using Pydantic models:
These schemas provide:
- Input validation: Ensures data meets requirements
- Output serialization: Standardizes response formats
- Documentation: Auto-generates API docs via OpenAPI
WebSocket Support
Services can also expose WebSocket endpoints using a similar pattern:
WebSocket connections are managed through a centralized WebSocketManager that handles:
- Connection acceptance
- Client tracking
- Broadcasting messages
- Connection lifecycle
Security Integration
Services integrate with FastAPI’s dependency injection system for security:
Security is implemented through:
- JWT Authentication: Token-based authentication
- RBAC: Role-based access control
- Permission Validation: Fine-grained permission checks
Request Lifecycle
When a request hits an endpoint:
- The request is routed to the appropriate service method
- Input is validated against Pydantic schemas
- The service method executes business logic
- Database operations are performed
- The response is serialized
- The HTTP response is returned
Best Practices
When developing services in Zyeta:
- Follow the Naming Convention: Use
method_resource
format - Keep Methods Focused: Each method should handle one specific operation
- Use Dependency Injection: Receive dependencies via parameters
- Validate Inputs: Use Pydantic schemas for validation
- Handle Errors: Use try/except blocks with detailed error messages
- Document Methods: Use docstrings to describe functionality
- Log Appropriately: Use the logger for important events
- Version Carefully: Place new services in appropriate version directories (e.g., v1, v2)
- Maintain Compatibility: When creating a new version, ensure breaking changes are only in new versions
- Document Version Changes: Clearly document differences between API versions
Testing Services
Services are designed for testability:
This approach enables:
- Unit Testing: Testing services in isolation
- Mocking Dependencies: Replacing real dependencies with mocks
- Integration Testing: Testing service interactions
- Functional Testing: Testing complete request flow
Was this page helpful?