# Meetily Model Download Manager Architecture: Progress Tracking, Cancellation, and Corruption Detection

> Discover Meetily's model download manager architecture. Learn how it tracks progress, handles cancellation via HTTP Range, and detects corruption using Rust.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: architecture
- Published: 2026-07-07

---

**Meetily's model download manager uses a Rust-based `ModelManager` struct with `Arc<RwLock<…>>` state management to track download lifecycles, report granular progress via callbacks, support HTTP Range resumption for cancellation, and validate GGUF magic numbers to detect corruption.**

The architecture resides in the Tauri backend of [Zackriya-Solutions/meetily](https://github.com/Zackriya-Solutions/meetily), specifically within the summarization engine module. It handles built-in AI models for LLM features through a robust state machine that transitions between `NotDownloaded`, `Downloading`, `Available`, `Corrupted`, and `Error` states. All operations are thread-safe, allowing concurrent UI interactions while maintaining data integrity across async download tasks.

## Core Architecture and Data Structures

### ModelManager Struct and Thread Safety

The central orchestrator is the `ModelManager` struct defined in [[`frontend/src-tauri/src/summary/summary_engine/model_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/summary_engine/model_manager.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/summary_engine/model_manager.rs#L10-L22). It encapsulates:

- The models directory path
- A map of model metadata (`HashMap<String, ModelInfo>`)
- A set of active downloads to prevent concurrent operations
- A cancellation flag for graceful shutdowns

All mutable state is protected behind **`Arc<RwLock<…>>`** wrappers, enabling safe sharing across async tasks without data races.

### ModelStatus Enum and State Machine

The lifecycle of every model is encoded in the `ModelStatus` enum (lines 60‑76):

```rust
pub enum ModelStatus {
    NotDownloaded,
    Downloading { progress: f32 },
    Available,
    Corrupted { size: u64, expected_minimum: u64 },
    Error(String),
}

```

This five-state design allows the UI to distinguish between a model that has never been downloaded, one currently in progress, a verified available asset, or a corrupted file requiring re-download.

### DownloadProgress and Real-time Reporting

Fine-grained progress reporting uses the `DownloadProgress` struct (lines 23‑38), which tracks:

- **Bytes downloaded** and **total bytes**
- **Megabytes** representation for UI display
- **Transfer speed** in MB/s
- **Percentage** completion

The manager emits these updates through a callback mechanism: `Box<dyn Fn(DownloadProgress)>` passed into the download method, allowing the Tauri frontend to receive real-time updates without polling.

## Download Flow with Progress and Resumption

### HTTP Range Requests and Partial File Handling

The `download_model_detailed` method implements **resumable downloads** via HTTP Range headers. When initiating a download, the manager first checks for existing partial files:

```rust
let existing_size = if file_path.exists() {
    std::fs::metadata(&file_path)?.len()
} else { 0 };

// Request resume if partial file exists
if existing_size > 0 {
    // Add header: Range: bytes=<existing>-
}

```

If the server supports partial content (HTTP 206), the manager opens the file in **append mode** using `OpenOptions::append(true)` and continues from the existing byte offset.

### Chunked Streaming and Progress Calculation

The download loop streams data using an **8 MiB buffered writer** (`BufWriter`). After each chunk:

1. Write to disk and flush the buffer
2. Update the running byte counter
3. Calculate percentage and speed (MB/s)
4. Determine if a progress event should fire (on every percent change or every 500ms)

During each iteration, the manager checks the cancellation flag via `Arc<RwLock<bool>>` comparison, allowing immediate but graceful termination.

## Cancellation Mechanism

Cancellation is handled through a non-blocking flag pattern. The `cancel_download` method (lines 95‑115) writes the target model name into `cancel_download_flag`, which the download loop inspects after each chunk write:

```rust
if cancel_flag.as_ref() == Some(&model_name.to_string()) {
    writer.flush()?;
    *status = ModelStatus::NotDownloaded;
    return Err("CANCELLED".into());
}

```

When cancelled, the method flushes the `BufWriter` to preserve partial data and returns an error. The partial file remains on disk, enabling **seamless resumption** when the user restarts the download.

## Corruption Detection and Validation

### Startup Scanning and Size Validation

Upon initialization (`init()` → `scan_models()`), the manager validates existing files against the metadata defined in [`models.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/models.rs). The corruption detection logic (lines 24‑56) implements a **±10% size tolerance**:

- If the file size matches expected dimensions → `ModelStatus::Available`
- If the size deviates beyond tolerance → `ModelStatus::Corrupted` with recorded actual and expected sizes
- If the file is missing → `ModelStatus::NotDownloaded`

This heuristic catches incomplete downloads or filesystem corruption before the model is loaded into memory.

### Post-Download GGUF Verification

After the byte stream completes, `validate_gguf_file` (lines 72‑92) performs a magic number check. The function reads the first four bytes and validates against the **GGUF signature** (`b"GGUF"`):

```rust
let mut buffer = [0u8; 4];
file.read_exact(&mut buffer)?;
if &buffer != b"GGUF" {
    // Mark as Error and delete file
}

```

If validation fails, the manager immediately deletes the corrupted file and transitions the status to `Error(String)`, preventing runtime crashes from invalid model formats.

## Integration with the Tauri Frontend

The Rust backend exposes functionality through Tauri commands in [[`frontend/src-tauri/src/commands.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/commands.rs)](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/commands.rs):

- **`whisper_download_model`** (line 452): Wraps `ModelManager::download_model` with progress callback serialization to the JavaScript frontend
- **`whisper_cancel_download`** (line 496): Invokes `ModelManager::cancel_download` to set the cancellation flag

The frontend receives structured progress updates containing bytes, MB, speed, and percentage, enabling rich UI progress bars with transfer rate indicators.

## Code Examples

### Starting a Download with Progress Callback

```rust
use meetily::summary::summary_engine::model_manager::ModelManager;

let manager = ModelManager::new()?;
manager.init().await?;

manager
    .download_model_detailed(
        "gemma_1b",
        Some(Box::new(|progress| {
            println!(
                "Progress: {:.1}% ({:.2} MB / {:.2} MB @ {:.2} MB/s)",
                progress.percent,
                progress.downloaded_mb,
                progress.total_mb,
                progress.speed_mbps
            );
        })),
    )
    .await?;

```

### Cancelling an Active Download

```rust
let manager = ModelManager::new()?;
manager.cancel_download("gemma_1b").await?;

```

The cancellation flag is set immediately; the download loop detects it within the next chunk iteration and preserves the partial file for resumption.

### Checking Model Availability

```rust
let manager = ModelManager::new()?;
manager.init().await?;

if manager.is_model_ready("gemma_1b", true).await {
    println!("Model validated and ready");
} else {
    println!("Model missing, corrupted, or downloading");
}

```

Passing `true` forces a fresh filesystem scan, ensuring the status reflects recent disk changes.

## Summary

- **Thread-safe architecture**: `ModelManager` uses `Arc<RwLock<…>>` to share mutable state across async tasks safely
- **Resumable downloads**: HTTP Range headers and append-mode file writing enable cancellation without data loss
- **Real-time progress**: `DownloadProgress` struct reports bytes, MB, speed, and percentage via callbacks to the frontend
- **Dual validation**: File size checks on startup (±10% tolerance) and GGUF magic number verification post-download prevent corrupted models from entering the pipeline
- **Graceful cancellation**: Atomic flag checks within the download loop allow immediate termination while preserving partial files

## Frequently Asked Questions

### How does Meetily handle network interruptions during model downloads?

Meetily's download manager supports **automatic resumption** through HTTP Range requests. When a download starts, it checks for existing partial files and sends a `Range: bytes=<existing>-` header. If the server supports partial content (HTTP 206), the download continues from the interruption point. If the network fails or the user cancels, the partial file remains on disk, allowing seamless continuation without re-downloading completed bytes.

### What happens if a downloaded model file is corrupted?

The manager implements **two-stage validation**. First, during startup scanning (`scan_models`), it checks if the file size falls within ±10% of the expected size, marking it as `Corrupted` if not. Second, after download completion, `validate_gguf_file` reads the first four bytes to verify the GGUF magic number. If either check fails, the file is deleted and the status becomes `Error`, requiring a fresh download.

### Can users cancel a download and restart it later without losing progress?

Yes. When `cancel_download` is invoked, it sets a cancellation flag that the download loop checks after each chunk. Upon detection, the loop flushes the `BufWriter` and exits cleanly, leaving the partial file intact. The status reverts to `NotDownloaded`. When the user restarts the download, the manager detects the existing file size and issues an HTTP Range request to resume from that byte offset, preserving previous progress.

### How does the frontend receive real-time download progress?

The backend uses a **callback mechanism** defined in `download_model_detailed`. It accepts a `Box<dyn Fn(DownloadProgress)>` closure that emits events containing bytes downloaded, total bytes, MB representation, transfer speed (MB/s), and percentage completion. These events are serialized through Tauri commands (`whisper_download_model`) and transmitted to the JavaScript frontend, enabling live progress bars without polling.