feat: enhance CacheService and DataApiService documentation and structure

- Added detailed file overview comments to CacheService and DataApiService, clarifying their roles as infrastructure components rather than business services.
- Updated README.md to reflect the new structure and naming conventions, emphasizing the distinction between infrastructure and business logic components.
- Introduced a new TestService for API testing scenarios, providing mock data and various test cases.
- Created IBaseService interface to standardize service operations across the codebase.
- Improved organization of API handlers and services for better clarity and maintainability.
This commit is contained in:
fullex 2025-11-01 18:36:28 +08:00
parent 5101488d65
commit 62ccb6105d
8 changed files with 405 additions and 56 deletions

View File

@ -1,3 +1,22 @@
/**
* @fileoverview CacheService - Infrastructure component for multi-tier caching
*
* NAMING NOTE:
* This component is named "CacheService" for management consistency, but it is
* actually an infrastructure component (cache manager) rather than a business service.
*
* True Nature: Cache Manager / Infrastructure Utility
* - Provides low-level caching primitives (memory/shared/persist tiers)
* - Manages TTL, expiration, and cross-window synchronization via IPC
* - Contains zero business logic - purely technical functionality
* - Acts as a utility for other services (PreferenceService, business services)
*
* The "Service" suffix is kept for consistency with existing codebase conventions,
* but developers should understand this is infrastructure, not business logic.
*
* @see {@link CacheService} For implementation details
*/
import { loggerService } from '@logger'
import type { CacheEntry, CacheSyncMessage } from '@shared/data/cache/cacheTypes'
import { IpcChannel } from '@shared/IpcChannel'

View File

@ -1,3 +1,28 @@
/**
* @fileoverview DataApiService - API coordination and orchestration (Main Process)
*
* NAMING NOTE:
* This component is named "DataApiService" for management consistency, but it is
* actually a coordinator/orchestrator rather than a business service.
*
* True Nature: API Coordinator / Orchestrator
* - Initializes and coordinates the Data API framework
* - Wires together ApiServer (routing) and IpcAdapter (IPC communication)
* - Manages lifecycle (startup/shutdown) of API infrastructure
* - Contains zero business logic - purely infrastructure plumbing
*
* Architecture:
* DataApiService coordinates ApiServer + IpcAdapter
* ApiServer routes requests Handlers Services DB
* IpcAdapter bridges IPC ApiServer
*
* The "Service" suffix is kept for consistency with existing codebase conventions,
* but developers should understand this is a coordinator, not a business service.
*
* @see {@link ApiServer} For request routing logic
* @see {@link IpcAdapter} For IPC communication bridge
*/
import { loggerService } from '@logger'
import { ApiServer, IpcAdapter } from './api'

View File

