Skip to content

Commit 3aff859

Browse files
committed
add cache in apiclient for model
1 parent a57a0b0 commit 3aff859

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

crates/chat-cli/src/api_client/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub use error::ApiClientError;
3434
use parking_lot::Mutex;
3535
pub use profile::list_available_profiles;
3636
use serde_json::Map;
37+
use tokio::sync::RwLock;
3738
use tracing::{
3839
debug,
3940
error,
@@ -75,6 +76,7 @@ pub struct ApiClient {
7576
sigv4_streaming_client: Option<QDeveloperStreamingClient>,
7677
mock_client: Option<Arc<Mutex<std::vec::IntoIter<Vec<ChatResponseStream>>>>>,
7778
profile: Option<AuthProfile>,
79+
model_cache: Arc<RwLock<Option<(Vec<Model>, Option<Model>)>>>,
7880
}
7981

8082
impl ApiClient {
@@ -114,6 +116,7 @@ impl ApiClient {
114116
sigv4_streaming_client: None,
115117
mock_client: None,
116118
profile: None,
119+
model_cache: Arc::new(RwLock::new(None)),
117120
};
118121

119122
if let Ok(json) = env.get("Q_MOCK_CHAT_RESPONSE") {
@@ -181,6 +184,7 @@ impl ApiClient {
181184
sigv4_streaming_client,
182185
mock_client: None,
183186
profile,
187+
model_cache: Arc::new(RwLock::new(None)),
184188
})
185189
}
186190

@@ -277,6 +281,30 @@ impl ApiClient {
277281
Ok((models, default_model))
278282
}
279283

284+
pub async fn list_available_models_cached(&self) -> Result<(Vec<Model>, Option<Model>), ApiClientError> {
285+
{
286+
let cache = self.model_cache.read().await;
287+
if let Some(cached) = cache.as_ref() {
288+
tracing::debug!("Returning cached model list");
289+
return Ok(cached.clone());
290+
}
291+
}
292+
293+
tracing::debug!("Cache miss, fetching models from list_available_models API");
294+
let result = self.list_available_models().await?;
295+
{
296+
let mut cache = self.model_cache.write().await;
297+
*cache = Some(result.clone());
298+
}
299+
Ok(result)
300+
}
301+
302+
pub async fn invalidate_model_cache(&self) {
303+
let mut cache = self.model_cache.write().await;
304+
*cache = None;
305+
tracing::info!("Model cache invalidated");
306+
}
307+
280308
pub async fn create_subscription_token(&self) -> Result<CreateSubscriptionTokenOutput, ApiClientError> {
281309
if cfg!(test) {
282310
return Ok(CreateSubscriptionTokenOutput::builder()

crates/chat-cli/src/cli/chat/cli/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub async fn select_model(os: &mut Os, session: &mut ChatSession) -> Result<Opti
3838
// Fetch available models from service
3939
let (models, _default_model) = os
4040
.client
41-
.list_available_models()
41+
.list_available_models_cached()
4242
.await
4343
.map_err(|e| ChatError::Custom(format!("Failed to fetch available models: {}", e).into()))?;
4444

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl ChatArgs {
289289

290290
// If modelId is specified, verify it exists before starting the chat
291291
// Otherwise, CLI will use a default model when starting chat
292-
let (models, default_model_opt) = os.client.list_available_models().await?;
292+
let (models, default_model_opt) = os.client.list_available_models_cached().await?;
293293
let model_id: Option<String> = if let Some(requested) = self.model.as_ref() {
294294
let requested_lower = requested.to_lowercase();
295295
if let Some(m) = models
@@ -2385,6 +2385,7 @@ impl ChatSession {
23852385
}
23862386

23872387
async fn retry_model_overload(&mut self, os: &mut Os) -> Result<ChatState, ChatError> {
2388+
os.client.invalidate_model_cache().await;
23882389
match select_model(os, self).await {
23892390
Ok(Some(_)) => (),
23902391
Ok(None) => {

0 commit comments

Comments
 (0)