Fix browser crash: cache schema context, lazy Dashboard, default to Ask tab
Root cause: Dashboard auto-fired 6+ API calls on load, then Ask tab fired 7 DESCRIBE queries per question — 15+ concurrent requests from WASM. Fixes: - Schema context cached after first build (7 DESCRIBE → 0 on subsequent questions) - Dashboard lazy-loads only when tab clicked (not on app mount) - Default tab changed back to Ask (no background API storm) - std::sync::Mutex for WASM compat (no tokio in browser) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
238cb84d26
commit
fdb2e9cda8
@ -109,8 +109,30 @@ async fn fetch_health(path: &str) -> Result<String, String> {
|
||||
resp.text().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Cached schema context — built once, reused across questions.
|
||||
static SCHEMA_CACHE: std::sync::OnceLock<std::sync::Mutex<Option<String>>> = std::sync::OnceLock::new();
|
||||
|
||||
async fn get_schema_context_cached(datasets: &[Dataset]) -> String {
|
||||
// Check cache first
|
||||
{
|
||||
let cache = SCHEMA_CACHE.get_or_init(|| std::sync::Mutex::new(None));
|
||||
if let Ok(guard) = cache.lock() {
|
||||
if let Some(ref cached) = *guard {
|
||||
return cached.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Build and cache
|
||||
let ctx = get_schema_context(datasets).await;
|
||||
if let Some(cache) = SCHEMA_CACHE.get() {
|
||||
if let Ok(mut guard) = cache.lock() {
|
||||
*guard = Some(ctx.clone());
|
||||
}
|
||||
}
|
||||
ctx
|
||||
}
|
||||
|
||||
/// Get schema context for datasets (used for AI SQL generation).
|
||||
/// Limits to core tables to keep prompt size reasonable.
|
||||
async fn get_schema_context(datasets: &[Dataset]) -> String {
|
||||
let core_tables = ["candidates", "clients", "job_orders", "placements", "timesheets", "call_log", "email_log"];
|
||||
let mut ctx = String::from("DATABASE SCHEMA:\n\n");
|
||||
@ -163,7 +185,7 @@ enum Tab {
|
||||
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let mut active_tab = use_signal(|| Tab::Dashboard);
|
||||
let mut active_tab = use_signal(|| Tab::Ask);
|
||||
let mut datasets = use_signal(Vec::<Dataset>::new);
|
||||
let mut ds_loading = use_signal(|| true);
|
||||
|
||||
@ -268,7 +290,7 @@ fn AskPanel(datasets: Vec<Dataset>) -> Element {
|
||||
|
||||
// Step 1: Get schema context
|
||||
step.set("reading schemas...".into());
|
||||
let schema_ctx = get_schema_context(&ds).await;
|
||||
let schema_ctx = get_schema_context_cached(&ds).await;
|
||||
|
||||
// Step 2: Generate SQL
|
||||
step.set("writing SQL...".into());
|
||||
@ -351,7 +373,7 @@ fn AskPanel(datasets: Vec<Dataset>) -> Element {
|
||||
generated_sql.set(None);
|
||||
result.set(None);
|
||||
step.set("reading schemas...".into());
|
||||
let schema_ctx = get_schema_context(&ds).await;
|
||||
let schema_ctx = get_schema_context_cached(&ds).await;
|
||||
step.set("writing SQL...".into());
|
||||
let prompt = format!(
|
||||
"You are a SQL assistant. You write Apache DataFusion SQL (PostgreSQL-compatible).\n\n\
|
||||
@ -673,8 +695,14 @@ fn DashboardPanel() -> Element {
|
||||
};
|
||||
|
||||
// Auto-load on mount
|
||||
// Auto-load on mount
|
||||
use_effect(move || { do_load(); });
|
||||
// Load on first render (user clicks Dashboard tab)
|
||||
let mut loaded = use_signal(|| false);
|
||||
use_effect(move || {
|
||||
if !*loaded.read() {
|
||||
loaded.set(true);
|
||||
do_load();
|
||||
}
|
||||
});
|
||||
|
||||
rsx! {
|
||||
div { class: "panel",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user