8.9 KiB
8.9 KiB
Library Cluster Architecture
System Architecture Diagram
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
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
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
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
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
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
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
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
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
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
- Cluster name: 1-100 characters, alphanumeric + spaces
- Color: Valid hex color format (#RRGGBB)
- Icon: From predefined list
- Library assignments: Only existing library IDs
- Prevent circular references
- Rate limiting: 100 requests/minute per user
Migration Strategy
Phase 1: Schema Migration (No Downtime)
-- Add new tables without affecting existing ones
-- All existing functionality continues to work
Phase 2: Gradual Rollout
- Deploy backend with new tables (inactive)
- Deploy UI with cluster management (opt-in)
- Monitor performance and gather feedback
- 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
-
Usage Metrics
- Number of clusters created
- Average libraries per cluster
- Most popular cluster types
-
Performance Metrics
- Cluster query response time
- Media aggregation performance
- Database query execution time
-
User Engagement
- Cluster view page visits
- Time spent on cluster views
- Feature adoption rate
Error Handling
Common Error Scenarios
- Duplicate Cluster Name: Return 409 Conflict
- Library Not Found: Return 404 Not Found
- Invalid Mapping: Return 400 Bad Request
- Database Error: Return 500 Internal Server Error
- 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
- Minor Issues: Hot-fix and redeploy
- Major Issues:
- Disable cluster UI features
- Keep database tables (no data loss)
- Investigate and fix
- Re-enable when stable
Database Rollback (If Needed)
-- 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