382 lines
8.9 KiB
Markdown
382 lines
8.9 KiB
Markdown
# Library Cluster Architecture
|
|
|
|
## System Architecture Diagram
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "Frontend Layer"
|
|
A[Settings Page] --> B[Cluster Management UI]
|
|
C[Sidebar] --> D[Cluster Navigation]
|
|
E[Cluster View Page] --> F[Media Grid]
|
|
end
|
|
|
|
subgraph "API Layer"
|
|
G[/api/clusters]
|
|
H[/api/clusters/id]
|
|
I[/api/clusters/id/libraries]
|
|
J[/api/clusters/id/videos]
|
|
K[/api/clusters/id/stats]
|
|
end
|
|
|
|
subgraph "Database Layer"
|
|
L[(clusters)]
|
|
M[(library_cluster_mapping)]
|
|
N[(libraries)]
|
|
O[(media)]
|
|
end
|
|
|
|
B --> G
|
|
B --> H
|
|
B --> I
|
|
D --> G
|
|
F --> J
|
|
F --> K
|
|
|
|
G --> L
|
|
H --> L
|
|
I --> M
|
|
J --> O
|
|
K --> O
|
|
|
|
M --> L
|
|
M --> N
|
|
O --> N
|
|
```
|
|
|
|
## Data Model Relationships
|
|
|
|
```mermaid
|
|
erDiagram
|
|
CLUSTERS ||--o{ LIBRARY_CLUSTER_MAPPING : contains
|
|
LIBRARIES ||--o{ LIBRARY_CLUSTER_MAPPING : belongs_to
|
|
LIBRARIES ||--o{ MEDIA : contains
|
|
|
|
CLUSTERS {
|
|
int id PK
|
|
string name UK
|
|
string description
|
|
string color
|
|
string icon
|
|
datetime created_at
|
|
datetime updated_at
|
|
}
|
|
|
|
LIBRARY_CLUSTER_MAPPING {
|
|
int id PK
|
|
int library_id FK
|
|
int cluster_id FK
|
|
datetime created_at
|
|
}
|
|
|
|
LIBRARIES {
|
|
int id PK
|
|
string path UK
|
|
}
|
|
|
|
MEDIA {
|
|
int id PK
|
|
int library_id FK
|
|
string path
|
|
string type
|
|
string title
|
|
int size
|
|
}
|
|
```
|
|
|
|
## User Flow: Creating and Using a Cluster
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[User opens Settings] --> B[Navigate to Clusters section]
|
|
B --> C[Click Create Cluster]
|
|
C --> D[Enter cluster details]
|
|
D --> E{Name valid?}
|
|
E -->|No| D
|
|
E -->|Yes| F[Select color and icon]
|
|
F --> G[Click Save]
|
|
G --> H[Cluster created]
|
|
H --> I[Assign libraries to cluster]
|
|
I --> J[Select libraries from list]
|
|
J --> K[Confirm assignment]
|
|
K --> L[Cluster ready to use]
|
|
L --> M[Navigate via sidebar]
|
|
M --> N[View unified media from all libraries]
|
|
```
|
|
|
|
## API Request Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User
|
|
participant Frontend
|
|
participant API
|
|
participant Database
|
|
|
|
User->>Frontend: Click cluster in sidebar
|
|
Frontend->>API: GET /api/clusters/123/videos
|
|
API->>Database: SELECT media WHERE library_id IN (cluster_libraries)
|
|
Database-->>API: Return media records
|
|
API-->>Frontend: JSON response with videos
|
|
Frontend->>Frontend: Render virtual grid
|
|
Frontend-->>User: Display unified media view
|
|
```
|
|
|
|
## Component Hierarchy
|
|
|
|
```
|
|
App
|
|
├── Layout
|
|
│ ├── Sidebar
|
|
│ │ ├── Navigation
|
|
│ │ └── Clusters Section
|
|
│ │ ├── Cluster Item (Movies)
|
|
│ │ ├── Cluster Item (TV Shows)
|
|
│ │ └── Cluster Item (Anime)
|
|
│ │
|
|
│ └── Main Content Area
|
|
│ ├── Settings Page
|
|
│ │ ├── Library Management
|
|
│ │ └── Cluster Management
|
|
│ │ ├── Cluster List
|
|
│ │ ├── Create Cluster Form
|
|
│ │ └── Library Assignment UI
|
|
│ │
|
|
│ └── Cluster View Page
|
|
│ ├── Cluster Header
|
|
│ ├── Stats Cards
|
|
│ ├── Tab Navigation
|
|
│ └── Media Grid (Virtualized)
|
|
```
|
|
|
|
## Database Query Patterns
|
|
|
|
### Pattern 1: Get all clusters with library counts
|
|
```sql
|
|
SELECT
|
|
c.*,
|
|
COUNT(DISTINCT lcm.library_id) as library_count,
|
|
COUNT(DISTINCT m.id) as media_count
|
|
FROM clusters c
|
|
LEFT JOIN library_cluster_mapping lcm ON c.id = lcm.cluster_id
|
|
LEFT JOIN libraries l ON lcm.library_id = l.id
|
|
LEFT JOIN media m ON l.id = m.library_id
|
|
GROUP BY c.id
|
|
ORDER BY c.name;
|
|
```
|
|
|
|
### Pattern 2: Get all media for a cluster
|
|
```sql
|
|
SELECT m.*, l.path as library_path
|
|
FROM media m
|
|
INNER JOIN libraries l ON m.library_id = l.id
|
|
INNER JOIN library_cluster_mapping lcm ON l.id = lcm.library_id
|
|
WHERE lcm.cluster_id = ?
|
|
AND m.type = ?
|
|
ORDER BY m.created_at DESC
|
|
LIMIT ? OFFSET ?;
|
|
```
|
|
|
|
### Pattern 3: Get cluster statistics
|
|
```sql
|
|
SELECT
|
|
COUNT(CASE WHEN m.type = 'video' THEN 1 END) as video_count,
|
|
COUNT(CASE WHEN m.type = 'photo' THEN 1 END) as photo_count,
|
|
COUNT(CASE WHEN m.type = 'text' THEN 1 END) as text_count,
|
|
SUM(m.size) as total_size,
|
|
COUNT(DISTINCT l.id) as library_count
|
|
FROM media m
|
|
INNER JOIN libraries l ON m.library_id = l.id
|
|
INNER JOIN library_cluster_mapping lcm ON l.id = lcm.library_id
|
|
WHERE lcm.cluster_id = ?;
|
|
```
|
|
|
|
## State Management
|
|
|
|
### Cluster State
|
|
```typescript
|
|
interface ClusterState {
|
|
clusters: Cluster[];
|
|
selectedCluster: Cluster | null;
|
|
loading: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
interface Cluster {
|
|
id: number;
|
|
name: string;
|
|
description?: string;
|
|
color: string;
|
|
icon: string;
|
|
library_count?: number;
|
|
media_count?: number;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
```
|
|
|
|
### Library-Cluster Mapping State
|
|
```typescript
|
|
interface ClusterMapping {
|
|
clusterId: number;
|
|
libraryIds: number[];
|
|
}
|
|
|
|
interface LibraryWithClusters extends Library {
|
|
clusters: Cluster[];
|
|
}
|
|
```
|
|
|
|
## Performance Optimization Strategy
|
|
|
|
### 1. Database Level
|
|
- Composite indexes on `(cluster_id, library_id, type, created_at)`
|
|
- Materialized views for cluster statistics
|
|
- Connection pooling for concurrent queries
|
|
|
|
### 2. API Level
|
|
- Response caching with Redis (TTL: 5 minutes)
|
|
- Pagination for large result sets
|
|
- Batch operations for library assignments
|
|
|
|
### 3. Frontend Level
|
|
- Virtual scrolling for large media grids
|
|
- Lazy loading of cluster details
|
|
- Client-side caching of cluster metadata
|
|
- Optimistic UI updates
|
|
|
|
## Security Considerations
|
|
|
|
### Access Control Flow
|
|
```mermaid
|
|
graph LR
|
|
A[User Request] --> B{Authenticated?}
|
|
B -->|No| C[401 Unauthorized]
|
|
B -->|Yes| D{Has Library Access?}
|
|
D -->|No| E[403 Forbidden]
|
|
D -->|Yes| F{Cluster Exists?}
|
|
F -->|No| G[404 Not Found]
|
|
F -->|Yes| H[Return Data]
|
|
```
|
|
|
|
### Validation Rules
|
|
1. Cluster name: 1-100 characters, alphanumeric + spaces
|
|
2. Color: Valid hex color format (#RRGGBB)
|
|
3. Icon: From predefined list
|
|
4. Library assignments: Only existing library IDs
|
|
5. Prevent circular references
|
|
6. Rate limiting: 100 requests/minute per user
|
|
|
|
## Migration Strategy
|
|
|
|
### Phase 1: Schema Migration (No Downtime)
|
|
```sql
|
|
-- Add new tables without affecting existing ones
|
|
-- All existing functionality continues to work
|
|
```
|
|
|
|
### Phase 2: Gradual Rollout
|
|
1. Deploy backend with new tables (inactive)
|
|
2. Deploy UI with cluster management (opt-in)
|
|
3. Monitor performance and gather feedback
|
|
4. Promote feature to all users
|
|
|
|
### Phase 3: Data Backfill (Optional)
|
|
- Auto-create clusters based on library naming patterns
|
|
- Suggest cluster assignments using ML/heuristics
|
|
- Allow users to accept/reject suggestions
|
|
|
|
## Monitoring and Metrics
|
|
|
|
### Key Metrics to Track
|
|
1. **Usage Metrics**
|
|
- Number of clusters created
|
|
- Average libraries per cluster
|
|
- Most popular cluster types
|
|
|
|
2. **Performance Metrics**
|
|
- Cluster query response time
|
|
- Media aggregation performance
|
|
- Database query execution time
|
|
|
|
3. **User Engagement**
|
|
- Cluster view page visits
|
|
- Time spent on cluster views
|
|
- Feature adoption rate
|
|
|
|
## Error Handling
|
|
|
|
### Common Error Scenarios
|
|
1. **Duplicate Cluster Name**: Return 409 Conflict
|
|
2. **Library Not Found**: Return 404 Not Found
|
|
3. **Invalid Mapping**: Return 400 Bad Request
|
|
4. **Database Error**: Return 500 Internal Server Error
|
|
5. **Concurrent Modification**: Use optimistic locking
|
|
|
|
## Testing Checklist
|
|
|
|
### Unit Tests
|
|
- [ ] Cluster CRUD operations
|
|
- [ ] Library-cluster mapping
|
|
- [ ] Media queries by cluster
|
|
- [ ] Statistics calculation
|
|
- [ ] Validation rules
|
|
|
|
### Integration Tests
|
|
- [ ] End-to-end cluster creation
|
|
- [ ] Multi-library media aggregation
|
|
- [ ] Pagination with large datasets
|
|
- [ ] Concurrent user access
|
|
|
|
### Performance Tests
|
|
- [ ] 1000+ media items per cluster
|
|
- [ ] 10+ libraries per cluster
|
|
- [ ] 50+ concurrent cluster queries
|
|
- [ ] Database index effectiveness
|
|
|
|
### UI/UX Tests
|
|
- [ ] Responsive design
|
|
- [ ] Accessibility (WCAG 2.1)
|
|
- [ ] Browser compatibility
|
|
- [ ] Mobile experience
|
|
|
|
## Rollback Plan
|
|
|
|
### If Issues Occur
|
|
1. **Minor Issues**: Hot-fix and redeploy
|
|
2. **Major Issues**:
|
|
- Disable cluster UI features
|
|
- Keep database tables (no data loss)
|
|
- Investigate and fix
|
|
- Re-enable when stable
|
|
|
|
### Database Rollback (If Needed)
|
|
```sql
|
|
-- Only if absolutely necessary
|
|
DROP TABLE library_cluster_mapping;
|
|
DROP TABLE clusters;
|
|
-- Application continues to work without cluster features
|
|
```
|
|
|
|
## Future Enhancements Roadmap
|
|
|
|
### Q1 2026
|
|
- Smart auto-categorization
|
|
- Cluster templates
|
|
- Import/export configurations
|
|
|
|
### Q2 2026
|
|
- Cross-cluster search
|
|
- Advanced analytics
|
|
- Cluster sharing between users
|
|
|
|
### Q3 2026
|
|
- AI-powered recommendations
|
|
- Cluster-based permissions
|
|
- Scheduled scanning per cluster
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Last Updated**: 2025-10-11
|
|
**Related Documents**: LIBRARY_CLUSTER_FEATURE.md
|