feat: update plan with async/sync boundaries and performance optimizations

Co-authored-by: aider (openai/andrew/openrouter/mistralai/mistral-medium-3.1) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-08-24 23:20:37 -03:00
parent accb5b79f8
commit 0f79d99c8b

120
PLAN.md
View File

@@ -1,31 +1,37 @@
# Refactoring Plan to Reduce Code Duplication # Refactoring Plan to Reduce Code Duplication
## 1. Create Core Service Layer ## 1. Create Core Service Layer
**Files:** `src/core/` (new directory) **Files:** `src/core/` (new directory)
- `src/core/item_service.rs` - Main service for item operations - `src/core/item_service.rs` - Main service for item operations (synchronous)
- `src/core/async_item_service.rs` - Async wrapper for API use
- `src/core/compression_service.rs` - Compression handling - `src/core/compression_service.rs` - Compression handling
- `src/core/meta_service.rs` - Metadata processing - `src/core/meta_service.rs` - Metadata processing
- `src/core/mod.rs` - Module exports - `src/core/mod.rs` - Module exports
- `src/core/error.rs` - Unified error handling
**Reason:** Extract common business logic from modes and APIs into reusable services **Reason:** Extract common business logic from modes and APIs into reusable services
**Implementation:** **Implementation:**
- Move logic from modes (get, save, list, info) and API handlers into service functions - Move logic from modes (get, save, list, info) and API handlers into service functions
- Services should return structured data, not format output - Services should return structured data, not format output
- Handle compression, metadata, and database operations - Handle compression, metadata, and database operations
- Keep core services **synchronous** for CLI performance
- Provide async wrappers using `tokio::task::spawn_blocking` for API use
- Use streaming for pipeline efficiency (process data in chunks)
## 2. Create Common Data Structures ## 2. Create Common Data Structures
**Files:** `src/core/types.rs` **Files:** `src/core/types.rs`
**Reason:** Standardize data structures used across modes and APIs **Reason:** Standardize data structures used across modes and APIs
**Implementation:** **Implementation:**
- Define structs for Item, ItemContent, ItemWithMeta, etc. - Define structs for `Item`, `ItemWithContent`, `ItemWithMeta`, `Response<T>`
- Include conversion functions from database types - Include conversion functions from database types (`From<db::Item>`)
- Add serialization/deserialization support - Add serialization/deserialization support for JSON/YAML
- Ensure all fields are properly documented
- Use zero-copy patterns where possible (slicing instead of copying)
## 3. Refactor CLI Modes to Use Services ## 3. Refactor CLI Modes to Use Services
**Files:** **Files:**
- `src/modes/get.rs` - `src/modes/get.rs`
- `src/modes/save.rs` - `src/modes/save.rs`
- `src/modes/list.rs` - `src/modes/list.rs`
- `src/modes/info.rs` - `src/modes/info.rs`
- `src/modes/delete.rs` - `src/modes/delete.rs`
@@ -37,61 +43,119 @@
- Replace current implementations with calls to core services - Replace current implementations with calls to core services
- Keep only CLI-specific formatting and output logic - Keep only CLI-specific formatting and output logic
- Handle command-line argument parsing and validation - Handle command-line argument parsing and validation
- Use synchronous services directly
- Implement streaming for stdin/stdout to maintain pipeline performance
## 4. Refactor REST API to Use Services ## 4. Refactor REST API to Use Async Services
**Files:** **Files:**
- `src/modes/server/api/item.rs` - `src/modes/server/api/item.rs`
- `src/modes/server/api/status.rs` - `src/modes/server/api/status.rs`
**Reason:** Remove business logic from HTTP handlers **Reason:** Remove business logic from HTTP handlers
**Implementation:** **Implementation:**
- Convert handlers to call core services - Convert handlers to call async core services
- Keep only HTTP-specific code (status codes, headers, etc.) - Keep only HTTP-specific code (status codes, headers, etc.)
- Use common error handling - Use common error handling with conversions to HTTP responses
- Wrap synchronous service calls in `tokio::task::spawn_blocking`
## 5. Refactor MCP Tools to Use Services ## 5. Refactor MCP Tools to Use Services
**Files:** **Files:** `src/modes/server/mcp/tools.rs`
- `src/modes/server/mcp/tools.rs`
**Reason:** Remove duplication with REST API and CLI modes **Reason:** Remove duplication with REST API and CLI modes
**Implementation:** **Implementation:**
- Replace current implementation with calls to core services - Replace current implementation with calls to core services
- Keep only MCP protocol-specific logic - Keep only MCP protocol-specific logic
- Use synchronous services directly (MCP is typically local/short-lived)
- Standardize response format to match API/CLI
## 6. Create Common Error Handling ## 6. Create Common Error Handling
**Files:** `src/core/error.rs` **Files:** `src/core/error.rs`
**Reason:** Standardize error types across the application **Reason:** Standardize error types across the application
**Implementation:** **Implementation:**
- Define comprehensive error enum with conversions - Define comprehensive error enum with conversions:
- Implement proper error formatting for different outputs (CLI, JSON, HTTP) - From database errors
- From I/O errors
- From compression errors
- From validation errors
- Implement conversions to:
- `anyhow::Error` (for CLI)
- `axum::http::StatusCode` (for API)
- `ToolError` (for MCP)
- Provide user-friendly error messages
- Include error codes for programmatic handling
## 7. Update Database Layer for Batch Operations ## 7. Update Database Layer for Batch Operations
**Files:** `src/db.rs` **Files:** `src/db.rs`
**Reason:** Support efficient batch operations needed by services **Reason:** Support efficient batch operations needed by services
**Implementation:** **Implementation:**
- Add functions to get multiple items with their metadata and tags - Add functions to get multiple items with their metadata and tags
- Add batch insertion/updates for tags and metadata
- Add transaction support for atomic operations
- Optimize queries for common access patterns - Optimize queries for common access patterns
- Ensure all batch operations are properly documented
## 8. Add Integration Tests ## 8. Add Integration Tests
**Files:** `tests/integration/` (new directory) **Files:** `tests/integration/` (new directory)
**Reason:** Ensure refactored code maintains functionality **Reason:** Ensure refactored code maintains functionality and performance
**Implementation:** **Implementation:**
- Test core services independently - Test core services independently
- Test CLI modes and APIs through their public interfaces - Test CLI modes and APIs through their public interfaces
- Verify compression, metadata, and database operations - Verify compression, metadata, and database operations
- Include performance benchmarks for critical paths
- Use in-memory databases and tempfiles for isolation
- Test both sync and async service implementations
## 9. Performance Optimization Guidelines
**Reason:** Ensure the refactored version doesn't slow down pipelines
**Implementation:**
- Use streaming for stdin/stdout processing (chunked I/O)
- Minimize buffering and memory copies
- Offload CPU-bound work (compression, plugins) to thread pools
- Provide fast-path options (e.g., `--fast` flag to skip metadata plugins)
- Benchmark critical operations before/after refactoring
- Document performance characteristics
## Implementation Order: ## Implementation Order:
1. Create core module structure and error types 1. Create core module structure and error types (`core/error.rs`, `core/types.rs`)
2. Implement core services with basic functionality 2. Implement core services with basic functionality (sync first)
3. Refactor one mode (e.g., get) to use services 3. Add async wrappers for API use
4. Refactor corresponding API endpoints 4. Refactor one mode (e.g., `get`) to use services and validate approach
5. Repeat for other modes and APIs 5. Refactor corresponding API endpoints to use async services
6. Add comprehensive tests 6. Repeat for other modes and APIs
7. Clean up removed code from original files 7. Refactor MCP tools to use services
8. Add comprehensive tests and benchmarks
9. Clean up removed code from original files
10. Document performance characteristics and tradeoffs
## Benefits: ## Benefits:
- Reduced code duplication - Reduced code duplication between CLI, API, and MCP
- Easier maintenance - Easier maintenance with clear separation of concerns
- Consistent behavior across interfaces - Consistent behavior across all interfaces
- Better testability - Better testability with isolated service layer
- Clear separation of concerns - Maintained or improved pipeline performance
- Flexible architecture supporting both sync and async use cases
## Key Risks and Mitigations:
1. **Performance Regression:**
- Risk: Refactoring could slow down pipeline operations
- Mitigation: Benchmark before/after, use streaming, minimize overhead
2. **Increased Complexity:**
- Risk: Adding service layer could make code harder to understand
- Mitigation: Clear documentation, gradual refactoring, maintain simple interfaces
3. **Async/Sync Boundaries:**
- Risk: Mixing sync/async could lead to deadlocks or inefficiencies
- Mitigation: Clear boundaries, use `spawn_blocking` for sync work in async context
4. **Breaking Changes:**
- Risk: Refactoring could change behavior in subtle ways
- Mitigation: Comprehensive tests, gradual rollout, maintain backward compatibility
## Design Principles:
1. **Zero-Copy Where Possible:** Use slicing instead of copying data
2. **Streaming Processing:** Handle data in chunks for memory efficiency
3. **Clear Boundaries:** Separate core logic from interface-specific code
4. **Performance First:** Optimize for common pipeline use cases
5. **Consistent Errors:** Unified error handling across all interfaces
6. **Backward Compatibility:** Maintain existing CLI/API behavior