8.1 KiB
Prefetch Scheduling Trace Analysis
Analysis Date: October 27, 2025 - 12:18:37 UTC
Author: Matthew Raymer
Status: Investigation Complete
Summary
This document traces how prefetch scheduling works solo and in conjunction with notification schedules. Investigation reveals that prefetch schedules ARE being set, but there may be issues with logging visibility and execution.
Code Flow Analysis
1. Notification Scheduling Flow
When a user schedules a notification via the plugin:
DailyNotificationPlugin.scheduleDailyNotification()
↓
DailyNotificationScheduler.scheduleNotification()
↓
Plugin.scheduleBackgroundFetch(content.getScheduledTime())
Location: android/plugin/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java:658
2. Prefetch Scheduling Flow
The scheduleBackgroundFetch method calculates the fetch time:
private void scheduleBackgroundFetch(long scheduledTime) {
try {
Log.d(TAG, "DN|SCHEDULE_FETCH_START time=" + scheduledTime);
// Schedule fetch 5 minutes before notification
long fetchTime = scheduledTime - TimeUnit.MINUTES.toMillis(5);
if (fetchTime > System.currentTimeMillis()) {
Log.d(TAG, "DN|SCHEDULE_FETCH_CALC fetch_at=" + fetchTime + " notification_at=" + scheduledTime);
fetcher.scheduleFetch(fetchTime);
Log.i(TAG, "DN|SCHEDULE_FETCH_OK Background fetch scheduled for " + fetchTime + " (5 minutes before notification at " + scheduledTime + ")");
} else {
Log.w(TAG, "DN|SCHEDULE_FETCH_PAST fetch_time=" + fetchTime + " current=" + System.currentTimeMillis());
}
} catch (Exception e) {
Log.e(TAG, "DN|SCHEDULE_FETCH_ERR Error scheduling background fetch", e);
}
}
Location: DailyNotificationPlugin.java:961-978
3. WorkManager Enqueuing
The fetcher.scheduleFetch() method creates a WorkManager request:
public void scheduleFetch(long scheduledTime) {
try {
Log.d(TAG, "Scheduling background fetch for " + scheduledTime);
// Calculate fetch time (5 minutes before notification)
long fetchTime = scheduledTime - TimeUnit.MINUTES.toMillis(5);
if (fetchTime > System.currentTimeMillis()) {
// Create work data
Data inputData = new Data.Builder()
.putLong("scheduled_time", scheduledTime)
.putLong("fetch_time", fetchTime)
.putInt("retry_count", 0)
.build();
// Create one-time work request
OneTimeWorkRequest fetchWork = new OneTimeWorkRequest.Builder(
DailyNotificationFetchWorker.class)
.setInputData(inputData)
.addTag(WORK_TAG_FETCH)
.setInitialDelay(fetchTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.build();
// Enqueue the work
workManager.enqueue(fetchWork);
Log.i(TAG, "Background fetch scheduled successfully");
} else {
Log.w(TAG, "Fetch time has already passed, scheduling immediate fetch");
scheduleImmediateFetch();
}
} catch (Exception e) {
Log.e(TAG, "Error scheduling background fetch", e);
// Fallback to immediate fetch
scheduleImmediateFetch();
}
}
Location: DailyNotificationFetcher.java:77-115
Key Findings
✅ Prefetch Scheduling IS Implemented
The code shows that:
- When a notification is scheduled,
scheduleBackgroundFetch()is called if scheduling succeeds - The prefetch time is calculated:
fetchTime = scheduledTime - 5 minutes - WorkManager work is enqueued with the calculated delay
- Logs ARE generated at several points
⚠️ Potential Issues
-
Logging Visibility
- Logs may not be visible if:
- The app is closed (logs go to system logcat)
- Filters are not capturing the right tags
- Log level is not set correctly
- Logs may not be visible if:
-
Conditional Logging
- The
scheduleBackgroundFetchis only called whenscheduled == true - If notification scheduling fails, no prefetch is scheduled
- This is at line 655-666 in
DailyNotificationPlugin.java
- The
-
Timing Issues
- If
fetchTimeis in the past, it schedules immediate fetch - This might cause confusion if timing calculations are wrong
- If
Expected Log Sequence
When properly scheduling a notification:
DN|SCHEDULE_CALLBACK scheduled=true, calling scheduleBackgroundFetch
DN|SCHEDULE_FETCH_START time=<scheduledTime>
DN|SCHEDULE_FETCH_CALC fetch_at=<fetchTime> notification_at=<scheduledTime>
Scheduling background fetch for <scheduledTime>
Background fetch scheduled successfully
DN|SCHEDULE_FETCH_OK Background fetch scheduled for <fetchTime> (5 minutes before notification at <scheduledTime>)
How to Debug
1. Check if Prefetch is Being Scheduled
Look for these log tags in logcat:
adb logcat | grep -E "DN\|SCHEDULE_FETCH|DailyNotificationFetcher"
Expected logs:
DN|SCHEDULE_FETCH_STARTDN|SCHEDULE_FETCH_CALCDN|SCHEDULE_FETCH_OKScheduling background fetch for
2. Check WorkManager Queue
Verify that work is actually enqueued:
adb shell dumpsys job scheduler | grep -A 5 "daily_notification_fetch"
3. Check if Notification Scheduling Succeeded
Verify the notification scheduling succeeded (this is a prerequisite):
adb logcat | grep "DN|SCHEDULE"
Look for:
DN|SCHEDULE_CALLBACK scheduled=true- Good, prefetch will be scheduledDN|SCHEDULE_CALLBACK scheduled=false- Bad, prefetch will NOT be scheduled
4. Check AlarmManager Schedule
Verify the actual alarm is set:
adb shell dumpsys alarm | grep -i "dailynotification"
Investigation Checklist
To diagnose why prefetch logs aren't appearing:
- Check if notification scheduling is succeeding (look for
DN|SCHEDULE_CALLBACK scheduled=true) - Check if
scheduleBackgroundFetchis being called (look forDN|SCHEDULE_FETCH_START) - Check if fetch time calculation is correct (look for
DN|SCHEDULE_FETCH_CALC) - Check if WorkManager is enqueuing the work (look for "Background fetch scheduled successfully")
- Check if fetch time is in the past (look for "Fetch time has already passed")
- Check WorkManager queue status via
dumpsys job scheduler - Check for any exceptions (look for "DN|SCHEDULE_FETCH_ERR" or "Error scheduling background fetch")
Recommendations
1. Add More Diagnostic Logging
Add logs at critical decision points:
// In scheduleDailyNotification, after scheduler.scheduleNotification()
if (scheduled) {
Log.i(TAG, "DN|SCHEDULE_CALLBACK scheduled=true, calling scheduleBackgroundFetch");
Log.d(TAG, "DN|SCHEDULE_CALLBACK content.getScheduledTime()=" + content.getScheduledTime());
scheduleBackgroundFetch(content.getScheduledTime());
} else {
Log.w(TAG, "DN|SCHEDULE_CALLBACK scheduled=false, NOT calling scheduleBackgroundFetch");
}
2. Add WorkManager Status Logging
Add a log after enqueuing to verify:
workManager.enqueue(fetchWork);
Log.i(TAG, "DN|SCHEDULE_WORK_ENQUEUED work_id=" + fetchWork.getId() +
" fetch_at=" + fetchTime + " delay_ms=" + (fetchTime - System.currentTimeMillis()));
3. Add User-Zero Specific Logging
For stars querying, add specific event IDs:
Log.i(TAG, "EVT_PREFETCH_SCHEDULED time=" + fetchTime + " stars_query=true");
Next Steps
- Capture logcat during notification scheduling
- Search for specific log prefixes documented above
- Check WorkManager queue to verify work is enqueued
- Add diagnostic logging if needed
- Test with actual notification scheduling to see full flow
Conclusion
The prefetch scheduling IS implemented in the codebase. The issue is likely one of:
- Logging visibility (logs not being captured)
- Timing issues (fetch time in past)
- Notification scheduling failure (prefetch not called)
- WorkManager not executing (system-level issue)
The infrastructure is there, but we need to verify the execution path.