From 3a91afe7a6ca8e74789e45de0eb555fa3aaa2206 Mon Sep 17 00:00:00 2001 From: Anthony Potappel Date: Mon, 26 Aug 2024 08:02:12 +0200 Subject: [PATCH] execute_query now returns LumniError, add conversion to ApplicationError, allowing to catch NotFound in filebrowser --- lumni-web/src/components/apps/form_submit.rs | 9 +++++ lumni/src/apps/api/error.rs | 35 ++++++++++++++++-- .../prompt/src/tui/modals/filebrowser/mod.rs | 30 ++++++++++----- lumni/src/base/connector.rs | 4 +- lumni/src/handlers/object_store.rs | 37 ++++++++++++------- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/lumni-web/src/components/apps/form_submit.rs b/lumni-web/src/components/apps/form_submit.rs index 2070fca5..323ddc60 100644 --- a/lumni-web/src/components/apps/form_submit.rs +++ b/lumni-web/src/components/apps/form_submit.rs @@ -102,6 +102,15 @@ pub fn AppFormSubmit(app_uri: String) -> impl IntoView { LumniError::Runtime(RuntimeError::Unexpected(e)) => { log::error!("RuntimeError - Unexpected: {}", e); } + LumniError::ParseError(e) => { + log::error!("ParseError: {}", e); + } + LumniError::InternalError(e) => { + log::error!("InternalError: {}", e); + } + LumniError::Resource(e) => { + log::error!("ResourceError: {}", e); + } LumniError::Invoke(e, _) => { log::error!("InvokeError: {}", e); } diff --git a/lumni/src/apps/api/error.rs b/lumni/src/apps/api/error.rs index 9e1d1507..7c084b88 100644 --- a/lumni/src/apps/api/error.rs +++ b/lumni/src/apps/api/error.rs @@ -16,6 +16,8 @@ pub enum LumniError { Invoke(ApplicationError, Option), Resource(ResourceError), NotImplemented(String), + InternalError(String), + ParseError(String), Message(String), Any(String), } @@ -65,9 +67,11 @@ impl fmt::Display for LumniError { LumniError::Runtime(runtime_err) => { write!(f, "RuntimeError: {}", runtime_err) } + LumniError::ParseError(s) => write!(f, "ParseError: {}", s), LumniError::Application(app_err, Some(app_name)) => { write!(f, "[{}]: {}", app_name, app_err) } + LumniError::InternalError(s) => write!(f, "InternalError: {}", s), LumniError::Invoke(app_err, Some(app_name)) => { write!(f, "[{}]: {}", app_name, app_err) } @@ -98,14 +102,39 @@ impl fmt::Display for RequestError { impl From for ApplicationError { fn from(error: LumniError) -> Self { match error { - LumniError::Application(app_error, None) => app_error, - _ => { - ApplicationError::Unexpected("Unhandled LumniError".to_string()) + LumniError::Application(app_error, _) => app_error, + LumniError::Resource(ResourceError::NotFound(s)) => { + ApplicationError::NotFound(s) + } + LumniError::Request(RequestError::QueryInvalid(s)) => { + ApplicationError::InvalidInput(s) + } + LumniError::Runtime(RuntimeError::Unexpected(s)) => { + ApplicationError::Runtime(s) + } + LumniError::ParseError(s) => ApplicationError::InvalidInput(s), + LumniError::InternalError(s) => ApplicationError::InternalError(s), + LumniError::Invoke(s, _) => { + ApplicationError::Runtime(s.to_string()) + } + LumniError::NotImplemented(s) => { + ApplicationError::NotImplemented(s) + } + LumniError::Message(s) | LumniError::Any(s) => { + ApplicationError::Unexpected(s) } } } } +impl fmt::Display for ResourceError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ResourceError::NotFound(s) => write!(f, "NotFound: {}", s), + } + } +} + impl fmt::Display for RuntimeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/lumni/src/apps/builtin/llm/prompt/src/tui/modals/filebrowser/mod.rs b/lumni/src/apps/builtin/llm/prompt/src/tui/modals/filebrowser/mod.rs index f7b0738a..08493e9f 100644 --- a/lumni/src/apps/builtin/llm/prompt/src/tui/modals/filebrowser/mod.rs +++ b/lumni/src/apps/builtin/llm/prompt/src/tui/modals/filebrowser/mod.rs @@ -6,6 +6,7 @@ use std::time::Instant; use async_trait::async_trait; use crossterm::event::KeyCode; +use futures::TryFutureExt; use lumni::{EnvironmentConfig, ObjectStoreHandler, Table, TableColumnValue}; use ratatui::layout::{Alignment, Constraint, Direction, Layout, Margin, Rect}; use ratatui::style::{Color, Modifier, Style}; @@ -46,18 +47,31 @@ impl FileListHandler { Self { handler } } - async fn list_files( + async fn handle_query( &self, - path: String, + query: String, ) -> Result>, ApplicationError> { - let query = format!("SELECT * FROM \"localfs://{}\" LIMIT 100", path); let config = EnvironmentConfig::new(HashMap::new()); - match self + let result = self .handler .execute_query(&query, &config, true, false, None, None) .await - { - Ok(table) => Ok(Arc::new(table as Box)), + .map_err(ApplicationError::from)?; + Ok(Arc::new(result as Box)) + } + + async fn list_files( + &self, + path: String, + ) -> Result>, ApplicationError> { + let query = format!("SELECT * FROM \"localfs://{}\" LIMIT 100", path); + match self.handle_query(query).await { + Ok(table) => Ok(table), + Err(ApplicationError::NotFound(_)) => { + let query = + "SELECT * FROM \"localfs://.\" LIMIT 100".to_string(); + self.handle_query(query).await + } Err(e) => match e { // TODO: update execute_query to return LumniError::ResourceError //ResourceError::NotFound => Err(ApplicationError::NotFound(path)), @@ -324,9 +338,7 @@ impl<'a> FileBrowserModal<'a> { let result = handler .execute_query(&query, &config, true, false, None, None) .await - .map_err(|e| { - ApplicationError::InternalError(e.to_string()) - }); + .map_err(ApplicationError::from); let directory_change_result = match result { Ok(_) => Ok(new_path), diff --git a/lumni/src/base/connector.rs b/lumni/src/base/connector.rs index b4201b78..d47c6d53 100644 --- a/lumni/src/base/connector.rs +++ b/lumni/src/base/connector.rs @@ -1,4 +1,4 @@ -use crate::{EnvironmentConfig, InternalError, ObjectStoreHandler, Table}; +use crate::{EnvironmentConfig, LumniError, ObjectStoreHandler, Table}; #[derive(Clone)] pub struct LumniHandler { @@ -19,7 +19,7 @@ impl LumniHandler { query: String, skip_hidden: bool, recursive: bool, - ) -> Result, InternalError> { + ) -> Result, LumniError> { let callback = None; let result = self .handler diff --git a/lumni/src/handlers/object_store.rs b/lumni/src/handlers/object_store.rs index c633511b..b721dc39 100644 --- a/lumni/src/handlers/object_store.rs +++ b/lumni/src/handlers/object_store.rs @@ -5,18 +5,18 @@ use std::sync::Arc; use async_trait::async_trait; use log::debug; -use pkcs8::der::asn1::Int; use sqlparser::ast::{Expr, Query, SelectItem, SetExpr, Statement}; use sqlparser::dialect::GenericDialect; use sqlparser::parser::Parser; +use crate::api::error::{LumniError, ResourceError}; use crate::localfs::backend::LocalFsBucket; use crate::s3::backend::S3Bucket; use crate::table::object_store::table_from_list_bucket; use crate::table::{FileObjectTable, Table, TableCallback}; use crate::{ BinaryCallbackWrapper, EnvironmentConfig, FileObjectFilter, IgnoreContents, - InternalError, LumniError, ObjectStoreTable, ParsedUri, UriScheme, + InternalError, ObjectStoreTable, ParsedUri, UriScheme, }; #[derive(Debug, Clone)] @@ -317,7 +317,7 @@ impl ObjectStoreHandler { recursive: bool, ignore_contents: Option, callback: Option>, - ) -> Result, InternalError> { + ) -> Result, LumniError> { let dialect = GenericDialect {}; let parsed = Parser::parse_sql(&dialect, statement); @@ -326,22 +326,31 @@ impl ObjectStoreHandler { if let Some(Statement::Query(query)) = statements.into_iter().next() { - self.handle_select_statement( - &query, - config, - skip_hidden, - recursive, - ignore_contents, - callback, - ) - .await + let result = self + .handle_select_statement( + &query, + config, + skip_hidden, + recursive, + ignore_contents, + callback, + ) + .await; + + match result { + Ok(table) => Ok(table), + Err(InternalError::NotFound(e)) => Err( + LumniError::Resource(ResourceError::NotFound(e)), + ), + Err(e) => Err(LumniError::InternalError(e.to_string())), + } } else { - Err(InternalError::InternalError( + Err(LumniError::NotImplemented( "Unsupported query statement".to_string(), )) } } - Err(_e) => Err(InternalError::InternalError( + Err(_e) => Err(LumniError::ParseError( "Failed to parse query statement".to_string(), )), }