
* Add style prop to UserAvatar component for better customization * Refactor UserAvatar to use getAvatarSeed utility for consistent avatar generation * Fix React hook ordering issues in profile/overview.tsx to prevent crashes during auth state changes * Add proper state initialization and cleanup during authentication transitions * Ensure consistent fallback avatar display for unauthenticated users These changes improve stability during login/logout operations and provide better visual continuity with Robohash avatars when profile images aren't available.
8.3 KiB
Cache Management in POWR App
Last Updated: 2025-04-01
Status: Active
Related To: Mobile Performance, Offline Support, NDK Integration
Purpose
This document outlines the caching architecture in the POWR app, including current implementation, future direction, and strategies for optimizing offline functionality, reducing network usage, and enhancing performance.
Goals
- Improve Offline Experience: Allow users to access critical app features even when offline
- Reduce Network Usage: Minimize data consumption by caching frequently accessed data
- Enhance Performance: Speed up the app by reducing network requests
- Maintain Data Freshness: Implement strategies to keep cached data up-to-date
Current Implementation
The POWR app currently implements a fragmented caching system with multiple specialized services:
1. Profile Image Caching
Status: Implemented
The ProfileImageCache
service downloads and caches profile images locally, providing offline access and reducing network usage.
// Key features of ProfileImageCache
- Local storage of profile images in the app's cache directory
- Automatic fetching and caching of images when needed
- Age-based cache invalidation (24 hours by default)
- Integration with UserAvatar component for seamless usage
Integration Points:
UserAvatar
component uses the cache for all profile imagesEnhancedSocialPost
component usesUserAvatar
for profile images in the feed- NDK initialization sets the NDK instance in the ProfileImageCache service
2. Publication Queue Service
Status: Implemented
The PublicationQueueService
allows events to be created and queued when offline, then published when connectivity is restored.
// Key features of PublicationQueueService
- Persistent storage of unpublished events
- Automatic retry mechanism when connectivity is restored
- Priority-based publishing
- Status tracking for queued events
Integration Points:
- Social posting
- Workout publishing
- Template sharing
3. Social Feed Caching
Status: Implemented
The SocialFeedCache
service caches social feed events locally, allowing users to browse their feed even when offline.
// Key features of SocialFeedCache
- SQLite-based storage of feed events
- Feed-specific caching (following, POWR, global)
- Time-based pagination support
- Automatic cleanup of old cached events
Integration Points:
useSocialFeed
hook uses the cache when offlineSocialFeedService
manages the cache and provides a unified API- Feed components display cached content with offline indicators
4. Event Cache
Status: Implemented
The EventCache
service provides a lower-level caching mechanism for storing and retrieving Nostr events.
// Key features of EventCache
- SQLite-based storage of Nostr events
- Tag-based indexing and retrieval
- Transaction support for batch operations
Integration Points:
- Used by SocialFeedCache to store individual events
- Referenced by other services needing event data
5. Other Domain-Specific Caches
The app also includes several other caching services for specific domains:
- Workout History Caching: Stores workout records for offline access
- Exercise Library Caching: Maintains a local copy of the exercise database
- Template Caching: Provides offline access to workout templates
- Contact List Caching: Stores user's contact list for offline use
Implementation Challenges
Our current implementation has several challenges:
- Fragmentation: Multiple cache services with overlapping functionality
- Code Duplication: Similar patterns reimplemented across services
- Inconsistent Strategies: Different invalidation, error handling, and persistence approaches
- Maintenance Burden: Changes require updates to multiple services
- Dependency Management: Multiple NDK integration points
NDK Mobile Cache Integration
The NDK Mobile library provides robust built-in caching capabilities through the NDKCacheAdapterSqlite
class, which we are currently underutilizing. Key features include:
- Unified SQLite Database Management: Schema migrations, transaction support
- Event Caching: Storage/retrieval of events with tag indexing
- Profile Caching: LRU-based profile data caching
- Unpublished Event Management: Storing and retrying failed publications
- Query Interface: Sophisticated filtering of cached events
- Write Buffering: Performance optimizations for database writes
// NDK initialization with SQLite cache adapter
const cacheAdapter = new NDKCacheAdapterSqlite('powr', 1000);
await cacheAdapter.initialize();
const ndk = new NDK({
cacheAdapter,
explicitRelayUrls: DEFAULT_RELAYS,
enableOutboxModel: true,
autoConnectUserRelays: true,
clientName: 'powr',
});
Future Direction: Centralized Cache Architecture
To address the challenges of our current fragmented approach, we plan to evolve toward a unified caching architecture leveraging NDK Mobile's built-in capabilities.
Proposed Architecture
graph TD
A[Application] --> B[CacheManager]
B --> C[NDKCacheAdapterSqlite]
B --> D[DomainServiceLayer]
D --> E[ProfileService]
D --> F[FeedService]
D --> G[WorkoutService]
D --> H[TemplateService]
D --> I[ExerciseService]
Key Components
-
CacheManager: Centralized facade for all caching operations
- Initializes and configures NDK cache adapter
- Provides unified API for common operations
- Manages NDK integration
-
Domain Services: Specialized services that focus on business logic
- Use NDK cache for storage/retrieval
- Add domain-specific functionality
- Handle presentation concerns
-
Media Cache: For binary data not handled by NDK (images, etc.)
- File system based storage
- LRU eviction policies
- Size limitations and cleanup
Implementation Roadmap
-
Phase 1: Enhance NDK initialization and configuration
- Configure NDK cache adapter with appropriate settings
- Create CacheManager facade
-
Phase 2: Refactor existing services to use NDK cache
- Start with ProfileImageCache → ProfileService
- Update SocialFeedCache to leverage NDK subscription caching
-
Phase 3: Add centralized monitoring and management
- Cache size monitoring
- Performance metrics
- Coordinated invalidation
-
Phase 4: Implement advanced features
- Selective syncing
- Background refreshing
- Cross-device synchronization
User Experience Considerations
Offline Indicators
The app provides clear visual indicators when operating in offline mode:
- Global offline indicator in the header
- Feed-specific offline state components
- Disabled actions that require connectivity
- Queued action indicators
Transparent Sync
Synchronization happens transparently in the background:
- Automatic publishing of queued events when connectivity is restored
- Progressive loading of fresh content when coming online
- Prioritized sync for critical data
Data Freshness
The app balances offline availability with data freshness:
- Age indicators for cached content
- Pull-to-refresh to force update when online
- Background refresh of frequently accessed data
Migration Strategy
Transitioning from our current implementation to the centralized approach will be done incrementally:
- First, refactor NDK initialization to properly configure the cache adapter
- Create the CacheManager facade while maintaining compatibility with existing services
- Gradually update each service to use CacheManager instead of direct database access
- Consolidate duplicate functionality across services
Conclusion
The cache management system in POWR is critical for delivering a responsive, offline-capable experience. While our current implementation successfully provides these capabilities, moving toward a more centralized approach based on NDK's built-in features will reduce complexity, improve maintainability, and ensure consistent behavior across the app.
Related Documentation
- NDK Comprehensive Guide - Overview of NDK functionality
- Offline Queue - Publication queueing for offline support
- Social Feed Cache Implementation - Details on feed caching