Loading...

My experience building with AI

O
Osahenrumwen Aigbogun
50 min read
My experience building with AI

Local Convex Data Reset

Use this when you want to start testing with an empty Convex database while keeping the current schema and functions deployed.

What This Does

  • Clears documents from the configured Convex testing deployment.
  • Keeps packages/convex-backend/src/convex/schema.ts and all Convex functions intact.
  • Clears Convex component data too, including Better Auth and Convex Agent tables.
  • Does not run bun run dev.

Current Project Note

This checkout does not currently have a Convex deployment registered as local.
The .env.local files point at a dev: deployment, so the reset command used here targets:

--deployment dev

If you later create a true local Convex deployment, replace --deployment dev with:

--deployment local

Reset Commands

Run these from packages/convex-backend:

backup="/tmp/elevator-convex-before-reset-$(date +%Y%m%d-%H%M%S).zip"
empty_dir="$(mktemp -d /tmp/elevator-convex-empty-snapshot.XXXXXX)"
empty_zip="${empty_dir}.zip"

bunx convex export --deployment dev --path "$backup"

bunx convex data --deployment dev --format jsonArray | while IFS= read -r table; do
  [ -n "$table" ] || continue
  mkdir -p "$empty_dir/$table"
  : > "$empty_dir/$table/documents.jsonl"
done

(
  cd "$empty_dir"
  zip -qr "$empty_zip" .
)

bunx convex import --deployment dev --replace-all --yes "$empty_zip"

Verify The Wipe

Check that user tables are empty:

tables_json="$(bunx convex data --deployment dev --format jsonArray | jq -R -s -c 'split("\n") | map(select(length > 0))')"

bunx convex run --deployment dev --typecheck disable --inline-query "
const tables = $tables_json;
const nonempty = [];
for (const table of tables) {
  const docs = await ctx.db.query(table).take(1);
  if (docs.length > 0) nonempty.push(table);
}
return { checkedTables: tables.length, nonempty };
"

Expected result:

{
  "checkedTables": 158,
  "nonempty": []
}

Check that functions and schema metadata still exist:

bunx convex function-spec --deployment dev | jq '{functionCount: (.functions | length), url}'

For this reset, Convex reported 395 functions after the data wipe.

Rollback Snapshot

This reset saved a pre-wipe snapshot outside the repo:

/tmp/elevator-convex-before-reset-20260601-181645.zip

To restore that data, run from packages/convex-backend:

bunx convex import --deployment dev --replace-all --yes /tmp/elevator-convex-before-reset-20260601-181645.zip

Background Data Sync Audit Report

Project: Milogs Application
Date:
Auditor: Claude (AI Agent)
Scope: Deep audit of cross-platform background/foreground data synchronization behavior


Executive Summary

No, this application does NOT reliably continue syncing data when closed or backgrounded on any platform.

The app implements a foreground-only sync model with very limited background capabilities. When the app is closed (killed/terminated), data sync completely stops . When backgrounded (still running), there is minimal sync activity—only periodic media upload retries on native, and only service-worker-triggered single-pass uploads on web. There is no true background data sync (push/pull of all data types) when_flush’ing when minimized or closed.


1. Web Platform (Browser)

When Minimized / Tab in Background

  • Sync Behavior: Sync HALTS immediately.
  • Evidence:
    • syncEngine.ts line 359-365: appLifecycle.onHidden() callback tears down the real-time sync state subscription ( teardownRuntimeSyncStateSubscription()) and cancels any pending sync timer ( clearTimeout(syncScheduledTimeout)).
    • appLifecycle.ts line 32: Listens to document.visibilitychange and window.pagehide; both trigger onHidden.
    • There is no web worker, no periodic timer, and no setInterval that survives tab backgrounding. JavaScript execution is throttled or frozen.
  • Limitation: Web does not have a background sync mechanism that runs periodically or when the tab is not visible. The app only relies on the browser’s pagehide/ visibilitychange events, which are used to stop sync, not to continue it.

When Closed (Tab Closed / Browser Closed)

  • Sync Behavior: Sync STOPS COMPLETELY .
  • Evidence:
    • The service worker ( service-worker.ts) only handles a 'sync' event with the tag 'milogs-upload-sync', but this only posts a message to any active window clients ( client.postMessage).
    • If no window/tab is open, there is no client to receive the message, and no sync runs.
    • The service worker does not call any sync function directly; it delegates to the app window.
    • There is no periodicSync, push event handler for data sync, or background fetch logic in the service worker.
  • Conclusion: Closing the browser means zero sync until the user reopens the app.

