Implement comprehensive logging and observability for recovery operations: - Add HistoryDAO for Core Data history recording - recordRecovery() method with execution time tracking - recordRecoveryFailure() method with detailed error info - Query helpers for history retrieval - Enhance DailyNotificationReactivationManager logging: - Add execution time tracking (startTime/endTime) - Enhanced error logging with NSError details (domain, code, userInfo) - Comprehensive logging at each recovery step - Missed/future notification count logging - Implement Core Data persistence for recovery metrics: - Recovery execution time - Missed notification count - Rescheduled notification count - Verified notification count - Error count - Diagnostic JSON with full recovery context - Update recovery methods to record history: - Cold start recovery - Termination recovery - Boot recovery - All with timing and metrics Completes section 7.1 (Recovery Logging) and 7.2 (Metrics Recording) of iOS implementation checklist.
17 KiB
17 KiB
iOS Implementation Checklist
Author: Matthew Raymer
Date: 2025-12-08
Status: 🎯 ACTIVE - Implementation Tracking
Version: 1.0.0
Purpose
Complete checklist of iOS code that needs to be implemented for feature parity with Android. This checklist tracks all implementation tasks with checkboxes.
Reference:
- iOS Implementation Directive - Implementation guide
- iOS Recovery Scenario Mapping - Scenario details
- iOS Core Data Migration Guide - Database entities
Phase 1: Cold Start Recovery (High Priority)
1.1 Create ReactivationManager
- Create new file:
ios/Plugin/DailyNotificationReactivationManager.swift - Implement class structure with properties:
notificationCenter: UNUserNotificationCenterdatabase: DailyNotificationDatabasestorage: DailyNotificationStoragescheduler: DailyNotificationSchedulerTAG: String = "DNP-REACTIVATION"
- Implement
init(database:storage:scheduler:)initializer - Implement
performRecovery()async method - Add timeout protection (2 seconds max)
- Add error handling (non-fatal, log only)
1.2 Scenario Detection
- Create
RecoveryScenarioenum:.none- No recovery needed.coldStart- App launched after termination.termination- App terminated, notifications missing.warmStart- App resumed (optimization)
- Implement
detectScenario() async throws -> RecoveryScenario:- Check if database has notifications (empty →
.none) - Get pending notifications from
UNUserNotificationCenter - Compare DB state with notification center state
- Return appropriate scenario
- Check if database has notifications (empty →
1.3 Cold Start Recovery Logic
- Implement
performColdStartRecovery() async throws -> RecoveryResult:- Detect missed notifications (scheduled_time < now, not delivered)
- Mark missed notifications in database (Phase 1: basic marking, Phase 2: add delivery_status)
- Update
last_delivery_attempttimestamp (Phase 2: add property) - Record in history table (Phase 1: logging only, Phase 2: database recording)
- Verify future notifications are scheduled
- Reschedule missing future notifications
- Return
RecoveryResultwith counts
1.4 Missed Notification Detection
- Implement
detectMissedNotifications() async throws -> [NotificationContent]:- Query storage for notifications with
scheduled_time < currentTime - Filter for missed notifications (Phase 1: time-based only, Phase 2: add delivery_status check)
- Return list of missed notifications
- Query storage for notifications with
- Implement
markMissedNotification(_:) async throws:- Mark notification as missed (Phase 1: basic, Phase 2: add delivery_status property)
- Update notification in storage
- Record status change (Phase 1: logging, Phase 2: history table)
1.5 Future Notification Verification
- Implement
verifyFutureNotifications() async throws -> VerificationResult:- Get all future notifications from storage
- Get pending notifications from
UNUserNotificationCenter - Compare notification IDs
- Identify missing notifications
- Return verification result
- Implement
rescheduleMissingNotification(id:) async throws:- For each missing notification, reschedule using
DailyNotificationScheduler - Verify no duplicates created (scheduler handles this)
- Log rescheduling activity
- For each missing notification, reschedule using
1.6 Recovery Result Types
- Create
RecoveryResultstruct:missedCount: IntrescheduledCount: IntverifiedCount: Interrors: Int
- Create
VerificationResultstruct:totalSchedules: IntnotificationsFound: IntnotificationsMissing: IntmissingIds: [String]
1.7 Integration with Plugin
- Add
reactivationManagerproperty toDailyNotificationPlugin - Initialize
ReactivationManagerinload()method - Call
performRecovery()inload()method (async, non-blocking) - Add logging with
DNP-REACTIVATIONtag - Ensure recovery doesn't block app startup (Task-based async execution)
1.8 History Recording
- Implement
recordRecoveryHistory(_:scenario:)method:- Record recovery execution (Phase 1: logging with JSON, Phase 2: database table)
- Include scenario, counts, outcome
- Add diagnostic JSON with details
- Implement
recordRecoveryFailure(_:)method:- Record recovery errors (Phase 1: logging, Phase 2: database table)
- Include error message and error type
1.9 Testing
- Unit tests for scenario detection
- Unit tests for missed notification detection
- Unit tests for future notification verification
- Unit tests for boot detection
- Unit tests for recovery result types
- Integration test for full recovery flow
- Manual test with test scripts (
test-phase1.sh)
Phase 2: App Termination Detection (High Priority)
2.1 Termination Detection Logic
- Enhance
detectScenario()to detect termination:- Check if DB has notifications but no pending notifications
- Return
.terminationscenario
- Implement
handleTerminationRecovery() async throws:- Detect all missed notifications
- Mark all as missed
- Reschedule all future notifications
- Reschedule all fetch schedules (if applicable)
2.2 Comprehensive Recovery
- Implement
performFullRecovery() async throws -> RecoveryResult:- Handle all notifications (missed and future)
- Reschedule all missing notifications
- Batch operations for efficiency
- Return comprehensive result
2.3 Multiple Schedules Recovery
- Implement recovery for multiple schedules:
- Handle multiple notifications (batch processing)
- Batch operations for efficiency (single pending request query)
- Handle partial failures gracefully (continue on error)
- Separate missed vs future notifications for batch processing
2.4 Testing
- Test termination detection accuracy
- Test full recovery with multiple schedules
- Test partial failure scenarios
- Manual test with test scripts (
test-phase2.sh)
Phase 3: Background Task Registration & Boot Recovery (Medium Priority)
3.1 BGTaskScheduler Registration
- Verify
BGTaskSchedulerregistration inDailyNotificationPlugin.setupBackgroundTasks():- Check
fetchTaskIdentifierregistration (already implemented) - Check
notifyTaskIdentifierregistration (already implemented) - Add verification method
verifyBGTaskRegistration()in ReactivationManager
- Check
- Implement boot detection:
- Check system uptime on app launch
- Compare with last launch time (stored in UserDefaults)
- Detect if boot occurred recently (< 60 seconds threshold)
3.2 Boot Recovery Logic
- Implement
performBootRecovery() async throws:- Detect all missed notifications (past scheduled times)
- Mark all as missed
- Reschedule all future notifications
- Record boot recovery in history
3.3 Background Task Handlers
- Enhance
handleBackgroundFetchinDailyNotificationBackgroundTasks.swift:- Add recovery logic if needed
- Schedule next background task
- Handle expiration gracefully
- Enhance
handleBackgroundNotify:- Add recovery logic if needed
- Schedule next background task
3.4 Testing
- Test BGTaskScheduler registration
- Test boot detection (simulate or manual)
- Test boot recovery logic
- Manual test with test scripts (
test-phase3.sh)
Core Data Entities (High Priority)
4.1 NotificationContent Entity
- Update
DailyNotificationModel.xcdatamodeld:- Add
NotificationContententity - Add all 23 attributes (id, pluginVersion, timesafariDid, etc.)
- Set correct attribute types (String, Date, Int32, Int64, Bool)
- Add default values where specified
- Mark required vs optional attributes
- Add
- Add indexes:
timesafariDidindexnotificationTypeindexscheduledTimeindex
- Note: Core Data auto-generates class files with
codeGenerationType="class" - Implement data conversion helpers (if needed):
Date↔Long(epoch milliseconds) conversion helpersInt64↔Longconversion helpers
4.2 NotificationDelivery Entity
- Update
DailyNotificationModel.xcdatamodeld:- Add
NotificationDeliveryentity - Add all 20 attributes
- Set correct attribute types
- Add default values
- Add
- Configure relationship:
- Add
notificationContentrelationship (to-one) - Set deletion rule to
Nullify(Core Data handles cascade via inverse) - Add inverse relationship
deliveries(to-many) onNotificationContent
- Add
- Add indexes:
notificationIdindexdeliveryTimestampindex
- Note: Core Data auto-generates class files
4.3 NotificationConfig Entity
- Update
DailyNotificationModel.xcdatamodeld:- Add
NotificationConfigentity - Add all 13 attributes
- Set correct attribute types
- Add default values
- Add
- Add indexes:
configKeyindexconfigTypeindextimesafariDidindex
- Note: Core Data auto-generates class files
4.4 Data Access Layer
- Create DAO classes or extensions:
NotificationContentDAOor extension methodsNotificationDeliveryDAOor extension methodsNotificationConfigDAOor extension methods
- Implement CRUD operations:
- Create/Insert methods
- Read/Query methods with predicates
- Update methods
- Delete methods
- Implement query helpers:
- Query by timesafariDid
- Query by notificationType
- Query by scheduledTime range
- Query by deliveryStatus
4.5 Persistence Controller Updates
- Update
PersistenceController(if exists) or create:- Handle new entities in initialization
- Add migration policies if needed
- Test database initialization (unit tests verify Core Data stack)
- Test Core Data stack:
- Entity creation (tested in DAO unit tests)
- Relationships (tested in NotificationDeliveryDAOTests)
- Cascade delete (tested in NotificationDeliveryDAOTests)
- Data conversion (tested in DailyNotificationDataConversionsTests)
API Methods (Medium Priority)
5.1 Notification Permission Methods
- Implement
getNotificationPermissionStatus():- Query
UNUserNotificationCenter.current().getNotificationSettings() - Map to
NotificationPermissionStatustype - Return authorization status
- Query
- Implement
requestNotificationPermission():- Request authorization via
UNUserNotificationCenter - Handle user response
- Return
{ granted: boolean }
- Request authorization via
- Implement
openNotificationSettings():- Open iOS Settings app to notification settings
- Use
UIApplication.shared.open()with settings URL
5.2 Background Task Methods
- Implement
getBackgroundTaskStatus():- Check BGTaskScheduler registration
- Check Background App Refresh status (cannot check programmatically, return null)
- Return
BackgroundTaskStatusobject
- Implement
openBackgroundAppRefreshSettings():- Open iOS Settings app to Background App Refresh
- Use
UIApplication.shared.open()with settings URL
5.3 Pending Notifications Method
- Implement
getPendingNotifications():- Query
UNUserNotificationCenter.current().getPendingNotificationRequests() - Map to
PendingNotification[]array - Return count and notification details
- Query
- Add to
pluginMethodsarray inDailyNotificationPlugin
5.4 Register Methods in Plugin
- Add methods to
pluginMethodsarray:getNotificationPermissionStatusrequestNotificationPermissiongetPendingNotificationsgetBackgroundTaskStatusopenNotificationSettingsopenBackgroundAppRefreshSettings
Data Type Conversions (High Priority)
6.1 Time Conversions
- Create helper functions:
dateFromEpochMillis(_: Int64) -> DateepochMillisFromDate(_: Date) -> Int64
- Use in all Core Data operations:
- When reading from database (Long → Date)
- When writing to database (Date → Long)
6.2 Numeric Conversions
- Ensure correct type mappings:
Int→Int32for small integersLong→Int64for large integersBoolean→Bool(direct)
6.3 String Conversions
- Handle optional strings correctly:
String?in Swift maps to optional in Core Data- JSON fields stored as
String?
Logging & Observability (Medium Priority)
7.1 Recovery Logging
- Add comprehensive logging:
DNP-REACTIVATION: Starting app launch recoveryDNP-REACTIVATION: Detected scenario: [scenario]DNP-REACTIVATION: Missed notifications detected: [count]DNP-REACTIVATION: Future notifications verified: [count]DNP-REACTIVATION: Recovery completed: [result]
- Add error logging:
DNP-REACTIVATION: Recovery failed (non-fatal): [error]- Include error details and stack trace (NSError domain, code, userInfo)
7.2 Metrics Recording
- Record recovery metrics in history table:
- Recovery execution time (tracked with startTime/endTime)
- Missed notification count
- Rescheduled notification count
- Error count
- Add diagnostic JSON to history entries (via HistoryDAO.recordRecovery)
Error Handling (High Priority)
8.1 Recovery Error Handling
- Ensure all recovery methods catch errors:
- Database errors (non-fatal)
- Notification center errors (non-fatal)
- Scheduling errors (non-fatal)
- Log errors but don't crash app
- Return partial results if some operations fail
8.2 Error Types
- Define iOS-specific error codes:
NOTIFICATION_PERMISSION_DENIEDBACKGROUND_REFRESH_DISABLEDPENDING_NOTIFICATION_LIMIT_EXCEEDEDBG_TASK_NOT_REGISTEREDBG_TASK_EXECUTION_FAILED
- Map to error responses in plugin methods
Testing (High Priority)
9.1 Unit Tests
- Test
ReactivationManagerinitialization (DailyNotificationReactivationManagerTests) - Test scenario detection logic:
- Test
.nonescenario (empty database) - Test
.coldStartscenario - Test
.terminationscenario - Test
.warmStartscenario
- Test
- Test missed notification detection
- Test future notification verification
- Test recovery result creation
- Test data conversions (DailyNotificationDataConversionsTests)
- Test NotificationContentDAO (NotificationContentDAOTests)
- Test NotificationDeliveryDAO (NotificationDeliveryDAOTests)
- Test NotificationConfigDAO (NotificationConfigDAOTests)
9.2 Integration Tests
- Test full recovery flow:
- Schedule notification
- Terminate app
- Launch app
- Verify recovery executed
- Verify notifications rescheduled
- Test error handling:
- Test database errors
- Test notification center errors
- Verify app doesn't crash
9.3 Manual Testing
- Run
test-phase1.shscript - Run
test-phase2.shscript - Run
test-phase3.shscript - Test on physical device (not just simulator)
- Test with Background App Refresh enabled/disabled
- Test with notification permission granted/denied
Documentation Updates (Low Priority)
10.1 Code Documentation
- Add file-level documentation to
DailyNotificationReactivationManager.swift - Add method-level documentation to all public methods
- Add parameter documentation
- Add return value documentation
- Add error documentation
10.2 Implementation Status
- Update
ios/Plugin/README.mdwith implementation status - Mark completed features as ✅
- Update version numbers
- Update "Last Updated" dates
Summary
Total Tasks: ~150+ implementation tasks
Priority Breakdown:
- High Priority: ~80 tasks (Phase 1, Core Data, API methods, Error handling)
- Medium Priority: ~50 tasks (Phase 2, Phase 3, Logging)
- Low Priority: ~20 tasks (Documentation)
Estimated Implementation Time:
- Phase 1: 2-3 days
- Phase 2: 1-2 days
- Phase 3: 1 day
- Core Data: 2-3 days
- API Methods: 1 day
- Testing: 2-3 days
- Total: ~10-15 days
Document Version: 1.0.0
Last Updated: 2025-12-08
Next Review: After Phase 1 implementation