diff --git a/client/.gitignore b/client/.gitignore index 24e2a7a..ca69cc7 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1 +1,2 @@ canvas_config.toml.txt +ui_debug.log diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index 71854a6..b31c18d 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -109,7 +109,9 @@ impl EventHandler { edit_mode_cooldown: false, ideal_cursor_column: 0, input_engine: InputEngine::new(400, 5000), - auth_client: AuthClient::new().await?, + auth_client: AuthClient::with_channel( + grpc_client.channel() + ).await?, grpc_client, login_result_sender, register_result_sender, @@ -398,6 +400,7 @@ impl EventHandler { // Do NOT call the input engine here again. The top-level // process_key call above already ran for this key. // If we are waiting for more leader keys, swallow the key. + info!("Form branch: has_active_seq={}", self.input_engine.has_active_sequence()); if self.input_engine.has_active_sequence() { return Ok(EventOutcome::Ok(String::new())); } diff --git a/client/src/services/auth.rs b/client/src/services/auth.rs index df72ddc..78fb448 100644 --- a/client/src/services/auth.rs +++ b/client/src/services/auth.rs @@ -14,12 +14,20 @@ pub struct AuthClient { impl AuthClient { pub async fn new() -> Result { + // Kept for backward compatibility; opens a new connection. let client = AuthServiceClient::connect("http://[::1]:50051") .await .context("Failed to connect to auth service")?; Ok(Self { client }) } + /// Preferred: reuse an existing Channel (from GrpcClient). + pub async fn with_channel(channel: Channel) -> Result { + Ok(Self { + client: AuthServiceClient::new(channel), + }) + } + /// Login user via gRPC. pub async fn login(&mut self, identifier: String, password: String) -> Result { let request = tonic::Request::new(LoginRequest { identifier, password }); diff --git a/client/src/services/grpc_client.rs b/client/src/services/grpc_client.rs index cabaad1..21c823e 100644 --- a/client/src/services/grpc_client.rs +++ b/client/src/services/grpc_client.rs @@ -2,7 +2,9 @@ use common::proto::komp_ac::common::Empty; use common::proto::komp_ac::table_structure::table_structure_service_client::TableStructureServiceClient; -use common::proto::komp_ac::table_structure::{GetTableStructureRequest, TableStructureResponse}; +use common::proto::komp_ac::table_structure::{ + GetTableStructureRequest, TableStructureResponse, +}; use common::proto::komp_ac::table_definition::{ table_definition_client::TableDefinitionClient, PostTableDefinitionRequest, ProfileTreeResponse, TableDefinitionResponse, @@ -26,11 +28,13 @@ use crate::search::SearchGrpc; use common::proto::komp_ac::search::SearchResponse; use anyhow::{Context, Result}; use std::collections::HashMap; -use tonic::transport::Channel; +use tonic::transport::{Channel, Endpoint}; use prost_types::Value; +use std::time::Duration; #[derive(Clone)] pub struct GrpcClient { + channel: Channel, table_structure_client: TableStructureServiceClient, table_definition_client: TableDefinitionClient, table_script_client: TableScriptClient, @@ -40,7 +44,14 @@ pub struct GrpcClient { impl GrpcClient { pub async fn new() -> Result { - let channel = Channel::from_static("http://[::1]:50051") + let endpoint = Endpoint::from_static("http://[::1]:50051") + .connect_timeout(Duration::from_secs(5)) + .tcp_keepalive(Some(Duration::from_secs(30))) + .keep_alive_while_idle(true) + .http2_keep_alive_interval(Duration::from_secs(15)) + .keep_alive_timeout(Duration::from_secs(5)); + + let channel = endpoint .connect() .await .context("Failed to create gRPC channel")?; @@ -54,6 +65,7 @@ impl GrpcClient { let search_client = SearchGrpc::new(channel.clone()); Ok(Self { + channel, table_structure_client, table_definition_client, table_script_client, @@ -62,6 +74,11 @@ impl GrpcClient { }) } + // Expose the shared channel so other typed clients can reuse it. + pub fn channel(&self) -> Channel { + self.channel.clone() + } + pub async fn get_table_structure( &mut self, profile_name: String, diff --git a/client/src/state/app/state.rs b/client/src/state/app/state.rs index cff0513..da3ca8a 100644 --- a/client/src/state/app/state.rs +++ b/client/src/state/app/state.rs @@ -59,7 +59,6 @@ pub struct AppState { pub ui: UiState, pub form_editor: HashMap>, // key = "profile/table" - #[cfg(feature = "ui-debug")] pub debug_state: Option, } diff --git a/client/ui_debug.log b/client/ui_debug.log deleted file mode 100644 index d7dd3ef..0000000 --- a/client/ui_debug.log +++ /dev/null @@ -1,193 +0,0 @@ -Logger initialized... - INFO Auth data loaded from file. User is auto-logged in. - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from file. User is auto-logged in. - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from file. User is auto-logged in. - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: Action(ExitCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Auth data loaded from file. User is auto-logged in. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false - INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false - INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false - INFO InputEngine.reset_sequence() leader_seq_before=[] - INFO KeySequenceTracker.reset() from [] - INFO KeySequenceTracker.reset() from [] - INFO RAW KEY: code=Char('q') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Char('!') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false - INFO KeySequenceTracker.reset() from [] - INFO ENGINE OUTCOME: PassThrough post_active_seq=false -Logger initialized... - INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" - INFO Schema for 'default.customers' cached. - INFO Initial view set to Form due to auto-login. - INFO RAW KEY: code=Char('c') mods=KeyModifiers(CONTROL) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Char('c') mods=KeyModifiers(0x0) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: PassThrough post_active_seq=false - INFO RAW KEY: code=Char('c') mods=KeyModifiers(CONTROL) pre_active_seq=false - INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false - INFO ENGINE OUTCOME: PassThrough post_active_seq=false