- Refactor migrations and provider to use multiple PostgreSQL schemas, each matching a legacy SQLite database (activitylog, authentication, displaypreferences, library, users). - All tables, foreign keys, and indexes are now schema-qualified; Down migration drops tables by schema. - Provider ensures schemas exist before migrations; entities are mapped to correct schemas in OnModelCreating. - Add support for max-pool-size, min-pool-size, and multiplexing connection options; update logging accordingly. - VACUUM ANALYZE now runs per schema during scheduled optimization. - TruncateAllTablesAsync now truncates tables with schema qualification. - README updated with schema structure, new options, and multiplexing warnings. - CacheDecorator now calls async repository methods using .GetAwaiter().GetResult(), with documentation. - Lays groundwork for full async/await and multiplexing support in the database layer.
11 KiB
Repository Async Conversion Priority List
Based on analysis of 1,189 synchronous database operations found in the codebase.
📊 Priority Matrix
Priority determined by:
- Complexity: Lower is better (fewer operations, simpler logic)
- Impact: Higher is better (frequently used, performance-critical)
- Dependencies: Fewer dependencies = higher priority
✅ Phase 1: Simple Repositories (POC Complete + Easy Wins)
1. KeyframeRepository ✅ COMPLETED - POC
- Sync Operations: 3
- Complexity: ⭐ Very Low
- Files Changed: 3
IKeyframeRepository.csKeyframeRepository.csKeyframeManager.cs+ interfaceCacheDecorator.cs(sync wrapper needed)
- Status: ✅ CONVERTED
- Build: ✅ PASSING
- Notes: One method (
TryExtractKeyframes) remains sync by interface design
2. MediaAttachmentRepository ✅ COMPLETED - POC
- Sync Operations: 5
- Complexity: ⭐⭐ Low
- Estimated Effort: 2-3 days
- Files to Change: ~5
- API Impact: Minimal (internal use)
- Dependencies: Low
- Recommendation: Do Next
3. MediaStreamRepository ✅ ✅ COMPLETED - POC
- Sync Operations: 5
- Complexity: ⭐⭐ Low
- Estimated Effort: 2-3 days
- Files to Change: ~6
- API Impact: Low
- Dependencies: Low
- Recommendation: Do in Phase 1
4. ChapterRepository ✅ COMPLETED - POC
- Sync Operations: 6
- Complexity: ⭐⭐ Low-Medium
- Files Changed: 6
IChapterRepository.csChapterRepository.csIChapterManager.csChapterManager.csChapterImagesTask.csDtoService.cs
- Status: ✅ CONVERTED
- Build: ✅ PASSING
- API Impact: Medium (chapter API endpoints)
- Dependencies: Medium
⚡ Phase 2: Medium Complexity
5. PeopleRepository ✅ COMPLETED - POC
- Sync Operations: 15
- Complexity: ⭐⭐⭐ Medium
- Estimated Effort: 1 week
- Files to Change: ~15
- API Impact: Medium-High (people/actors endpoints)
- Dependencies: Medium (used by BaseItemRepository)
- Recommendation: Do in Phase 2
🔥 Phase 3: Complex (High Impact, High Risk)
6. BaseItemRepository ⚠️
- Sync Operations: 110
- Complexity: ⭐⭐⭐⭐⭐ Very High
- Estimated Effort: 4-6 weeks
- Files to Change: 50+
- API Impact: 🔴 CRITICAL (All item endpoints)
- Dependencies: 🔴 VERY HIGH (Core of Jellyfin)
- Recommendation: DO LAST - Needs careful planning
- Special Notes:
- Central to all library operations
- Used by nearly every API endpoint
- Requires extensive testing
- Consider breaking into smaller pieces
📅 Recommended Timeline
Sprint 1-2: Simple Repositories ✅ COMPLETE (3-4 weeks)
- ✅ KeyframeRepository (DONE)
- ✅ MediaAttachmentRepository (DONE)
- ✅ MediaStreamRepository (DONE)
- ✅ ChapterRepository (DONE)
Goal: ✅ ACHIEVED - Gained experience, established patterns, validated approach
Sprint 3-4: Medium Complexity ⏳ NEXT (4 weeks)
- Week 1-3: PeopleRepository conversion
- Week 4: Integration testing, bug fixes
Goal: Test patterns with more complex scenarios
Sprint 5-10: BaseItemRepository (6 weeks)
- Week 1-2: Planning, breaking down into modules
- Week 3-5: Conversion in phases
- Week 6: Testing, performance validation
Goal: Complete core conversion with minimal disruption
🎯 Conversion Order Rationale
Why This Order?
-
KeyframeRepository First (✅ Done)
- Smallest scope for POC
- Low risk - not heavily used
- Validates async patterns
- Builds team confidence
-
Media*Repository Next
- Still simple but more commonly used
- Tests pattern on slightly larger scope
- Related functionality (easier to reason about)
-
ChapterRepository After
- Medium complexity
- Has API endpoints (tests full stack)
- Good transition to Phase 2
-
PeopleRepository Mid-Game
- More complex queries
- Used by BaseItemRepository
- Must be done before BaseItemRepository
-
BaseItemRepository Last
- Most complex
- Highest risk
- By now, team has experience
- Patterns are well-established
📋 Detailed Conversion Steps
For each repository, follow this process:
1. Preparation (1 day)
- Read current implementation
- Identify all public methods
- Map all consumers (where it's used)
- List required interface changes
- Create feature branch
2. Interface Updates (0.5 days)
- Update interface with async methods
- Add CancellationToken parameters
- Update XML documentation
3. Implementation (1-3 days depending on complexity)
- Convert repository methods to async
- Update all database operations
- Add proper async disposal (
await using) - Add ConfigureAwait(false) where appropriate
4. Consumer Updates (1-2 days)
- Update service layer
- Update API controllers
- Update background services
5. Testing (1-2 days)
- Update unit tests
- Update integration tests
- Add cancellation tests
- Performance testing
6. Review & Merge (0.5 days)
- Code review
- Fix any issues
- Merge to main
🔍 Detailed Repository Analysis
MediaAttachmentRepository
Sync Operations Found: 5
ToList(): 3 instancesToArray(): 1 instanceSaveChanges(): 1 instance
Files That Use It:
MediaSourceManager.csEncodingHelper.cs- API controllers for media info
Breaking Changes:
GetAttachmentStreams(Guid itemId)→GetAttachmentStreamsAsync(...)SaveAttachments(...)→SaveAttachmentsAsync(...)
Estimated Changes: 5-7 files
MediaStreamRepository
Sync Operations Found: 5
ToList(): 3 instancesSaveChanges(): 2 instances
Files That Use It:
MediaSourceManager.csMediaInfoManager.cs- Playback state management
Breaking Changes:
GetMediaStreams(Guid itemId)→GetMediaStreamsAsync(...)SaveMediaStreams(...)→SaveMediaStreamsAsync(...)
Estimated Changes: 6-8 files
ChapterRepository
Sync Operations Found: 6
ToList(): 4 instancesExecuteDelete(): 1 instanceSaveChanges(): 1 instance
Files That Use It:
ChaptersController.cs(API)ChapterManager.csMediaSourceManager.cs
Breaking Changes:
GetChapters(Guid itemId)→GetChaptersAsync(...)SaveChapters(...)→SaveChaptersAsync(...)
API Endpoints Affected:
GET /Items/{id}/ChaptersPOST /Items/{id}/Chapters
Estimated Changes: 8-10 files
PeopleRepository
Sync Operations Found: 15
ToList(): 8 instancesToArray(): 4 instancesFirstOrDefault(): 2 instancesSaveChanges(): 1 instance
Files That Use It:
PersonController.cs(API)BaseItemRepository.cs(⚠️ circular dependency)- Various service layers
Breaking Changes:
GetPeople(InternalPeopleQuery query)→GetPeopleAsync(...)GetPerson(string name)→GetPersonAsync(...)- All people-related operations
API Endpoints Affected:
GET /PersonsGET /Persons/{name}- People aggregations
Estimated Changes: 15-20 files
⚠️ Special Consideration: Used by BaseItemRepository, so must be done before Phase 3
BaseItemRepository ⚠️
Sync Operations Found: 110
ToList(): 45+ instancesToArray(): 35+ instancesFirstOrDefault(): 15+ instancesExecuteDelete(): 8 instancesSaveChanges(): 5 instancesBeginTransaction(): 2 instances
Files That Use It:
- Nearly every API controller
LibraryManager.cs(core)- All media scanning services
- All playback services
- Search functionality
- Filtering/sorting
Breaking Changes:
- 🔴 40+ public methods need conversion
- All item CRUD operations
- All query operations
- All aggregations
API Endpoints Affected:
- 🔴 100+ endpoints directly or indirectly
- All item retrieval
- All filtering/search
- All library browsing
Estimated Changes: 50-100 files
⚠️ Critical Notes:
- Core of entire application
- Must be done in phases
- Requires feature flags for gradual rollout
- Extensive testing required
- Consider performance impact
- May need database connection pool adjustments
Suggested Sub-Phases for BaseItemRepository:
- Phase 3a: Query-only operations (GetItems, filters)
- Phase 3b: Item retrieval (RetrieveItem, GetItem)
- Phase 3c: Write operations (SaveItems, UpdateItems)
- Phase 3d: Delete operations (DeleteItem)
- Phase 3e: Aggregations and statistics
🧪 Testing Strategy Per Phase
Phase 1: Simple Repositories
- Unit Tests: All repository methods
- Integration Tests: Repository → Service layer
- Performance Tests: Basic benchmarks
Phase 2: Medium Complexity
- Unit Tests: All repository methods + edge cases
- Integration Tests: Full stack (Repository → Service → API)
- Performance Tests: Detailed benchmarks
- Load Tests: Concurrent operations
Phase 3: BaseItemRepository
- Unit Tests: Comprehensive coverage
- Integration Tests: End-to-end scenarios
- Performance Tests: Extensive benchmarking
- Load Tests: Production-like loads
- Stress Tests: Breaking point analysis
- Regression Tests: Ensure no behavioral changes
- Canary Deployment: Test with real users gradually
📊 Risk Assessment
| Repository | Complexity | API Impact | Test Coverage | Overall Risk |
|---|---|---|---|---|
| KeyframeRepository | ⭐ | Low | Good | 🟢 LOW |
| MediaAttachmentRepository | ⭐⭐ | Low | Good | 🟢 LOW |
| MediaStreamRepository | ⭐⭐ | Low | Good | 🟢 LOW |
| ChapterRepository | ⭐⭐⭐ | Medium | Good | 🟡 MEDIUM |
| PeopleRepository | ⭐⭐⭐ | Medium | Medium | 🟡 MEDIUM |
| BaseItemRepository | ⭐⭐⭐⭐⭐ | 🔴 Critical | Needs More | 🔴 HIGH |
✅ Success Metrics
Per Repository:
- All sync operations converted
- All tests passing
- No performance regression (<5% slower)
- Build successful
- Code review approved
Overall Project:
- 100% async database operations
- PostgreSQL multiplexing enabled
- 20-40% reduction in connection pool usage
- No API breaking changes (async signatures OK)
- Documentation updated
🚀 Next Steps
- ✅ Phase 1 COMPLETE: All simple repositories converted (4/4)
- ✅ Pattern Established: Repeatable async conversion process
- ✅ Documentation Complete: Comprehensive guides and presentations
- Present Results: Show Phase 1 completion to stakeholders
- Begin Phase 2: Start PeopleRepository conversion (~1 week)
- Phase 2 Review: Evaluate progress, adjust approach
Document Version: 2.0
Last Updated: 2025-01-15
Status: Phase 1 Complete ✅ | Phase 2 Ready 🚀
Next Action: Present to Stakeholders, then Begin PeopleRepository