Skip to content

Adopt Turso-inspired performance patterns for codebase databases#491

Draft
iberi22 wants to merge 1 commit into
mainfrom
perf/turso-patterns-10752104400361843081
Draft

Adopt Turso-inspired performance patterns for codebase databases#491
iberi22 wants to merge 1 commit into
mainfrom
perf/turso-patterns-10752104400361843081

Conversation

@iberi22
Copy link
Copy Markdown
Owner

@iberi22 iberi22 commented Jun 4, 2026

Improved Xavier's database performance by implementing patterns inspired by Turso: batch inserts with transactions, lazy schema creation, and an LRU connection cache using moka. These changes reduce resource usage and speed up repository indexing.

Fixes #427


PR created automatically by Jules for task 10752104400361843081 started by @iberi22

- Refactor ConnectionManager to use moka::future::Cache for LRU connection pooling.
- Implement lazy schema initialization in CodebaseDb and ConversationsDb via OnceCell.
- Add batch insert methods to CodebaseDb using libSQL transactions.
- Optimize FTS population and database connection logic for async efficiency.
- Enhance path sanitization for per-project conversation databases.
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd420a3d-c2e4-449e-bfbb-3da8db7c5302

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/turso-patterns-10752104400361843081

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request transitions the connection management from synchronous r2d2 pooling to an asynchronous moka::future::Cache using libsql::Connection. It also introduces lazy schema initialization via tokio::sync::OnceCell across ConversationsDb and CodebaseDb, alongside new batch insertion methods for chunks, symbols, and embeddings. Feedback on these changes highlights a critical compilation error in ConnectionManager::connect due to a lifetime mismatch when capturing a borrowed string slice in the cache initialization future, as well as panic risks from using .expect() instead of propagating errors via try_get_with.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +26 to 75
pub async fn connect(&self, project_id: &str, project_root: &str) -> Result<Connection> {
let project_id_owned = project_id.to_string();
let project_root_owned = project_root.to_string();

let conn_res = self.connections
.get_with(project_id_owned, async move {
let db_path = if project_id == "memory" {
PathBuf::from(project_root_owned).join("xavier_memory.db")
} else if project_id == "vec_store" {
PathBuf::from(project_root_owned).join("vec-store.sqlite3")
} else if project_id == "metrics" {
PathBuf::from(project_root_owned).join("metrics.db")
} else if project_id.starts_with("conv_") {
let pid = project_id.strip_prefix("conv_").unwrap();
crate::codebase::conversations_db::ConversationsDb::db_path(pid)
} else {
PathBuf::from(project_root_owned)
.join(".xavier")
.join("codebase.db")
};

if let Some(parent) = db_path.parent() {
let parent = parent.to_path_buf();
tokio::task::spawn_blocking(move || {
std::fs::create_dir_all(parent)
}).await
.expect("spawn_blocking panicked")
.expect("failed to create db directory");
}

let db = libsql::Builder::new_local(db_path.to_string_lossy().to_string())
.build()
.await
.expect("failed to build libsql db");
let conn = db.connect().expect("failed to connect to libsql db");

conn.execute_batch(
"PRAGMA journal_mode=WAL; \
PRAGMA busy_timeout=5000; \
PRAGMA synchronous=NORMAL;",
)
.await
.expect("failed to set pragmas");

conn
})
.await;

Ok(conn_res)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Critical Compilation & Safety Issues

  1. Lifetime / Compilation Error: The async move block passed to get_with captures project_id (which is a &str with a lifetime bound to the function call). Since moka::future::Cache::get_with requires the future to be 'static, this will cause a compilation error (borrowed value does not live long enough). To fix this, we must use an owned clone of the project ID (e.g., project_id_for_init) inside the async block.
  2. Panic Risk: Using .expect() inside the cache initialization block will panic the entire thread/task if any database or file system operation fails (e.g., disk full, permission denied). We should use try_get_with instead of get_with to gracefully propagate errors as anyhow::Result.
    pub async fn connect(&self, project_id: &str, project_root: &str) -> Result<Connection> {
        let project_id_owned = project_id.to_string();
        let project_id_for_init = project_id_owned.clone();
        let project_root_owned = project_root.to_string();

        let conn_res = self.connections
            .try_get_with(project_id_owned, async move {
                let db_path = if project_id_for_init == "memory" {
                    PathBuf::from(project_root_owned).join("xavier_memory.db")
                } else if project_id_for_init == "vec_store" {
                    PathBuf::from(project_root_owned).join("vec-store.sqlite3")
                } else if project_id_for_init == "metrics" {
                    PathBuf::from(project_root_owned).join("metrics.db")
                } else if project_id_for_init.starts_with("conv_") {
                    let pid = project_id_for_init.strip_prefix("conv_").unwrap();
                    crate::codebase::conversations_db::ConversationsDb::db_path(pid)
                } else {
                    PathBuf::from(project_root_owned)
                        .join(".xavier")
                        .join("codebase.db")
                };

                if let Some(parent) = db_path.parent() {
                    let parent = parent.to_path_buf();
                    tokio::task::spawn_blocking(move || {
                        std::fs::create_dir_all(parent)
                    }).await
                    .context("spawn_blocking panicked")?
                    .context("failed to create db directory")?;
                }

                let db = libsql::Builder::new_local(db_path.to_string_lossy().to_string())
                    .build()
                    .await
                    .context("failed to build libsql db")?;
                let conn = db.connect().context("failed to connect to libsql db")?;

                conn.execute_batch(
                    "PRAGMA journal_mode=WAL; \\
                     PRAGMA busy_timeout=5000; \\
                     PRAGMA synchronous=NORMAL;",
                )
                .await
                .context("failed to set pragmas")?;

                Ok::<_, anyhow::Error>(conn)
            })
            .await
            .map_err(|e| anyhow::anyhow!("failed to connect: {}", e))?;

        Ok(conn_res)
    }

@iberi22 iberi22 added jules Assigned to Google Jules and removed jules Assigned to Google Jules labels Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jules Assigned to Google Jules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[perf] Adoptar patrones de Turso: batch inserts, lazy schema, LRU cache, spawn_blocking

1 participant