You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4.2 KiB

Prefetch Investigation Summary

Problem Statement

The daily notification prefetch job (T-5 min) is not calling the native fetcher, resulting in:

  • from: null in prefetch logs
  • Fallback/mock content being used
  • DISPLAY_SKIP content_not_found at notification time
  • Storage empty ([]) when display worker runs

Root Cause Hypothesis

Based on the directive analysis, likely causes (ranked):

  1. Registration Timing: Prefetch worker runs before Application.onCreate() completes
  2. Discovery Failure: Worker resolves fetcher to null (wrong scope, process mismatch)
  3. Persistence Bug: Content written but wiped/deduped before display
  4. ID Mismatch: Prefetch writes notify_... but display looks for daily_...

Instrumentation Added

TimeSafariApplication.java

  • APP|ON_CREATE ts=... pid=... processName=... - App initialization timing
  • FETCHER|REGISTER_START instanceHash=... ts=... - Before registration
  • FETCHER|REGISTERED providerKey=... instanceHash=... registered=... ts=... - After registration with verification

TimeSafariNativeFetcher.java

  • FETCHER|CONFIGURE_START instanceHash=... pid=... ts=... - Configuration start
  • FETCHER|CONFIGURE_COMPLETE instanceHash=... configured=... apiBaseUrl=... activeDid=... jwtLength=... ts=... - Configuration completion
  • PREFETCH|START id=... notifyAt=... trigger=... instanceHash=... pid=... ts=... - Fetch start
  • PREFETCH|SOURCE from=native/fallback reason=... ts=... - Source resolution
  • PREFETCH|WRITE_OK id=... items=... ts=... - Successful fetch

Diagnostic Tools

Log Filtering Script

./scripts/diagnose-prefetch.sh app.timesafari.app

Filters logcat for:

  • APP|ON_CREATE
  • FETCHER|*
  • PREFETCH|*
  • DISPLAY|*
  • STORAGE|*

Manual Filtering

adb logcat | grep -E "APP\|ON_CREATE|FETCHER\||PREFETCH\||DISPLAY\||STORAGE\|"

Investigation Checklist

A. App/Plugin Initialization Order

  • Confirm APP|ON_CREATE appears before PREFETCH|START
  • Verify FETCHER|REGISTERED registered=true
  • Check for multiple onCreate invocations (process restarts)
  • Confirm single process (no android:process on workers)

B. Prefetch Worker Resolution

  • Check PREFETCH|SOURCE from=native (not from=fallback)
  • Verify instanceHash matches between registration and fetch
  • Compare pid values (should be same process)
  • Check FETCHER|CONFIGURE_COMPLETE configured=true before prefetch

C. Storage & Persistence

  • Verify PREFETCH|WRITE_OK items>=1
  • Check storage logs for content persistence
  • Compare prefetch ID vs display lookup ID (must match)

D. ID Schema Consistency

  • Prefetch ID format: daily_<epoch> or notify_<epoch>
  • Display lookup ID format: must match prefetch ID
  • Verify ID derivation rules are consistent

Next Steps

  1. Run diagnostic script during a notification cycle
  2. Analyze logs for timing issues and process mismatches
  3. If fetcher is null: Implement Fix #2 (Pass Fetcher Context With Work) or Fix #3 (Process-Safe DI)
  4. If ID mismatch: Normalize ID schema across prefetch and display
  5. If storage issue: Add transactional writes and read-after-write verification

Expected Log Flow (Success Case)

APP|ON_CREATE ts=... pid=... processName=app.timesafari.app
FETCHER|REGISTER_START instanceHash=... ts=...
FETCHER|REGISTERED providerKey=DailyNotificationPlugin instanceHash=... registered=true ts=...
FETCHER|CONFIGURE_START instanceHash=... pid=... ts=...
FETCHER|CONFIGURE_COMPLETE instanceHash=... configured=true ... ts=...
PREFETCH|START id=daily_... notifyAt=... trigger=prefetch instanceHash=... pid=... ts=...
PREFETCH|SOURCE from=native instanceHash=... apiBaseUrl=... ts=...
PREFETCH|WRITE_OK id=daily_... items=1 ts=...
STORAGE|POST_PREFETCH total=1 ids=[daily_...]
DISPLAY|START id=daily_...
STORAGE|PRE_DISPLAY total=1 ids=[daily_...]
DISPLAY|LOOKUP result=hit id=daily_...

Failure Indicators

  • PREFETCH|SOURCE from=fallback - Native fetcher not resolved
  • PREFETCH|SOURCE from=null - Fetcher registration failed
  • FETCHER|REGISTERED registered=false - Registration verification failed
  • STORAGE|PRE_DISPLAY total=0 - Content not persisted
  • DISPLAY|LOOKUP result=miss - ID mismatch or content cleared