# Database Consolidation Plan ## Current State ### Database 1: Java (`daily_notification_plugin.db`) - `notification_content` - Specific notification instances - `notification_delivery` - Delivery tracking/analytics - `notification_config` - Configuration ### Database 2: Kotlin (`daily_notification_database`) - `content_cache` - Fetched content with TTL - `schedules` - Recurring schedule patterns (CRITICAL for reboot) - `callbacks` - Callback configurations - `history` - Execution history ## Unified Schema Design ### Required Tables (All Critical) 1. **`schedules`** - Recurring schedule patterns - Stores cron/clockTime patterns - Used to restore schedules after reboot - Fields: id, kind ('fetch'/'notify'), cron, clockTime, enabled, lastRunAt, nextRunAt, jitterMs, backoffPolicy, stateJson 2. **`content_cache`** - Fetched content with TTL - Stores prefetched content for offline-first display - Fields: id, fetchedAt, ttlSeconds, payload (BLOB), meta 3. **`notification_config`** - Plugin configuration - Stores user preferences and plugin settings - Fields: id, timesafariDid, configType, configKey, configValue, configDataType, isEncrypted, createdAt, updatedAt 4. **`callbacks`** - Callback configurations - Stores callback endpoint configurations - Fields: id, kind ('http'/'local'/'queue'), target, headersJson, enabled, createdAt ### Optional Tables (Analytics/Debugging) 5. **`notification_content`** - Specific notification instances - May still be needed for one-time notifications or TimeSafari integration - Fields: All existing fields from Java entity 6. **`notification_delivery`** - Delivery tracking - Analytics for delivery attempts and user interactions - Fields: All existing fields from Java entity 7. **`history`** - Execution history - Logs fetch/notify/callback execution - Fields: id, refId, kind, occurredAt, durationMs, outcome, diagJson ## Consolidation Strategy - [x] Keep Kotlin schema as base - It already has critical tables - [x] Add Java tables to Kotlin schema - Merge missing entities - [x] Update all Java code - Use unified database instance - [x] Update all Kotlin code - Use unified database instance - [x] Single database file: `daily_notification_plugin.db` ## Migration Path - [x] Create unified `DailyNotificationDatabase` with all entities - [x] Update Java code to use unified database - [x] Update Kotlin code to use unified database - [x] Remove old `DailyNotificationDatabase` files - [ ] Test reboot recovery ## Key Decisions - **Primary language**: Kotlin (more modern, better coroutine support) - **Database name**: `daily_notification_plugin.db` (Java naming convention) - **All entities**: Both Java and Kotlin compatible - **DAOs**: Mix of Java and Kotlin DAOs as needed ## TypeScript Interface Requirements Since the plugin owns the database, the host app/webview needs TypeScript interfaces to read/write data. ### Required TypeScript Methods #### Schedules Management ```typescript // Read schedules getSchedules(options?: { kind?: 'fetch' | 'notify', enabled?: boolean }): Promise getSchedule(id: string): Promise // Write schedules createSchedule(schedule: CreateScheduleInput): Promise updateSchedule(id: string, updates: Partial): Promise deleteSchedule(id: string): Promise enableSchedule(id: string, enabled: boolean): Promise // Utility calculateNextRunTime(schedule: string): Promise ``` #### Content Cache Management ```typescript // Read content cache getContentCache(options?: { id?: string }): Promise getLatestContentCache(): Promise getContentCacheHistory(limit?: number): Promise // Write content cache saveContentCache(content: CreateContentCacheInput): Promise clearContentCache(options?: { olderThan?: number }): Promise ``` #### Configuration Management ```typescript // Read config getConfig(key: string, options?: { timesafariDid?: string }): Promise getAllConfigs(options?: { timesafariDid?: string, configType?: string }): Promise // Write config setConfig(config: CreateConfigInput): Promise updateConfig(key: string, value: string, options?: { timesafariDid?: string }): Promise deleteConfig(key: string, options?: { timesafariDid?: string }): Promise ``` #### Callbacks Management ```typescript // Read callbacks getCallbacks(options?: { enabled?: boolean }): Promise getCallback(id: string): Promise // Write callbacks registerCallback(callback: CreateCallbackInput): Promise updateCallback(id: string, updates: Partial): Promise deleteCallback(id: string): Promise enableCallback(id: string, enabled: boolean): Promise ``` #### History/Analytics (Optional) ```typescript // Read history getHistory(options?: { since?: number, kind?: 'fetch' | 'notify' | 'callback', limit?: number }): Promise getHistoryStats(): Promise ``` ### Type Definitions ```typescript interface Schedule { id: string kind: 'fetch' | 'notify' cron?: string clockTime?: string // HH:mm format enabled: boolean lastRunAt?: number nextRunAt?: number jitterMs: number backoffPolicy: string stateJson?: string } interface ContentCache { id: string fetchedAt: number ttlSeconds: number payload: string // Base64 or JSON string meta?: string } interface Config { id: string timesafariDid?: string configType: string configKey: string configValue: string configDataType: string isEncrypted: boolean createdAt: number updatedAt: number } interface Callback { id: string kind: 'http' | 'local' | 'queue' target: string headersJson?: string enabled: boolean createdAt: number } interface History { id: number refId: string kind: 'fetch' | 'notify' | 'callback' | 'boot_recovery' occurredAt: number durationMs?: number outcome: string diagJson?: string } ``` # Database Consolidation Plan ## Status: ✅ **CONSOLIDATION COMPLETE** The unified database has been successfully created and all code has been migrated to use it. ## Current State ### Unified Database (`daily_notification_plugin.db`) Located in: `android/src/main/java/com/timesafari/dailynotification/DatabaseSchema.kt` **All Tables Consolidated:** - ✅ `content_cache` - Fetched content with TTL (Kotlin) - ✅ `schedules` - Recurring schedule patterns (Kotlin, CRITICAL for reboot) - ✅ `callbacks` - Callback configurations (Kotlin) - ✅ `history` - Execution history (Kotlin) - ✅ `notification_content` - Specific notification instances (Java) - ✅ `notification_delivery` - Delivery tracking/analytics (Java) - ✅ `notification_config` - Configuration management (Java) ### Old Database Files (DEPRECATED - REMOVED) - ✅ `android/src/main/java/com/timesafari/dailynotification/database/DailyNotificationDatabase.java` - **REMOVED** - All functionality merged into unified database ## Migration Status ### ✅ Completed Tasks - [x] Analyzed both database schemas and identified all required tables - [x] Designed unified database schema with all required entities - [x] Created unified DailyNotificationDatabase class (Kotlin) - [x] Added migration from version 1 (Kotlin-only) to version 2 (unified) - [x] Updated all Java code to use unified database - [x] `DailyNotificationStorageRoom.java` - Uses unified database - [x] `DailyNotificationWorker.java` - Uses unified database - [x] Updated all Kotlin code to use unified database - [x] `DailyNotificationPlugin.kt` - Uses unified database - [x] `FetchWorker.kt` - Uses unified database - [x] `NotifyReceiver.kt` - Uses unified database - [x] `BootReceiver.kt` - Uses unified database - [x] Implemented all Config methods in PluginMethods - [x] TypeScript interfaces updated for database CRUD operations - [x] Documentation created for AI assistants ### ⏳ Pending Tasks - [x] Remove old database files (`DailyNotificationDatabase.java`) - [ ] Test reboot recovery with unified database - [ ] Verify migration path works correctly ## Unified Schema Design (IMPLEMENTED) ### Required Tables (All Critical) 1. **`schedules`** - Recurring schedule patterns - Stores cron/clockTime patterns - Used to restore schedules after reboot - Fields: id, kind ('fetch'/'notify'), cron, clockTime, enabled, lastRunAt, nextRunAt, jitterMs, backoffPolicy, stateJson 2. **`content_cache`** - Fetched content with TTL - Stores prefetched content for offline-first display - Fields: id, fetchedAt, ttlSeconds, payload (BLOB), meta 3. **`notification_config`** - Plugin configuration - Stores user preferences and plugin settings - Fields: id, timesafariDid, configType, configKey, configValue, configDataType, isEncrypted, createdAt, updatedAt, ttlSeconds, isActive, metadata 4. **`callbacks`** - Callback configurations - Stores callback endpoint configurations - Fields: id, kind ('http'/'local'/'queue'), target, headersJson, enabled, createdAt 5. **`notification_content`** - Specific notification instances - Stores notification content with plugin-specific fields - Fields: All existing fields from Java entity 6. **`notification_delivery`** - Delivery tracking - Analytics for delivery attempts and user interactions - Fields: All existing fields from Java entity 7. **`history`** - Execution history - Logs fetch/notify/callback execution - Fields: id, refId, kind, occurredAt, durationMs, outcome, diagJson ## Implementation Details ### Database Access - **Kotlin**: `DailyNotificationDatabase.getDatabase(context)` - **Java**: `DailyNotificationDatabase.getInstance(context)` (Java-compatible wrapper) ### Migration Path - Version 1 → Version 2: Automatically creates Java entity tables when upgrading from Kotlin-only schema - Migration runs automatically on first access after upgrade ### Thread Safety - All database operations use Kotlin coroutines (`Dispatchers.IO`) - Room handles thread safety internally - Singleton pattern ensures single database instance ## Next Steps 1. **Remove Old Database File** ✅ COMPLETE - [x] Delete `android/src/main/java/com/timesafari/dailynotification/database/DailyNotificationDatabase.java` - [x] Verify no remaining references 2. **Testing** - [ ] Test reboot recovery with unified database - [ ] Verify schedule restoration works correctly - [ ] Verify all Config methods work correctly - [ ] Test migration from v1 to v2 3. **Documentation** - [ ] Update any remaining documentation references - [ ] Verify AI documentation is complete