From 9583c7c3d251656605d75b8e2b7c1eeed6be7b53 Mon Sep 17 00:00:00 2001 From: fullex <0xfullex@gmail.com> Date: Wed, 26 Nov 2025 12:07:41 +0800 Subject: [PATCH] docs: enhance README with detailed service usage guidelines and decision flowchart --- src/renderer/src/data/README.md | 124 +++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/data/README.md b/src/renderer/src/data/README.md index d5e7d14e4d..1267685e8d 100644 --- a/src/renderer/src/data/README.md +++ b/src/renderer/src/data/README.md @@ -232,9 +232,127 @@ const [recentFiles, setRecentFiles] = usePersistCache('app.recent_files') ### When to Use Which Service -- **DataApiService**: For database operations, API calls, and any data that needs to persist -- **PreferenceService**: For user settings, app configuration, and preferences -- **CacheService**: For temporary data, computed results, and performance optimization +The three services map to distinct data categories based on the original architecture design. Use the following guide to choose the right service. + +#### Quick Decision Table + +| Service | Data Characteristics | Lifecycle | Data Loss Impact | Examples | +|---------|---------------------|-----------|------------------|----------| +| **CacheService** | Regenerable, temporary | ≤ App process or survives restart | None to minimal | API responses, computed results, UI state | +| **PreferenceService** | User settings, key-value | Permanent until changed | Low (can rebuild) | Theme, language, font size, shortcuts | +| **DataApiService** | Business data, structured | Permanent | **Severe** (irreplaceable) | Topics, messages, files, knowledge base | + +#### CacheService - Runtime & Cache Data + +Use CacheService when: +- Data can be **regenerated or lost without user impact** +- No backup or cross-device synchronization needed +- Lifecycle is tied to component, window, or app session + +**Two sub-categories**: +1. **Performance cache**: Computed results, API responses, expensive calculations +2. **UI state cache**: Temporary settings, scroll positions, panel states + +**Three tiers based on persistence needs**: +- `useCache` (memory): Lost on app restart, component-level sharing +- `useSharedCache` (shared): Cross-window sharing, lost on restart +- `usePersistCache` (persist): Survives app restarts via localStorage + +```typescript +// Good: Temporary computed results +const [searchResults, setSearchResults] = useCache('search.results', []) + +// Good: UI state that can be lost +const [sidebarCollapsed, setSidebarCollapsed] = useSharedCache('ui.sidebar.collapsed', false) + +// Good: Recent items (nice to have, not critical) +const [recentSearches, setRecentSearches] = usePersistCache('search.recent', []) +``` + +#### PreferenceService - User Preferences + +Use PreferenceService when: +- Data is a **user-modifiable setting that affects app behavior** +- Structure is key-value with **predefined keys** (users modify values, not keys) +- **Value structure is stable** (won't change frequently) +- Data loss has **low impact** (user can reconfigure) + +**Key characteristics**: +- Auto-syncs across all windows +- Each preference item should be **atomic** (one setting = one key) +- Values are typically: boolean, string, number, or simple array/object + +```typescript +// Good: App behavior settings +const [theme, setTheme] = usePreference('app.theme.mode') +const [language, setLanguage] = usePreference('app.language') +const [fontSize, setFontSize] = usePreference('chat.message.font_size') + +// Good: Feature toggles +const [showTimestamp, setShowTimestamp] = usePreference('chat.display.show_timestamp') +``` + +#### DataApiService - User Data + +Use DataApiService when: +- Data is **business data accumulated through user activity** +- Data is **structured with dedicated schemas/tables** +- Users can **create, delete, modify records** (no fixed limit) +- Data loss would be **severe and irreplaceable** +- Data volume can be **large** (potentially GBs) + +**Key characteristics**: +- No automatic window sync (fetch on demand for fresh data) +- May contain sensitive data (encryption consideration) +- Requires proper CRUD operations and transactions + +```typescript +// Good: User-generated business data +const { data: topics } = useQuery('/topics') +const { trigger: createTopic } = useMutation('/topics', 'POST') + +// Good: Conversation history (irreplaceable) +const { data: messages } = useQuery('/messages', { query: { topicId } }) + +// Good: User files and knowledge base +const { data: files } = useQuery('/files') +``` + +#### Decision Flowchart + +Ask these questions in order: + +1. **Can this data be regenerated or lost without affecting the user?** + - Yes → **CacheService** + - No → Continue to #2 + +2. **Is this a user-configurable setting that affects app behavior?** + - Yes → Does it have a fixed key and stable value structure? + - Yes → **PreferenceService** + - No (structure changes often) → **DataApiService** + - No → Continue to #3 + +3. **Is this business data created/accumulated through user activity?** + - Yes → **DataApiService** + - No → Reconsider #1 (most data falls into one of these categories) + +#### Common Anti-patterns + +| Wrong Choice | Why It's Wrong | Correct Choice | +|--------------|----------------|----------------| +| Storing AI provider configs in Cache | User loses configured providers on restart | **PreferenceService** | +| Storing conversation history in Preferences | Unbounded growth, complex structure | **DataApiService** | +| Storing topic list in Preferences | User-created records, can grow large | **DataApiService** | +| Storing theme/language in DataApi | Overkill for simple key-value settings | **PreferenceService** | +| Storing API responses in DataApi | Regenerable data, doesn't need persistence | **CacheService** | +| Storing window positions in Preferences | Can be lost without impact | **CacheService** (persist tier) | + +#### Edge Cases + +- **Recently used items** (e.g., recent files, recent searches): Use `usePersistCache` - nice to have but not critical if lost +- **Draft content** (e.g., unsaved message): Use `useSharedCache` for cross-window, consider auto-save to DataApi for recovery +- **Computed statistics**: Use `useCache` with TTL - regenerate when expired +- **User-created templates/presets**: Use **DataApiService** - user-generated content that can grow ### Performance Guidelines