[object Object]

← back to Exo

Ciaran/minor download bugs (#1674)

79c8dbeacd2bd8288d769da20df7fc24ba9c9295 · 2026-03-06 17:46:18 +0000 · ciaranbor

## Motivation

Two minor bugs in the download coordinator: cancelling a download didn't
reset its status to pending, and a single error in
_emit_existing_download_progress would kill the loop permanently.

## Changes

- Cancel emits pending status: When a download is cancelled, emit a
DownloadPending event so the UI/cluster state reflects that the model is
no longer actively downloading.
- Resilient progress emission loop: Move the try/except inside the while
loop so transient errors are logged but the periodic emission continues.

## Why It Works

- The cancel fix ensures the download status is consistent — without it,
a cancelled download would still appear as in-progress.
- The loop fix prevents a single exception from permanently stopping the
60-second periodic progress broadcast.

Files touched

Diff

commit 79c8dbeacd2bd8288d769da20df7fc24ba9c9295
Author: ciaranbor <81697641+ciaranbor@users.noreply.github.com>
Date:   Fri Mar 6 17:46:18 2026 +0000

    Ciaran/minor download bugs (#1674)
    
    ## Motivation
    
    Two minor bugs in the download coordinator: cancelling a download didn't
    reset its status to pending, and a single error in
    _emit_existing_download_progress would kill the loop permanently.
    
    ## Changes
    
    - Cancel emits pending status: When a download is cancelled, emit a
    DownloadPending event so the UI/cluster state reflects that the model is
    no longer actively downloading.
    - Resilient progress emission loop: Move the try/except inside the while
    loop so transient errors are logged but the periodic emission continues.
    
    ## Why It Works
    
    - The cancel fix ensures the download status is consistent — without it,
    a cancelled download would still appear as in-progress.
    - The loop fix prevents a single exception from permanently stopping the
    60-second periodic progress broadcast.
---
 src/exo/download/coordinator.py | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/exo/download/coordinator.py b/src/exo/download/coordinator.py
index 76307867..28e9f626 100644
--- a/src/exo/download/coordinator.py
+++ b/src/exo/download/coordinator.py
@@ -133,6 +133,16 @@ class DownloadCoordinator:
         if model_id in self.active_downloads and model_id in self.download_status:
             logger.info(f"Cancelling download for {model_id}")
             self.active_downloads.pop(model_id).cancel()
+            current_status = self.download_status[model_id]
+            pending = DownloadPending(
+                shard_metadata=current_status.shard_metadata,
+                node_id=self.node_id,
+                model_directory=self._model_dir(model_id),
+            )
+            self.download_status[model_id] = pending
+            await self.event_sender.send(
+                NodeDownloadProgress(download_progress=pending)
+            )
 
     async def _start_download(self, shard: ShardMetadata) -> None:
         model_id = shard.model_card.model_id
@@ -287,8 +297,8 @@ class DownloadCoordinator:
             del self.download_status[model_id]
 
     async def _emit_existing_download_progress(self) -> None:
-        try:
-            while True:
+        while True:
+            try:
                 logger.debug(
                     "DownloadCoordinator: Fetching and emitting existing download progress..."
                 )
@@ -376,8 +386,8 @@ class DownloadCoordinator:
                 logger.debug(
                     "DownloadCoordinator: Done emitting existing download progress."
                 )
-                await anyio.sleep(60)
-        except Exception as e:
-            logger.error(
-                f"DownloadCoordinator: Error emitting existing download progress: {e}"
-            )
+            except Exception as e:
+                logger.error(
+                    f"DownloadCoordinator: Error emitting existing download progress: {e}"
+                )
+            await anyio.sleep(60)

← 00961597 up gossipsub limit (#1671)  ·  back to Exo  ·  Ciaran/gpt oss tool call finish reason (#1673) d0163610 →