Skip to content

fix(core): eliminate background_downloader temp-file leak + deterministic task IDs (#383)#384

Merged
DenisovAV merged 10 commits into
mainfrom
fix/383-download-partial-cleanup
Jul 18, 2026
Merged

fix(core): eliminate background_downloader temp-file leak + deterministic task IDs (#383)#384
DenisovAV merged 10 commits into
mainfrom
fix/383-download-partial-cleanup

Conversation

@DenisovAV

Copy link
Copy Markdown
Owner

What

Failed / cancelled / process-killed large-file model downloads leaked multi-GB background_downloader temp files (com.bbflight.background_downloader<rand>) in Android filesDir — persistent internal storage the OS never reclaims. Reported in #383 with an exceptionally detailed source-level breakdown by @alan-insam. Fixes all five findings plus the migration needed to make the task-ID change regression-free.

Changes

  • Wrong typo in README #1 group mismatch — one SmartDownloader.downloadGroup constant; every cleanup / resume call site routed through it (three used the stale flutter_gemma_downloads literal ≠ the smart_downloads group downloads run under — the leak amplifier).
  • iOS: Build Error #2 non-deterministic task IDssha256 of the stable Task.split triple (baseDirectory / directory / filename), not hashCode and not the URL. Stable across process restarts, signed-URL rotation, and iOS app-container UUID churn.
  • <uses-native-library> missing in Android LLM Inference Guide #3 / Putting model inside output_path folder does not work #6 invisible fragmentsgetOrphanedFiles() now scans filesDir for com.bbflight.background_downloader* temps (flagged isDownloadFragment); cleanupStorage() deletes them.
  • Size concern  #4 watchdog leak — the resume watchdog now cancels the native task and purges its resume/paused/db records before failing; the attach path calls resume() on a recovered paused task instead of stalling until timeout.
  • Failed to build iOS app #5 reset vs cancel — cleanup cancels tasks (which deletes paused temp files) before reset(); performCleanup whole-group, _cleanupAllTasksOfType type-scoped.

Anti-regression migration

Legacy resume records written by a pre-1.3.1 version are reconciled and purged at startup before the reclaim gate — a resumeFromBackground()-materialized paused record no longer wedges it — and the blanket sweep only skips when a task is genuinely running (nativeRunningIds = allTasks − pausedTasks), with a 10-min mtime guard against a just-rescheduled download.

Behaviour notes

  • The plugin now drives the process's first resumeFromBackground().
  • A partial from an older plugin version is reclaimed on next launch (its record is reconciled), not silently stranded.
  • Android-only: reclaim + fragment scan are Platform.isAndroid-gated; iOS/macOS/web unaffected (the id-scheme change on iOS is a net improvement — stable across container-UUID rotation).

Verification

  • Host-VM: flutter analyze 0 errors/warnings, flutter test 470/470, flutter build web clean.
  • Cross-platform compile: iOS, macOS, and Android --release all build clean.
  • Device (Firebase Test Lab, Galaxy S23 Ultra / Android 14): 4/4 tests pass — orphan-fragment cleanup and the legacy-record reconciliation verified against real background_downloader storage.

Targets flutter_gemma 1.3.1. Pins background_downloader ^9.5.6.

Fixes #383

@DenisovAV
DenisovAV merged commit a2a895b into main Jul 18, 2026
5 checks passed
@DenisovAV
DenisovAV deleted the fix/383-download-partial-cleanup branch July 18, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: failed/resumed model downloads leak multi-GB background_downloader temp files

1 participant