Skip to content

Conversation

@timusus
Copy link
Owner

@timusus timusus commented Nov 16, 2025

📋 Overview
This PR introduces a comprehensive architecture design document for implementing bidirectional playlist synchronization between Shuttle2 and media servers (Jellyfin, Emby, Plex).

Addresses: #102 - Sync S2 playlist actions with Jellyfin server

🎯 Problem Statement
Currently, Shuttle2 supports one-way sync (pull playlists from media servers), but modifications made locally (adding/removing songs, renaming, deleting) don't sync back to the server. This creates:

Divergence between Shuttle2 and server state
Manual maintenance burden across multiple clients
Confusion when playlists differ between devices
✨ What's Included
Complete Architecture Document (PLAYLIST_SYNC_ARCHITECTURE.md)
A production-ready design covering:

Core Components

PlaylistSyncProvider interface for server-agnostic sync operations
PlaylistSyncCoordinator for managing sync lifecycle
SyncQueueRepository with persistent queue and retry logic
Repository interceptor pattern for non-invasive change tracking
Conflict Resolution Strategy

Safe Auto-Merge (default): Preserves all content when safe
User prompts only for destructive conflicts (renames, deletions)
Configurable preferences: Auto-merge, Always Local, Always Remote, Ask Me
Sync Configuration

Daily background sync (default, battery-friendly)
User configurable: 15 min, hourly, 6 hours, daily, or manual only
Global enable/disable per server type (Jellyfin/Emby/Plex)
Smart playlists excluded (query-based, read-only)
Media Server API Analysis

Jellyfin: Full CRUD support (with known bugs documented + workarounds)
Emby: Most stable API, excellent documentation
Plex: Comprehensive but different paradigm (URI-based)
Implementation Roadmap

8 phases over 12 weeks
Feature flags for gradual rollout
Backward compatible (no breaking changes)
Clear success criteria for each phase
🏗️ Architecture Highlights
Clean Architecture Principles
Presentation → Domain (Sync Coordinator) → Data (Repository + Providers) → Network
✅ SOLID principles throughout
✅ Repository pattern with reactive streams (Flow)
✅ Plugin architecture for media providers
✅ Offline-first with persistent sync queue
✅ Resilient error handling and conflict resolution
✅ Testable with clear component boundaries
Key Technical Decisions
| Decision | Choice | Rationale | |----------|--------|-----------| | Change Tracking | Repository Interceptor | Non-invasive, decorator pattern | | Sync Queue | Room database | Survives app restarts, queryable | | Conflict Detection | Content hashing | Efficient state comparison | | Background Sync | WorkManager | Battery-aware, constraint-based | | Scope | Global per server | Simple UX, less overhead |

📊 Design Decisions (Resolved)
All open questions have been answered:

✅ Conflict Resolution: Safe Auto-Merge (preserve content, minimize prompts)
✅ Sync Frequency: Daily default (user configurable)
✅ Sync Scope: Global per server type (Jellyfin/Emby/Plex toggles)
✅ Smart Playlists: No sync (query-based, read-only)
🚀 Next Steps
This PR contains architecture design only (no implementation code).

After merge:

Create implementation tickets for Phase 1 (Foundation)
Set up feature flags in build configuration
Begin database schema implementation
Follow the 8-phase rollout plan
📝 Document Details
Version: 1.1
Status: Ready for Implementation
Estimated Effort: 12 weeks (1 developer)
Priority: High (community requested)
Lines: ~1,230 lines of comprehensive documentation
🔍 Review Focus Areas
When reviewing, please pay attention to:

Architecture soundness - Does the component design follow best practices?
Scalability - Can this handle thousands of playlists across multiple servers?
User experience - Are the defaults sensible? Is conflict resolution intuitive?
Implementation feasibility - Is the phased approach realistic?
API compatibility - Are the server API capabilities accurately represented?

This design document provides a complete architectural blueprint for
implementing bidirectional playlist synchronization with Jellyfin, Emby,
and Plex media servers.

Key architectural components:
- PlaylistSyncProvider interface for server-agnostic sync operations
- PlaylistSyncCoordinator for managing sync lifecycle
- Persistent sync queue with retry logic and priority handling
- Conflict detection and resolution strategies
- Repository interceptor pattern for change tracking

The design follows Clean Architecture principles and maintains backward
compatibility while providing a scalable, resilient foundation for
bidirectional sync.

Addresses: #102
Resolved all open questions from architecture review:

1. Default Conflict Resolution: Safe Auto-Merge
   - Union merge for additive operations (preserve all content)
   - User prompts only for destructive conflicts
   - Aligns with user expectation of not losing changes

2. Sync Frequency: Daily (user configurable)
   - Default: Daily background sync (battery-friendly)
   - Options: 15 min, hourly, 6 hours, daily, manual only
   - Manual "Sync Now" button for immediate sync

3. Sync Scope: Global per media server
   - Settings per server type (Jellyfin/Emby/Plex)
   - All playlists from enabled servers sync automatically
   - Simpler UX with less configuration overhead

4. Smart Playlists: No sync
   - Smart playlists are query-based and read-only
   - Focus sync effort on regular user playlists
   - Keep them local-only or read-only from server

Additional enhancements:
- Added detailed WorkManager configuration with constraints
- Added PlaylistSyncPreferences structure for user settings
- Expanded conflict resolution examples with scenarios
- Added shouldSync() helper to exclude smart playlists
- Updated document version to 1.1 with changelog

Status: Ready for implementation

Addresses: #102
This commit implements the foundational infrastructure for bidirectional
playlist synchronization as outlined in PLAYLIST_SYNC_ARCHITECTURE.md.

New Components:
1. Room Entities
   - SyncOperation: Persistent queue for sync operations
   - PlaylistSyncState: Tracks sync state and conflicts per playlist
   - Added enums: OperationType, SyncStatus, PlaylistSyncStatus

2. Database Layer
   - SyncOperationDao: CRUD operations for sync queue
   - PlaylistSyncStateDao: Sync state management
   - MIGRATION_40_41: Creates new tables with proper indexes and foreign keys
   - Updated Converters with Instant and enum type converters

3. Repository Layer
   - PlaylistSyncProvider: Interface for server-specific sync operations
   - SyncQueueRepository: Interface for sync queue management
   - LocalSyncQueueRepository: Room-based implementation

4. Dependency Injection
   - Added SyncQueueRepository to RepositoryModule
   - Database updated to version 41 with new entities

Features:
- Persistent sync queue survives app restarts
- Priority-based operation ordering
- Retry logic with configurable max retries
- Conflict detection via content hashing
- Foreign key constraints for data integrity
- Comprehensive query support for sync status

This establishes the foundation for:
- Change tracking (Phase 3)
- Background sync worker (Phase 4)
- Conflict resolution (Phase 5)
- Server-specific implementations (Phase 2, 7)

Addresses: #102
Related: PLAYLIST_SYNC_ARCHITECTURE.md Phase 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants