name: service-guide description: Guide for implementing Backend.AI service layer (create, get, search, update, delete, purge, batch operations, Actions, ActionResults, Processors, ActionProcessor, Service methods) version: 1.0.0 dependencies: - repository-guide - tdd-guide tags: - service-layer - actions - processors - business-logic
Service Layer Implementation Guide
Guide for implementing Backend.AI service layer with Actions, Processors, and Service methods.
Standard Operations
Services implement 6 standard operations:
- create - Create new entity
- get - Retrieve single entity
- search - Query with filters
- update - Update entity
- delete - Delete entity
- purge - Permanently remove entity
Multi-target: batch_* (atomic, one statement) vs bulk_* (per-row, partial failures). See /repository-guide.
Method naming (no prefix):
await service.create_user(action: CreateUserAction)
await service.user(action: GetUserAction)
await service.search_users(action: SearchUsersAction)
await service.update_user(action: UpdateUserAction)
await service.delete_user(action: DeleteUserAction)
await service.purge_user(action: PurgeUserAction)
Architecture
API Handler → Processor → Service → Repository
Components:
- Actions: Immutable dataclasses (operations)
- ActionResults: Immutable dataclasses (results)
- Processors: Orchestrate with hooks and metrics
- Service Methods: Business logic
- Repositories: Data access
Directory Structure
services/{domain}/
├── types.py # Operation enums
├── service.py # Service protocol + implementation
├── processors.py # Processor package
└── actions/
├── base.py # Base action classes
├── create.py # Create action
├── get.py # Get action
├── search.py # Search action
├── update.py # Update action
├── delete.py # Delete action
└── purge.py # Purge action
Example: src/ai/backend/manager/services/storage_namespace/
Actions and ActionResults
Pattern:
- Frozen dataclasses for immutability
- Base classes define
entity_id()andoperation_type() - Concrete actions for each operation (create, get, search, update, delete, purge)
- Corresponding ActionResult types
See complete examples:
services/storage_namespace/actions/- Full action implementationsservices/storage_namespace/actions/base.py- Base classes
Processors
Pattern:
ActionProcessorwraps service methods- Provides hooks and metrics integration
- Expose processors via properties
- Initialize with service protocol
See complete examples:
services/storage_namespace/processors.py- Processor packageservices/processors.py- Base processor classes
Service Implementation
Pattern:
- Define Protocol with all operation methods
- Implement service class accepting Actions, returning ActionResults
- Follow: validate → business rules → repository call → return result
Operation patterns:
create_{entity}: Validate → check existence → create{entity}: Fetch → check not found → returnsearch_{entities}: Build scope/filters → repository.searchupdate_{entity}: Validate → update → returndelete_{entity}: Soft delete (status change)purge_{entity}: Hard delete
Repository Call Pattern
Core principle (preferred):
- Service method SHOULD call a single repository method
- Avoid combining multiple repository calls in service layer
- If complex composition is needed, consider adding specialized repository method
Transaction boundary:
- DB sessions are created and managed at repository method level
- Service methods do NOT create transactions directly
- Repository uses
begin_session()(write) orbegin_readonly_session()(read) - Each repository public method defines its own transaction scope
Exception cases:
- Multi-repository coordination is acceptable when business logic requires
- Example: Creating domain requires both domain and user_group repositories
- Document the reason when combining multiple repository calls
See complete examples:
services/storage_namespace/service.py:38-81- Single repository call patternservices/domain/service.py- Multi-repository coordination (exceptional case)repositories/README.md:54-61- Service-Repository integration principles
Implementation Workflow
Step 1: Define Operations Enum
File: services/{domain}/types.py
Define StrEnum with 6 operations: CREATE, GET, SEARCH, UPDATE, DELETE, PURGE
See: services/storage_namespace/types.py
Step 2: Create Base Actions
File: services/{domain}/actions/base.py
Define base classes with entity_id() and operation_type()
Step 3: Implement Concrete Actions
Files: services/{domain}/actions/{operation}.py
For each operation: create, get, search, update, delete, purge
Step 4: Define Service Protocol
File: services/{domain}/service.py
Protocol with all standard operations
Step 5: Implement Service
Same file
- Initialize with repository
- Implement all operations
- Follow: validate → business rules → repository → return result
Step 6: Create Processor Package
File: services/{domain}/processors.py
- Processor for each operation
- Expose via properties
Step 7: Write Tests
See: /tdd-guide for complete testing workflow
Critical: Service tests MUST mock repositories (no real DB)
Step 8: Integrate with API
See: /api-guide for REST and GraphQL integration
Common Patterns
| Operation | Key Steps | Exception Handling |
|---|---|---|
| create | validate → check existence → create → return | {Entity}AlreadyExists |
| get | fetch → not found check → return | {Entity}NotFound |
| search | build scope → repository.search → return | - |
| update | validate → fetch → update → return | {Entity}NotFound, Invalid{Entity} |
| delete | check exists → delete → return | {Entity}NotFound |
| purge | check exists → check dependencies → purge → return | {Entity}HasDependents |
Complete examples: src/ai/backend/manager/services/storage_namespace/service.py
Best Practices
Action Design
- Immutable:
@dataclass(frozen=True) - Complete: All operation params
- Self-describing names
Service Method Design
- Single responsibility
- Explicit exceptions (inherit BackendAIError)
- Repository coordination only
- Always return ActionResult
- Single repository call per method (preferred pattern)
- Transaction boundary managed by repository
Processor Design
- Thin orchestration
- Use ActionProcessor for hooks
- Property pattern
Testing
- Mock repositories (never real DB)
- Test business logic
- Verify repository calls
See: /tdd-guide skill
Related Documentation
- Repository Layer:
/repository-guide- Data access - API Integration:
/api-guide- REST/GraphQL - Testing:
/tdd-guide- TDD workflow - Service README:
src/ai/backend/manager/services/README.md
Examples
Complete implementations:
src/ai/backend/manager/services/storage_namespace/- Full servicesrc/ai/backend/manager/services/domain/- Multi-repositorysrc/ai/backend/manager/services/auth/- Hook integration
Summary
Standard operations:
- create, get, search, update, delete, purge
- batch_update, batch_delete, batch_purge
Components:
- Actions/ActionResults (immutable)
- Processors (orchestration)
- Service methods (business logic)
Testing: Mock repositories (no real DB)
Next steps:
- Study example services
- Define actions and operations
- Implement service methods
- Create processors
- Write tests (
/tdd-guide) - Integrate with API (
/api-guide)