2. Native iOS

When Backgrounded (App Switcher but not closed)

  • Sync Behavior: Sync HALTS .
  • Evidence:
    • syncEngine.ts line 359-365: appLifecycle.onHidden() callback fires when the app is backgrounded (via App.addListener('appStateChange')), which tears down subscriptions and cancels sync timers.
    • There is no iOS Background Fetch, Background URL Session (for sync data), or BGTaskScheduler configured.
    • The only background task is handleEventsForBackgroundURLSession in AppDelegate.swift (line 56-58), which handles AI model downloads (not data sync).

When Closed (Killed / Swiped Away)

  • Sync Behavior: Sync STOPS COMPLETELY .
  • Evidence:
    • Apple's iOS background execution model does not allow arbitrary code to run when the app is terminated.
    • There are no iOS Push Notifications via APNS that trigger a background sync (only local notifications for reminders).
    • The app does not register for remote notifications that could wake it up.

3. Native Android

When Backgrounded (Recent Apps, but not closed)

  • Sync Behavior: Very limited sync— only media uploads via a background interval timer.
  • Evidence:
    • backgroundUpload.ts lines 17-30: On native, App.addListener('pause', ...) starts腹中 starts a setInterval loop ( BACKGROUND_UPLOAD_INTERVAL_MS = 15_000 / 15 seconds) that only runs runSync(true, { uploadsOnly: true }).
    • This is uploads-only and does not pull new data.
    • The loop is stopped on resume.
  • No Background Sync for Pull: There is no full sync (push + pull) when the app is backgrounded.

When Closed (Killed / Swiped Away)

  • Sync Behavior: Sync STOPS COMPLETELY .
  • Evidence:
    • Android BroadcastReceivers ( ReminderBootReceiver, FinAlertBootReceiver) only handle boot/system events to restore notification channels and alarm schedules. They do not trigger data sync.
    • No WorkManager, JobScheduler, or AlarmManager tasks are registered for periodic sync.
    • The AndroidForegroundService is used only for active audio recording and transcription—not for sync.

4. Service Worker Analysis

What the Service Worker Does

  • Caching: Caches static assets (JS, CSS, images) for offline-first loading ( service-worker.ts lines 7-24).
  • Sync Event: Listens for the 'sync' event with tag 'milogs-upload-sync' ( service-worker.ts line 26-38). When triggered, it tries to notify any open window clients to run an upload-only sync pass.
  • Fetch Interception: Caches image assets on fetch ( service-worker.ts lines 40-77).

What the Service Worker Does NOT Do

  • No Periodic Sync: No periodicSync registration or handling.
  • No Push-Triggered Sync: No push event handler.
  • No Direct Sync Execution: Does not call runSync() or any sync engine functions directly. It rely entirely on an active window/tab being open to receive the postMessage.
  • No Background Data Processing: Cannot push non-media entities or pull remote changes when the app is closed.

5. Live Update / OTA (Capgo Plugin)

  • The CapacitorUpdater plugin is configured with autoUpdate: 'atBackground' ( capacitor.config.ts).
  • This triggers Over-The-Air (OTA) updates when the app is backgrounded, but this is not related to data sync . It updates the app's web assets, not user data.

6. Summary Table

Platform Minimized / Background Tab App Closed (Killed) Notes
Web 国际社会 国际社会 Sync halts on visibilitychange hidden. No background execution.
iOS Native 国际社会 国际社会 No Background Fetch, WorkManager, or periodic sync. Foreground-only.
Android Native Limited (uploads-only, every 15s) 国际社会 Only media uploads via setInterval prefer-background timer. No pull.

7. Recommendations (No Code Changes Per Request)

Since the user explicitly requested no code changes, here are documented observations for future action:

  1. Web: Consider implementing Background Sync API ( periodicSync) or Push Notifications to wake the service worker and run sync logic directly (not via window postMessage).
  2. iOS: Consider implementing Background Fetch ( BGAppRefreshTask) or Background Processing ( BGProcessingTask) to periodically sync data when the app receives system background execution time.
  3. Android: Consider using WorkManager with PeriodicWorkRequest or OneTimeWorkRequest to schedule sync tasks that survive app closure.
  4. Push Notifications: Implement push-triggered sync via a push notification service (FCM for Android, APNS for iOS) that wakes the app to perform a sync cycle.
  5. Foreground Service: For critical real-time sync, consider a persistent foreground service (with user-facing notification) on Android that keeps the sync engine alive.

This report was generated by a comprehensive codebase audit focusing on lifecycle hooks, service workers, native background capabilities, and sync engine behavior.