@ -6,58 +6,201 @@ This directory contains the main process data management system, providing unifi
```
src/main/data/
├── api/ # Data API framework
│ ├── core/ # Core API infrastructure
│ │ ├── ApiServer.ts # Request routing and handler execution
├── api/ # Data API framework (interface layer)
│ ├── core/ # Core API infrastructure
│ │ ├── ApiServer.ts # Request routing and handler execution
│ │ ├── MiddlewareEngine.ts # Request/response middleware
│ │ └── adapters/ # Communication adapters
│ ├── handlers/ # API endpoint implementations
│ ├── services/ # Business logic services
│ └── index.ts # API framework exports
├── db/ # Database layer
│ ├── schemas/ # Drizzle table definitions
│ ├── seeding/ # Database initialization
│ └── DbService.ts # Database connection and management
├── migrate/ # Data migration system
│ └── dataRefactor/ # v2 data refactoring migration tools
├── CacheService.ts # Main process cache management
├── DataApiService.ts # Data API coordination service
└── PreferenceService.ts # User preferences management
│ │ └── adapters/ # Communication adapters (IPC)
│ ├── handlers/ # API endpoint implementations
│ │ └── index.ts # Thin handlers: param extraction, DTO conversion
│ └── index.ts # API framework exports
├── services/ # Business logic layer
│ ├── base/ # Service base classes and interfaces
│ │ └── IBaseService.ts # Service interface definitions
│ └── TestService.ts # Test service (placeholder for real services)
│ # Future business services:
│ # - TopicService.ts # Topic business logic
│ # - MessageService.ts # Message business logic
│ # - FileService.ts # File business logic
├── repositories/ # Data access layer (selective usage)
│ # Repository pattern used selectively for complex domains
│ # Future repositories:
│ # - TopicRepository.ts # Complex: Topic data access
│ # - MessageRepository.ts # Complex: Message data access
├── db/ # Database layer
│ ├── schemas/ # Drizzle table definitions
│ │ ├── preference.ts # Preference configuration table
│ │ ├── appState.ts # Application state table
│ │ └── columnHelpers.ts # Reusable column definitions
│ ├── seeding/ # Database initialization
│ └── DbService.ts # Database connection and management
├── migrate/ # Data migration system
│ └── dataRefactor/ # v2 data refactoring migration tools
├── CacheService.ts # Infrastructure: Cache management
├── DataApiService.ts # Infrastructure: API coordination
└── PreferenceService.ts # System service: User preferences
```
## Core Services
## Core Components
### CacheService
- **Purpose**: Main process caching with TTL support
- **Features**: Memory cache, IPC synchronization, cross-window broadcasting
- **Usage**: Internal caching for main process services
### Naming Note
### PreferenceService
- **Purpose**: Type-safe user configuration management
- **Features**: SQLite persistence, multi-window sync, batch operations
- **Usage**: Managing user settings and application configuration
Three components at the root of `data/` use the "Service" suffix but serve different purposes:
### DataApiService
- **Purpose**: Coordinates API server and IPC communication
- **Features**: Request routing, error handling, type safety
- **Usage**: Central hub for all data API operations
#### CacheService (Infrastructure Component)
- **True Nature**: Cache Manager / Infrastructure Utility
- **Purpose**: Multi-tier caching system (memory/shared/persist)
- **Features**: TTL support, IPC synchronization, cross-window broadcasting
- **Characteristics**: Zero business logic, purely technical functionality
- **Note**: Named "Service" for management consistency, but is actually infrastructure
## Data API Framework
#### DataApiService (Coordinator Component)
- **True Nature**: API Coordinator (Main) / API Client (Renderer)
- **Main Process Purpose**: Coordinates ApiServer and IpcAdapter initialization
- **Renderer Purpose**: HTTP-like client for IPC communication
- **Characteristics**: Zero business logic, purely coordination/communication plumbing
- **Note**: Named "Service" for management consistency, but is actually coordinator/client
### API Server (`api/core/ApiServer.ts`)
#### PreferenceService (System Service)
- **True Nature**: System-level Data Access Service
- **Purpose**: User configuration management with caching and multi-window sync
- **Features**: SQLite persistence, full memory cache, cross-window synchronization
- **Characteristics**: Minimal business logic (validation, defaults), primarily data access
- **Note**: Hybrid between data access and infrastructure, "Service" naming is acceptable
**Key Takeaway**: Despite all being named "Service", these are infrastructure/coordination components, not business services. The "Service" suffix is kept for consistency with existing codebase conventions.
## Architecture Layers
### API Framework Layer (`api/`)
The API framework provides the interface layer for data access:
#### API Server (`api/core/ApiServer.ts`)
- Request routing and handler execution
- Middleware pipeline processing
- Type-safe endpoint definitions
### Handlers (`api/handlers/`)
- Endpoint implementations for business logic
- Currently contains test handlers (production handlers pending)
- Must implement types defined in `@shared/data/api`
#### Handlers (`api/handlers/`)
- **Purpose**: Thin API endpoint implementations
- **Responsibilities**:
- HTTP-like parameter extraction from requests
- DTO/domain model conversion
- Delegating to business services
- Transforming responses for IPC
- **Anti-pattern**: Do NOT put business logic in handlers
- **Currently**: Contains test handlers (production handlers pending)
- **Type Safety**: Must implement all endpoints defined in `@shared/data/api`
### Services (`api/services/`)
- Business logic layer
- Database operations and data validation
- Called by API handlers
### Business Logic Layer (`services/`)
Business services implement domain logic and workflows:
#### When to Create a Service
- Contains business rules and validation
- Orchestrates multiple repositories or data sources
- Implements complex workflows
- Manages transactions across multiple operations
#### Service Pattern
Just an example for understanding.
```typescript
// services/TopicService.ts
export class TopicService {
constructor(
private topicRepo: TopicRepository, // Use repository for complex data access
private cacheService: CacheService // Use infrastructure utilities
) {}
async createTopicWithMessage(data: CreateTopicDto) {
// Business validation
this.validateTopicData(data)
// Transaction coordination
return await DbService.transaction(async (tx) => {
const topic = await this.topicRepo.create(data.topic, tx)
const message = await this.messageRepo.create(data.message, tx)
return { topic, message }
})
}
}
```
#### Current Services
- `TestService`: Placeholder service for testing API framework
- More business services will be added as needed (TopicService, MessageService, etc.)
### Data Access Layer (`repositories/`)
Repositories handle database operations with a **selective usage pattern**:
#### When to Use Repository Pattern
Use repositories for **complex domains** that meet multiple criteria:
- ✅ Complex queries (joins, subqueries, aggregations)
- ✅ GB-scale data requiring optimization and pagination
- ✅ Complex transactions involving multiple tables
- ✅ Reusable data access patterns across services
- ✅ High testing requirements (mock data access in tests)
#### When to Use Direct Drizzle in Services
Skip repository layer for **simple domains**:
- ✅ Simple CRUD operations
- ✅ Small datasets (< 100MB)
- ✅ Domain-specific queries with no reuse potential
- ✅ Fast development is priority
#### Repository Pattern
Just an example for understanding.
```typescript
// repositories/TopicRepository.ts
export class TopicRepository {
async findById(id: string, tx?: Transaction): Promise<Topic | null> {
const db = tx || DbService.db
return await db.select()
.from(topicTable)
.where(eq(topicTable.id, id))
.limit(1)
}
async findByIdWithMessages(
topicId: string,
pagination: PaginationOptions
): Promise<TopicWithMessages> {
// Complex join query with pagination
// Handles GB-scale data efficiently
}
}
```
#### Direct Drizzle Pattern (Simple Services)
```typescript
// services/SimpleService.ts
export class SimpleService extends BaseService {
async getItem(id: string) {
// Direct Drizzle query for simple operations
return await this.database
.select()
.from(itemTable)
.where(eq(itemTable.id, id))
}
}
```
#### Planned Repositories
- **TopicRepository**: Complex topic data access with message relationships
- **MessageRepository**: GB-scale message queries with pagination
- **FileRepository**: File reference counting and cleanup logic
**Decision Principle**: Use the simplest approach that solves the problem. Add repository abstraction only when complexity demands it.
## Database Layer
@ -89,32 +232,144 @@ import { dataApiService } from '@/data/DataApiService'
### Adding New API Endpoints
1. Define endpoint in `@shared/data/api/apiSchemas.ts`
2. Implement handler in `api/handlers/index.ts`
3. Create service in `api/services/` if needed
4. Add database schema in `db/schemas/` if required
2. Implement handler in `api/handlers/index.ts` (thin layer, delegate to service)
3. Create business service in `services/` for domain logic
4. Create repository in `repositories/` if domain is complex (optional)
5. Add database schema in `db/schemas/` if required
### Adding Database Tables
1. Create schema in `db/schemas/{tableName}.ts`
2. Generate migration: `yarn run migrations:generate`
3. Add seeding data in `db/seeding/` if needed
4. Create corresponding service in `api/services/`
4. Decide: Repository pattern or direct Drizzle?
- Complex domain → Create repository in `repositories/`
- Simple domain → Use direct Drizzle in service
5. Create business service in `services/`
6. Implement API handler in `api/handlers/`
### Creating a New Business Service
**For complex domains (with repository)**:
```typescript
// 1. Create repository: repositories/ExampleRepository.ts
export class ExampleRepository {
async findById(id: string, tx?: Transaction) { /* ... */ }
async create(data: CreateDto, tx?: Transaction) { /* ... */ }
}
// 2. Create service: services/ExampleService.ts
export class ExampleService {
constructor(private exampleRepo: ExampleRepository) {}
async createExample(data: CreateDto) {
// Business validation
this.validate(data)
// Use repository
return await this.exampleRepo.create(data)
}
}
// 3. Create handler: api/handlers/example.ts
import { ExampleService } from '../../services/ExampleService'
export const exampleHandlers = {
'POST /examples': async ({ body }) => {
return await ExampleService.getInstance().createExample(body)
}
}
```
**For simple domains (direct Drizzle)**:
```typescript
// 1. Create service: services/SimpleService.ts
export class SimpleService extends BaseService {
async getItem(id: string) {
// Direct database access
return await this.database
.select()
.from(itemTable)
.where(eq(itemTable.id, id))
}
}
// 2. Create handler: api/handlers/simple.ts
export const simpleHandlers = {
'GET /items/:id': async ({ params }) => {
return await SimpleService.getInstance().getItem(params.id)
}
}
```
## Data Flow
### Complete Request Flow
```
Renderer IPC Request
DataApiService (coordination)
ApiServer (routing)
Handler (endpoint logic)
Service (business logic)
DbService (data persistence)
┌─────────────────────────────────────────────────────┐
│ Renderer Process │
│ React Component → useDataApi Hook │
└────────────────┬────────────────────────────────────┘
│ IPC Request
┌────────────────▼────────────────────────────────────┐
│ Infrastructure Layer │
│ DataApiService (coordinator) │
│ ↓ │
│ ApiServer (routing) → MiddlewareEngine │
└────────────────┬────────────────────────────────────┘
┌────────────────▼────────────────────────────────────┐
│ API Layer (api/handlers/) │
│ Handler: Thin layer │
│ - Extract parameters │
│ - Call business service │
│ - Transform response │
└────────────────┬────────────────────────────────────┘
┌────────────────▼────────────────────────────────────┐
│ Business Logic Layer (services/) │
│ Service: Domain logic │
│ - Business validation │
│ - Transaction coordination │
│ - Call repository or direct DB │
└────────────────┬────────────────────────────────────┘
┌──────────┴──────────┐
│ │
┌─────▼─────────┐ ┌──────▼──────────────────────────┐
│ repositories/ │ │ Direct Drizzle │
│ (Complex) │ │ (Simple domains) │
│ - Repository │ │ - Service uses DbService.db │
│ - Query logic │ │ - Inline queries │
└─────┬─────────┘ └──────┬──────────────────────────┘
│ │
└──────────┬─────────┘
┌────────────────▼────────────────────────────────────┐
│ Database Layer (db/) │
│ DbService → SQLite (Drizzle ORM) │
└─────────────────────────────────────────────────────┘
```
### Architecture Principles
1. **Separation of Concerns**
- Handlers: Request/response transformation only
- Services: Business logic and orchestration
- Repositories: Data access (when complexity demands it)
2. **Dependency Flow** (top to bottom only)
- Handlers depend on Services
- Services depend on Repositories (or DbService directly)
- Repositories depend on DbService
- **Never**: Services depend on Handlers
- **Never**: Repositories contain business logic
3. **Selective Repository Usage**
- Use Repository: Complex domains (Topic, Message, File)
- Direct Drizzle: Simple domains (Agent, Session, Translate)
- Decision based on: query complexity, data volume, testing needs
## Development Guidelines
- All services use singleton pattern

