mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-04-24 00:17:47 -04:00
- Added a new `apps/cli` module to encapsulate the CLI application logic, improving organization and modularity. - Updated `Cargo.toml` to include dependencies for the CLI, such as `clap` for command-line argument parsing. - Implemented a `Context` struct to manage application state and core client interactions. - Created command handling for file operations and library management, enhancing user experience and functionality. - Introduced utility functions for output formatting, supporting both human-readable and JSON outputs. These changes significantly enhance the structure and maintainability of the CLI application while providing a more robust user interface.
3.8 KiB
3.8 KiB
CQRS Migration: Corrected Approach ✅
Date: 2025-01-27 Status: Fixed - No More Duplicates
🚨 Issue Identified & Fixed
Problem: I initially created duplicate implementations - both old ActionHandler AND new ActionType for the same actions. This was completely wrong and defeated the purpose of the migration.
Solution: Replace, don't duplicate. Each action should have only ONE implementation.
✅ Corrected Approach
1. Single Implementation Per Action
// ❌ WRONG (what I did initially):
impl ActionHandler for LibraryCreateHandler { ... } // Old system
impl ActionType for LibraryCreateAction { ... } // New system - DUPLICATE!
// ✅ CORRECT (what we have now):
// Note: ActionHandler implementation removed - using ActionType instead
impl ActionType for LibraryCreateAction { ... } // Only new system
2. Backward Compatible ActionManager
The key insight: ActionManager::dispatch(Action) extracts the inner action and uses the new system:
impl ActionManager {
pub async fn dispatch(&self, action: Action) -> ActionResult<ActionOutput> {
match action {
// Migrated actions use new system
Action::LibraryCreate(inner_action) => {
let result = self.dispatch_action(inner_action).await?;
Ok(ActionOutput::from_trait(result)) // Convert for compatibility
}
Action::VolumeTrack { action: inner_action } => {
let result = self.dispatch_action(inner_action).await?;
Ok(ActionOutput::VolumeTracked {
fingerprint: result.fingerprint,
library_id: result.library_id,
volume_name: result.volume_name,
})
}
// Non-migrated actions fall back to old system
_ => {
let handler = REGISTRY.get(action.kind())?;
handler.execute(self.context.clone(), action).await
}
}
}
}
3. Progressive Migration
- ✅ Migrated Actions:
LibraryCreateAction,LibraryDeleteAction,LibraryRenameAction,VolumeTrackAction,VolumeUntrackAction,VolumeSpeedTestAction - ⏳ Not Yet Migrated: Location actions, File actions, etc. (fall back to old system)
- 🎯 End Goal: All actions migrated, then remove
ActionOutputenum entirely
🔥 Key Benefits Achieved
- No Duplication: Each action has exactly one implementation
- Backward Compatibility: Old
ActionManager::dispatch(Action)still works - Progressive Migration: Can migrate actions one by one
- Native Types: New actions return native output types directly
- Unified API:
core.execute_action()provides clean interface
📊 Current Status
What Works Now:
// NEW: Direct native types
let action = LibraryCreateAction { name: "Photos".to_string(), path: None };
let result: LibraryCreateOutput = core.execute_action(action).await?;
println!("Library ID: {}", result.library_id);
// OLD: Still works through compatibility layer
let old_action = Action::LibraryCreate(action);
let old_result: ActionOutput = action_manager.dispatch(old_action).await?;
Migration Progress:
- ✅ 6 actions migrated to
ActionType - ✅ ActionManager updated to use new system internally
- ✅ Core API provides unified interface
- ⏳ ~15 actions remaining to migrate
🎯 Next Steps
- Continue Migration: Migrate remaining actions (locations, files, etc.)
- Remove Old System: Once all actions migrated, remove
ActionHandlertrait andActionOutputenum - Clean Up: Remove compatibility conversion code
This corrected approach achieves true modularity without duplication! 🚀