10 KiB
Database Consolidation Plan
Current State
Database 1: Java (daily_notification_plugin.db)
notification_content- Specific notification instancesnotification_delivery- Delivery tracking/analyticsnotification_config- Configuration
Database 2: Kotlin (daily_notification_database)
content_cache- Fetched content with TTLschedules- Recurring schedule patterns (CRITICAL for reboot)callbacks- Callback configurationshistory- Execution history
Unified Schema Design
Required Tables (All Critical)
-
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
-
content_cache- Fetched content with TTL- Stores prefetched content for offline-first display
- Fields: id, fetchedAt, ttlSeconds, payload (BLOB), meta
-
notification_config- Plugin configuration- Stores user preferences and plugin settings
- Fields: id, timesafariDid, configType, configKey, configValue, configDataType, isEncrypted, createdAt, updatedAt
-
callbacks- Callback configurations- Stores callback endpoint configurations
- Fields: id, kind ('http'/'local'/'queue'), target, headersJson, enabled, createdAt
Optional Tables (Analytics/Debugging)
-
notification_content- Specific notification instances- May still be needed for one-time notifications or TimeSafari integration
- Fields: All existing fields from Java entity
-
notification_delivery- Delivery tracking- Analytics for delivery attempts and user interactions
- Fields: All existing fields from Java entity
-
history- Execution history- Logs fetch/notify/callback execution
- Fields: id, refId, kind, occurredAt, durationMs, outcome, diagJson
Consolidation Strategy
- Keep Kotlin schema as base - It already has critical tables
- Add Java tables to Kotlin schema - Merge missing entities
- Update all Java code - Use unified database instance
- Update all Kotlin code - Use unified database instance
- Single database file:
daily_notification_plugin.db
Migration Path
- Create unified
DailyNotificationDatabasewith all entities - Update Java code to use unified database
- Update Kotlin code to use unified database
- Remove old
DailyNotificationDatabasefiles - 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
// Read schedules
getSchedules(options?: { kind?: 'fetch' | 'notify', enabled?: boolean }): Promise<Schedule[]>
getSchedule(id: string): Promise<Schedule | null>
// Write schedules
createSchedule(schedule: CreateScheduleInput): Promise<Schedule>
updateSchedule(id: string, updates: Partial<Schedule>): Promise<Schedule>
deleteSchedule(id: string): Promise<void>
enableSchedule(id: string, enabled: boolean): Promise<void>
// Utility
calculateNextRunTime(schedule: string): Promise<number>
Content Cache Management
// Read content cache
getContentCache(options?: { id?: string }): Promise<ContentCache | null>
getLatestContentCache(): Promise<ContentCache | null>
getContentCacheHistory(limit?: number): Promise<ContentCache[]>
// Write content cache
saveContentCache(content: CreateContentCacheInput): Promise<ContentCache>
clearContentCache(options?: { olderThan?: number }): Promise<void>
Configuration Management
// Read config
getConfig(key: string, options?: { timesafariDid?: string }): Promise<Config | null>
getAllConfigs(options?: { timesafariDid?: string, configType?: string }): Promise<Config[]>
// Write config
setConfig(config: CreateConfigInput): Promise<Config>
updateConfig(key: string, value: string, options?: { timesafariDid?: string }): Promise<Config>
deleteConfig(key: string, options?: { timesafariDid?: string }): Promise<void>
Callbacks Management
// Read callbacks
getCallbacks(options?: { enabled?: boolean }): Promise<Callback[]>
getCallback(id: string): Promise<Callback | null>
// Write callbacks
registerCallback(callback: CreateCallbackInput): Promise<Callback>
updateCallback(id: string, updates: Partial<Callback>): Promise<Callback>
deleteCallback(id: string): Promise<void>
enableCallback(id: string, enabled: boolean): Promise<void>
History/Analytics (Optional)
// Read history
getHistory(options?: {
since?: number,
kind?: 'fetch' | 'notify' | 'callback',
limit?: number
}): Promise<History[]>
getHistoryStats(): Promise<HistoryStats>
Type Definitions
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
- Analyzed both database schemas and identified all required tables
- Designed unified database schema with all required entities
- Created unified DailyNotificationDatabase class (Kotlin)
- Added migration from version 1 (Kotlin-only) to version 2 (unified)
- Updated all Java code to use unified database
DailyNotificationStorageRoom.java- Uses unified databaseDailyNotificationWorker.java- Uses unified database
- Updated all Kotlin code to use unified database
DailyNotificationPlugin.kt- Uses unified databaseFetchWorker.kt- Uses unified databaseNotifyReceiver.kt- Uses unified databaseBootReceiver.kt- Uses unified database
- Implemented all Config methods in PluginMethods
- TypeScript interfaces updated for database CRUD operations
- Documentation created for AI assistants
⏳ Pending Tasks
- 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)
-
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
-
content_cache- Fetched content with TTL- Stores prefetched content for offline-first display
- Fields: id, fetchedAt, ttlSeconds, payload (BLOB), meta
-
notification_config- Plugin configuration- Stores user preferences and plugin settings
- Fields: id, timesafariDid, configType, configKey, configValue, configDataType, isEncrypted, createdAt, updatedAt, ttlSeconds, isActive, metadata
-
callbacks- Callback configurations- Stores callback endpoint configurations
- Fields: id, kind ('http'/'local'/'queue'), target, headersJson, enabled, createdAt
-
notification_content- Specific notification instances- Stores notification content with plugin-specific fields
- Fields: All existing fields from Java entity
-
notification_delivery- Delivery tracking- Analytics for delivery attempts and user interactions
- Fields: All existing fields from Java entity
-
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
-
Remove Old Database File ✅ COMPLETE
- Delete
android/src/main/java/com/timesafari/dailynotification/database/DailyNotificationDatabase.java - Verify no remaining references
- Delete
-
Testing
- Test reboot recovery with unified database
- Verify schedule restoration works correctly
- Verify all Config methods work correctly
- Test migration from v1 to v2
-
Documentation
- Update any remaining documentation references
- Verify AI documentation is complete