From 138ef8301b91f00d2818ca2586b90dd7715abcaa Mon Sep 17 00:00:00 2001 From: Meng Zhang Date: Thu, 18 Apr 2024 12:14:12 -0700 Subject: [PATCH] refactor(webserver): cache list_repositories in CodeService (#1886) * refactor(webserver): cache list_repositories in CodeService * update * update * update --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/tabby-common/src/api/code.rs | 3 ++ crates/tabby/Cargo.toml | 3 +- crates/tabby/src/routes/search.rs | 4 +++ crates/tabby/src/services/code.rs | 16 +++++++--- .../services/completion/completion_prompt.rs | 4 +++ ee/tabby-db/Cargo.toml | 2 +- ee/tabby-webserver/Cargo.toml | 1 - ee/tabby-webserver/src/handler.rs | 31 +++++-------------- 10 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 138ccf3309ce..55485b5b999b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4471,6 +4471,7 @@ dependencies = [ "axum", "axum-prometheus", "axum-tracing-opentelemetry", + "cached", "chrono", "clap", "futures", @@ -4639,7 +4640,6 @@ dependencies = [ "axum", "base64 0.22.0", "bincode", - "cached", "chrono", "futures", "hash-ids", diff --git a/Cargo.toml b/Cargo.toml index bbb7f48f3138..0165076bbd03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ authors = ["TabbyML Team"] homepage = "https://github.com/TabbyML/tabby" [workspace.dependencies] -cached = { version = "0.49.3", features = ["async"] } +cached = "0.49.3" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1" diff --git a/crates/tabby-common/src/api/code.rs b/crates/tabby-common/src/api/code.rs index ecc992fe3cee..c2cc31f4bc79 100644 --- a/crates/tabby-common/src/api/code.rs +++ b/crates/tabby-common/src/api/code.rs @@ -36,6 +36,9 @@ pub enum CodeSearchError { #[error(transparent)] TantivyError(#[from] tantivy::TantivyError), + + #[error(transparent)] + Other(#[from] anyhow::Error), } #[async_trait] diff --git a/crates/tabby/Cargo.toml b/crates/tabby/Cargo.toml index 8405e27f8459..c5f4721367ff 100644 --- a/crates/tabby/Cargo.toml +++ b/crates/tabby/Cargo.toml @@ -59,7 +59,8 @@ thiserror.workspace = true chrono.workspace = true axum-prometheus = "0.4.0" uuid.workspace = true -nucleo = { workspace = true } +nucleo.workspace = true +cached = { workspace = true, features = ["async"] } [dependencies.openssl] optional = true diff --git a/crates/tabby/src/routes/search.rs b/crates/tabby/src/routes/search.rs index a7ff29aa06db..fe93dc3cf5f9 100644 --- a/crates/tabby/src/routes/search.rs +++ b/crates/tabby/src/routes/search.rs @@ -60,5 +60,9 @@ pub async fn search( warn!("{}", err); Err(StatusCode::BAD_REQUEST) } + Err(CodeSearchError::Other(err)) => { + warn!("{}", err); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } } } diff --git a/crates/tabby/src/services/code.rs b/crates/tabby/src/services/code.rs index 48186b319fc3..91846c0eabb7 100644 --- a/crates/tabby/src/services/code.rs +++ b/crates/tabby/src/services/code.rs @@ -2,6 +2,7 @@ use std::{sync::Arc, time::Duration}; use anyhow::Result; use async_trait::async_trait; +use cached::{CachedAsync, TimedCache}; use nucleo::Utf32String; use tabby_common::{ api::code::{CodeSearch, CodeSearchError, Hit, HitDocument, SearchResponse}, @@ -25,6 +26,7 @@ struct CodeSearchImpl { schema: CodeSearchSchema, repository_access: Arc, + repo_cache: Mutex>>, } impl CodeSearchImpl { @@ -47,6 +49,7 @@ impl CodeSearchImpl { reader, query_parser, schema: code_schema, + repo_cache: Mutex::new(TimedCache::with_lifespan(10 * 60)), }) } @@ -126,11 +129,14 @@ impl CodeSearch for CodeSearchImpl { let language_query = self.schema.language_query(language); let body_query = self.schema.body_query(tokens); - let repos = self - .repository_access - .list_repositories() - .await - .unwrap_or_default(); + let mut cache = self.repo_cache.lock().await; + + let repos = cache + .try_get_or_set_with((), || async { + let repos = self.repository_access.list_repositories().await?; + Ok::<_, anyhow::Error>(repos) + }) + .await?; let Some(git_url) = closest_match(git_url, repos.iter()) else { return Ok(SearchResponse::default()); diff --git a/crates/tabby/src/services/completion/completion_prompt.rs b/crates/tabby/src/services/completion/completion_prompt.rs index 0436619d75de..f456738e7bd5 100644 --- a/crates/tabby/src/services/completion/completion_prompt.rs +++ b/crates/tabby/src/services/completion/completion_prompt.rs @@ -200,6 +200,10 @@ async fn collect_snippets( warn!("Failed to parse query: {}", err); return ret; } + Err(CodeSearchError::Other(err)) => { + warn!("Failed to search: {}", err); + return ret; + } }; let mut count_characters = 0; diff --git a/ee/tabby-db/Cargo.toml b/ee/tabby-db/Cargo.toml index 9a8b99e9bdd0..77e64c68ad16 100644 --- a/ee/tabby-db/Cargo.toml +++ b/ee/tabby-db/Cargo.toml @@ -18,7 +18,7 @@ sql_query_builder = { version = "2.1.0", features = ["sqlite"] } sqlx = { version = "0.7.3", features = ["sqlite", "chrono", "runtime-tokio", "macros"] } tokio = { workspace = true, features = ["fs"] } uuid.workspace = true -cached.workspace = true +cached = { workspace = true, features = ["async"]} [dev-dependencies] assert_matches = "1.5.0" diff --git a/ee/tabby-webserver/Cargo.toml b/ee/tabby-webserver/Cargo.toml index 2d2331213b78..616e03c7a39d 100644 --- a/ee/tabby-webserver/Cargo.toml +++ b/ee/tabby-webserver/Cargo.toml @@ -15,7 +15,6 @@ async-trait.workspace = true axum = { workspace = true, features = ["ws", "headers"] } base64 = "0.22.0" bincode = "1.3.3" -cached = { workspace = true } chrono = { workspace = true, features = ["serde"] } futures.workspace = true hash-ids.workspace = true diff --git a/ee/tabby-webserver/src/handler.rs b/ee/tabby-webserver/src/handler.rs index 9128fe59e6f8..148d0bcf064e 100644 --- a/ee/tabby-webserver/src/handler.rs +++ b/ee/tabby-webserver/src/handler.rs @@ -8,7 +8,6 @@ use axum::{ response::{IntoResponse, Response}, routing, Extension, Json, Router, }; -use cached::{CachedAsync, TimedCache}; use hyper::{header::CONTENT_TYPE, Body, StatusCode}; use juniper::ID; use juniper_axum::{graphiql, playground}; @@ -21,7 +20,6 @@ use tabby_common::{ config::{RepositoryAccess, RepositoryConfig}, }; use tabby_db::DbConn; -use tokio::sync::Mutex; use tracing::{error, warn}; use crate::{ @@ -45,14 +43,18 @@ use crate::{ struct RepositoryAccessImpl { git_repository_service: Arc, github_repository_service: Arc, - url_cache: Mutex>>, } #[async_trait] impl RepositoryAccess for RepositoryAccessImpl { async fn list_repositories(&self) -> anyhow::Result> { - let mut cache = self.url_cache.lock().await; - let mut repos = vec![]; + let mut repos: Vec = self + .git_repository_service + .list(None, None, None, None) + .await? + .into_iter() + .map(|repo| RepositoryConfig::new(repo.git_url)) + .collect(); repos.extend( self.github_repository_service @@ -63,24 +65,6 @@ impl RepositoryAccess for RepositoryAccessImpl { .map(RepositoryConfig::new), ); - repos.extend( - cache - .try_get_or_set_with((), || async { - let repos = self - .git_repository_service - .list(None, None, None, None) - .await?; - Ok::<_, anyhow::Error>( - repos - .into_iter() - .map(|repo| RepositoryConfig::new(repo.git_url)) - .collect(), - ) - }) - .await? - .clone(), - ); - Ok(repos) } } @@ -112,7 +96,6 @@ impl WebserverHandle { repository_access: Arc::new(RepositoryAccessImpl { git_repository_service, github_repository_service, - url_cache: Mutex::new(TimedCache::with_lifespan(10 * 60)), }), } }