# Perfect Dual Action API: CoreAction vs LibraryAction **Date:** 2025-01-27 **Status:** **Perfect Architecture Achieved** ## 🎯 **The Perfect Solution** We've achieved the **ideal action architecture** that eliminates boilerplate while preserving extensibility and central infrastructure. ## ✅ **Two Clear Action Types:** ### **1. CoreAction - Global Operations** ```rust /// Core-level actions that operate without library context pub trait CoreAction: Send + Sync + 'static { type Output: Send + Sync + 'static; async fn execute(self, context: Arc) -> Result; fn action_kind(&self) -> &'static str; // No library validation boilerplate! } // Examples: Managing libraries themselves, volumes, devices impl CoreAction for LibraryCreateAction { type Output = LibraryCreateOutput; // Creates libraries } impl CoreAction for VolumeSpeedTestAction { type Output = VolumeSpeedTestOutput; // Tests volumes globally } ``` ### **2. LibraryAction - Library-Scoped Operations** ```rust /// Library-scoped actions that operate within a specific library pub trait LibraryAction: Send + Sync + 'static { type Output: Send + Sync + 'static; async fn execute(self, library: Arc, context: Arc) -> Result; fn action_kind(&self) -> &'static str; fn library_id(&self) -> Uuid; // Library pre-validated by ActionManager - zero boilerplate! } // Examples: Files, locations, indexing within libraries impl LibraryAction for VolumeTrackAction { type Output = VolumeTrackOutput; // Tracks volume in library } impl LibraryAction for FileCopyAction { type Output = JobHandle; // Copies files within library } ``` ## 🚀 **Perfect Usage Examples:** ### **Core Actions:** ```rust // ✅ Global operations - no library context needed let library: LibraryCreateOutput = core.execute_core_action( LibraryCreateAction::new("Photos".to_string(), None) ).await?; let speed_result: VolumeSpeedTestOutput = core.execute_core_action( VolumeSpeedTestAction::new(fingerprint) ).await?; ``` ### **Library Actions:** ```rust // ✅ Library operations - library pre-validated automatically let volume: VolumeTrackOutput = core.execute_library_action( VolumeTrackAction::with_name(fingerprint, library_id, "My Drive".to_string()) ).await?; let copy_job: JobHandle = core.execute_library_action( FileCopyAction::builder() .library_id(library_id) .sources(sources) .destination(dest) .build()? ).await?; ``` ## 🎉 **Key Benefits Achieved:** ### **1. Zero Boilerplate:** ```rust // ❌ OLD: Every action validates library existence async fn validate(&self, context: Arc) -> Result<(), ActionError> { let _library = context.library_manager.get_library(self.library_id).await .ok_or_else(|| ActionError::LibraryNotFound(self.library_id))?; // Repeated in EVERY action! } // ✅ NEW: ActionManager validates once, provides Library async fn execute(self, library: Arc, context: Arc) -> Result { // Library already validated - use it directly! } ``` ### **2. Clear Semantics:** - **`CoreAction`** - "This operates at the global level" - **`LibraryAction`** - "This operates within a library" - **No confusion** about when to use which pattern ### **3. Extension Support:** ```rust // ✅ Runtime registration for plugins pub trait ActionRegistry { fn register_core_action(&mut self, name: &str); fn register_library_action(&mut self, name: &str); } ``` ### **4. Enhanced ActionManager:** ```rust impl ActionManager { // Handles global operations pub async fn dispatch_core(&self, action: A) -> Result // Handles library operations with pre-validation pub async fn dispatch_library(&self, action: A) -> Result } ``` ## 💡 **Perfect Architecture:** - ✅ **No centralized enums** - True modularity achieved - ✅ **Central dispatch** - Validation, audit logging, monitoring - ✅ **Zero boilerplate** - Library validation done once at ActionManager level - ✅ **Type safety** - Library vs Core distinction enforced by type system - ✅ **Extension support** - Runtime registration for plugins - ✅ **Natural return types** - Domain objects or job handles as appropriate This is the **perfect balance** of modularity, infrastructure, and usability! 🎯✨