diff --git a/crates/desktop/artcraft/src/core/commands/generate/models/image/list_image_models_command.rs b/crates/desktop/artcraft/src/core/commands/generate/models/image/list_image_models_command.rs index 26add76061..214c8ffcb1 100644 --- a/crates/desktop/artcraft/src/core/commands/generate/models/image/list_image_models_command.rs +++ b/crates/desktop/artcraft/src/core/commands/generate/models/image/list_image_models_command.rs @@ -47,6 +47,10 @@ pub async fn list_image_models_command( } Err(error_message) => { warn!("list_image_models_command failed after {} attempts: {}", MAX_ATTEMPTS, error_message); + if let Some(stale) = any_cached_response() { + warn!("list_image_models_command: refresh failed; serving stale cached response"); + return Ok(stale.into()); + } Err(error_message.into()) } } @@ -62,6 +66,13 @@ fn cached_response() -> Option { } } +/// The cached response regardless of age. Used as a fallback so that a failed +/// refresh still returns the last-known-good data instead of an error. +fn any_cached_response() -> Option { + let guard = CACHE.read().ok()?; + guard.as_ref().map(|entry| entry.response.clone()) +} + fn store_response(response: ListImageModelsResponse) { if let Ok(mut guard) = CACHE.write() { *guard = Some(CacheEntry { response, loaded_at: Instant::now() }); diff --git a/crates/desktop/artcraft/src/core/commands/generate/models/video/list_video_models_command.rs b/crates/desktop/artcraft/src/core/commands/generate/models/video/list_video_models_command.rs index 638b4ab012..79dfde8cda 100644 --- a/crates/desktop/artcraft/src/core/commands/generate/models/video/list_video_models_command.rs +++ b/crates/desktop/artcraft/src/core/commands/generate/models/video/list_video_models_command.rs @@ -47,6 +47,10 @@ pub async fn list_video_models_command( } Err(error_message) => { warn!("list_video_models_command failed after {} attempts: {}", MAX_ATTEMPTS, error_message); + if let Some(stale) = any_cached_response() { + warn!("list_video_models_command: refresh failed; serving stale cached response"); + return Ok(stale.into()); + } Err(error_message.into()) } } @@ -62,6 +66,13 @@ fn cached_response() -> Option { } } +/// The cached response regardless of age. Used as a fallback so that a failed +/// refresh still returns the last-known-good data instead of an error. +fn any_cached_response() -> Option { + let guard = CACHE.read().ok()?; + guard.as_ref().map(|entry| entry.response.clone()) +} + fn store_response(response: ListVideoModelsResponse) { if let Ok(mut guard) = CACHE.write() { *guard = Some(CacheEntry { response, loaded_at: Instant::now() });