# Redux Persistence Middleware - Quick Start Guide ## What is it? The Redux Persistence Middleware automatically saves your Redux state changes to IndexedDB and optionally syncs them with a Flask API backend. **No manual database calls needed!** ## Key Features ✅ **Automatic Persistence** - State changes are automatically saved ✅ **Debounced Writes** - Efficient 300ms debouncing prevents excessive writes ✅ **Flask Sync** - Optional bidirectional sync with remote API ✅ **Metrics Tracking** - Real-time performance monitoring ✅ **Auto-Sync** - Periodic automatic synchronization ✅ **Zero Configuration** - Works out of the box ## How It Works ``` Redux Action → Middleware Intercepts → Queue (300ms debounce) → IndexedDB + Flask API ``` ## Basic Usage ### 1. Just Use Redux Normally ```typescript import { useAppDispatch } from '@/store' import { saveFile } from '@/store/slices/filesSlice' function MyComponent() { const dispatch = useAppDispatch() const handleSave = () => { // That's it! Middleware handles persistence automatically dispatch(saveFile({ id: 'file-1', name: 'example.js', content: 'console.log("Hello")', language: 'javascript', path: '/src/example.js', updatedAt: Date.now() })) } return } ``` ### 2. Monitor Persistence Status ```typescript import { usePersistence } from '@/hooks/use-persistence' function StatusBar() { const { status, metrics } = usePersistence() return (
Status: {status.syncStatus} Operations: {metrics.totalOperations} Success Rate: {(metrics.successfulOperations / metrics.totalOperations * 100)}%
) } ``` ### 3. Configure Auto-Sync ```typescript import { usePersistence } from '@/hooks/use-persistence' function Settings() { const { configureAutoSync } = usePersistence() const enableAutoSync = () => { configureAutoSync({ enabled: true, intervalMs: 30000, // Sync every 30 seconds syncOnChange: true, // Sync when changes detected maxQueueSize: 50 // Force sync after 50 changes }) } return } ``` ## Supported Redux Actions The middleware automatically handles these action patterns: ### Files - `files/addItem`, `files/updateItem`, `files/removeItem` - `files/saveFile`, `files/deleteFile` - `files/setFiles` ### Models - `models/addItem`, `models/updateItem`, `models/removeItem` - `models/saveModel`, `models/deleteModel` - `models/setModels` ### Components - `components/addItem`, `components/updateItem`, `components/removeItem` - `components/saveComponent`, `components/deleteComponent` - `components/setComponents` ### Component Trees - `componentTrees/addItem`, `componentTrees/updateItem`, `componentTrees/removeItem` - `componentTrees/saveComponentTree`, `componentTrees/deleteComponentTree` - `componentTrees/setComponentTrees` ### Workflows, Lambdas, Theme - Same pattern as above for `workflows/*`, `lambdas/*`, `theme/*` ## Advanced Usage ### Flush Pending Operations ```typescript import { usePersistence } from '@/hooks/use-persistence' function SaveButton() { const { flush } = usePersistence() const handleCriticalSave = async () => { // Force immediate persistence of all pending operations await flush() console.log('All data persisted!') } return } ``` ### Configure Per-Slice Settings ```typescript import { configurePersistence } from '@/store/middleware' // Disable Flask sync for local-only data configurePersistence('settings', { syncToFlask: false }) // Increase debounce for frequently updated data configurePersistence('theme', { debounceMs: 1000 }) // Reduce debounce for critical data configurePersistence('files', { debounceMs: 100 }) ``` ### Disable/Enable Persistence ```typescript import { disablePersistence, enablePersistence } from '@/store/middleware' // Temporarily disable persistence (e.g., during bulk operations) disablePersistence('files') // ... perform bulk operations ... // Re-enable persistence enablePersistence('files') ``` ### Manual Sync ```typescript import { useAppDispatch } from '@/store' import { syncToFlaskBulk, syncFromFlaskBulk } from '@/store/slices/syncSlice' function SyncButtons() { const dispatch = useAppDispatch() return ( <> ) } ``` ## Monitoring & Debugging ### View Dashboard Navigate to the **Persistence** page in the app to see: - Real-time connection status - Sync metrics and performance - Auto-sync configuration - Manual sync controls - Error reporting ### Subscribe to Metrics ```typescript import { subscribeSyncMetrics } from '@/store/middleware' useEffect(() => { const unsubscribe = subscribeSyncMetrics((metrics) => { console.log('Metrics updated:', metrics) if (metrics.failedOperations > 10) { alert('High failure rate detected!') } }) return unsubscribe }, []) ``` ### Check Connection Status ```typescript import { useAppSelector } from '@/store' function ConnectionIndicator() { const connected = useAppSelector((state) => state.sync.flaskConnected) const status = useAppSelector((state) => state.sync.status) return (
{connected ? '🟢 Connected' : '🔴 Offline'} | Status: {status}
) } ``` ## Performance Tips ### 1. Use Appropriate Debounce Times - **Fast UI updates**: 100-200ms (search, filters) - **Standard forms**: 300ms (default, recommended) - **Non-critical data**: 500-1000ms (preferences, settings) ### 2. Batch Operations ```typescript // ❌ Bad - Multiple individual operations files.forEach(file => dispatch(saveFile(file))) // ✅ Good - Single batch operation dispatch(setFiles(files)) ``` ### 3. Disable During Bulk Operations ```typescript import { disablePersistence, enablePersistence, flushPersistence } from '@/store/middleware' async function importData(largeDataset) { disablePersistence('files') // Perform bulk operations without persistence overhead largeDataset.forEach(item => dispatch(addItem(item))) enablePersistence('files') // Flush once after all operations await flushPersistence() } ``` ## Common Patterns ### Create with Auto-Save ```typescript const handleCreate = () => { dispatch(saveFile({ id: generateId(), name: 'new-file.js', content: '', language: 'javascript', path: '/src/new-file.js', updatedAt: Date.now() })) // Automatically persisted and synced! } ``` ### Update with Auto-Save ```typescript const handleUpdate = (fileId, newContent) => { dispatch(updateFile({ id: fileId, content: newContent, updatedAt: Date.now() })) // Automatically persisted and synced! } ``` ### Delete with Auto-Save ```typescript const handleDelete = (fileId) => { dispatch(deleteFile(fileId)) // Automatically removed from storage! } ``` ## Troubleshooting ### Data not persisting? 1. Check that the slice is configured in `persistenceMiddleware.ts` 2. Verify the action matches supported patterns 3. Check console for errors ### High failure rate? 1. Check Flask API is running 2. Verify network connection 3. Check IndexedDB quota not exceeded ### Slow performance? 1. Increase debounce time 2. Reduce sync frequency 3. Disable Flask sync for non-critical data ## Example: Complete CRUD Component ```typescript import { useAppDispatch, useAppSelector } from '@/store' import { saveFile, deleteFile } from '@/store/slices/filesSlice' import { usePersistence } from '@/hooks/use-persistence' function FileManager() { const dispatch = useAppDispatch() const files = useAppSelector((state) => state.files.files) const { status } = usePersistence() const create = (name, content) => { dispatch(saveFile({ id: `file-${Date.now()}`, name, content, language: 'javascript', path: `/src/${name}`, updatedAt: Date.now() })) } const update = (id, content) => { const file = files.find(f => f.id === id) if (file) { dispatch(saveFile({ ...file, content, updatedAt: Date.now() })) } } const remove = (id) => { dispatch(deleteFile(id)) } return (
Status: {status.syncStatus}
{files.map(file => (
{file.name}
))}
) } ``` ## Learn More - Full documentation: `PERSISTENCE_MIDDLEWARE_DOCS.md` - View live dashboard: Navigate to **Persistence** page - Try the demo: Navigate to **Persistence Demo** page