nextav/docs/active/library-clusters/LIBRARY_CLUSTER_ARCHITECTUR...

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