View File

@ -5,10 +5,9 @@
* TypeScript will error if any endpoint is missing.
*/
import { TestService } from '@data/services/TestService'
import type { ApiImplementation } from '@shared/data/api/apiSchemas'
import { TestService } from '../services/TestService'
// Service instances
const testService = TestService.getInstance()

View File

@ -1,3 +1,22 @@
/**
* @fileoverview CacheService - Infrastructure component for multi-tier caching (Renderer)
*
* NAMING NOTE:
* This component is named "CacheService" for management consistency, but it is
* actually an infrastructure component (cache manager) rather than a business service.
*
* True Nature: Cache Manager / Infrastructure Utility
* - Provides 3-tier caching system (memory/shared/persist)
* - Manages synchronization with Main process and other windows
* - Contains zero business logic - purely technical functionality
* - Used by React components via hooks (useCache, useSharedCache, usePersistCache)
*
* The "Service" suffix is kept for consistency with existing codebase conventions,
* but developers should understand this is infrastructure, not business logic.
*
* @see {@link CacheService} For implementation details
*/
import { loggerService } from '@logger'
import type {
RendererPersistCacheKey,

View File

@ -1,3 +1,35 @@
/**
* @fileoverview DataApiService - API client for data requests (Renderer Process)
*
* NAMING NOTE:
* This component is named "DataApiService" for management consistency, but it is
* actually an API client rather than a business service.
*
* True Nature: API Client / Gateway
* - Provides HTTP-like interface for making data requests to Main process
* - Wraps IPC communication with type-safe, retry-enabled interface
* - Acts as a Gateway/Facade for all data operations from renderer
* - Contains zero business logic - purely communication infrastructure
*
* Key Features:
* - Type-safe requests with full TypeScript inference
* - Automatic retry with exponential backoff (network, timeout, 500/503 errors)
* - Request timeout management (3s default)
* - Batch request support for performance
* - Subscription management (real-time updates)
*
* Architecture:
* React Component DataApiService (this file) IPC Main Process
* Main Process Handlers Services DB IPC Response
* DataApiService Updates component state
*
* The "Service" suffix is kept for consistency with existing codebase conventions,
* but developers should understand this is an API client (similar to axios, fetch).
*
* @see {@link DataApiService} Main process coordinator
* @see {@link useDataApi} React hook for data requests
*/
import { loggerService } from '@logger'
import type { ApiClient, ConcreteApiPaths } from '@shared/data/api/apiSchemas'
import type {