From 52cfbd7070774ab58a3aaa8b59f231d8709dad00 Mon Sep 17 00:00:00 2001 From: Priec Date: Sat, 5 Sep 2026 09:03:54 +0200 Subject: [PATCH] filtered navigation batched --- Cargo.lock | 36 ++++++------- Cargo.toml | 2 +- client | 2 +- common/proto/search.proto | 6 +++ common/src/proto/descriptor.bin | Bin 247928 -> 248415 bytes common/src/proto/komp_ac.search.rs | 82 +++++++++++++++++++++++++++++ komp-app/src/grpc.rs | 22 ++++++++ komp-app/src/search.rs | 7 +++ search/src/lib.rs | 7 +++ server | 2 +- 10 files changed, 145 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 060bc130..a26eee30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ "objc2-foundation", "parking_lot", "percent-encoding", - "windows-sys 0.59.0", + "windows-sys 0.52.0", "x11rb", ] @@ -1161,7 +1161,7 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "client" -version = "0.8.50" +version = "0.8.54" dependencies = [ "anyhow", "async-trait", @@ -1282,7 +1282,7 @@ dependencies = [ [[package]] name = "common" -version = "0.8.50" +version = "0.8.54" dependencies = [ "icu_casemap", "prost", @@ -2574,7 +2574,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2738,7 +2738,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4248,7 +4248,7 @@ dependencies = [ [[package]] name = "komp-app" -version = "0.8.50" +version = "0.8.54" dependencies = [ "anyhow", "common", @@ -4749,7 +4749,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5934,7 +5934,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6618,7 +6618,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6675,7 +6675,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6782,7 +6782,7 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "search" -version = "0.8.50" +version = "0.8.54" dependencies = [ "anyhow", "common", @@ -6970,7 +6970,7 @@ dependencies = [ [[package]] name = "server" -version = "0.8.50" +version = "0.8.54" dependencies = [ "anyhow", "bcrypt", @@ -7959,7 +7959,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -8562,7 +8562,7 @@ checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" [[package]] name = "tui-canvas" -version = "0.8.50" +version = "0.8.54" dependencies = [ "anyhow", "arboard", @@ -8593,7 +8593,7 @@ dependencies = [ [[package]] name = "tui-canvas-validation-core" -version = "0.8.50" +version = "0.8.54" dependencies = [ "regex", "serde", @@ -8603,7 +8603,7 @@ dependencies = [ [[package]] name = "tui-pages" -version = "0.8.50" +version = "0.8.54" dependencies = [ "criterion", "crossterm", @@ -8849,7 +8849,7 @@ dependencies = [ [[package]] name = "ux-config" -version = "0.8.50" +version = "0.8.54" dependencies = [ "toml", ] @@ -9323,7 +9323,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index debc6728..b40f6bab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ resolver = "3" [workspace.package] # TODO: idk how to do the name, fix later # name = "komp_ac" -version = "0.8.50" +version = "0.8.54" edition = "2024" license = "GPL-3.0-or-later" authors = ["Filip Priečinský "] diff --git a/client b/client index 53ec9866..efe9dfe0 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 53ec9866affe26dd539357909ff6c90ff4b6dfd6 +Subproject commit efe9dfe05b12b2fa414c85bbaa3bd38e4d4d2078 diff --git a/common/proto/search.proto b/common/proto/search.proto index 94cbc107..a5cd0335 100644 --- a/common/proto/search.proto +++ b/common/proto/search.proto @@ -3,9 +3,15 @@ syntax = "proto3"; package komp_ac.search; import "common.proto"; +import "tables_data.proto"; service Searcher { rpc Search(SearchRequest) returns (SearchResponse); + // Loads one current row at the zero-based offset using the requested filter + // and ordering. Requires a table and a nonempty filter; limit is ignored. + // Returns live authorized row data and one-based filtered navigation bounds. + // A missing position returns NOT_FOUND. Search and row reads are not a snapshot. + rpc GetFilteredRow(SearchRequest) returns (komp_ac.tables_data.GetTableDataResponse); rpc Count(SearchRequest) returns (SearchCountResponse); } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index d0cd2ec2c5f5858986f971681d717bec85eaab37..c7a4717337cf2e2d3c5d8cb67e5a79e45fa9d5be 100644 GIT binary patch delta 4347 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 delta 3920 zcmYjTNlzR{6z+aq-P6-EY|SzQ44A1KZ`M?tJy=k?j|d74S0hyo{8fs=KkDDncwjlCeO zjdBsbkrR6v8jJFg&j6-OkWUc-RkftZ1M0peG&qJdB_@|qkV_G0VZJ#<33y@G1dgV_ zjaAO6GGQ<&7dB`;m&3@@N16iwQ$DCk5%lu4T`7WGet1sHQLJj5dLu{R)P(g~j##di z?r2H^1Y2!T&=3fEwZ)MXL9h0M+room9nFe~BdiPJ6oFP(-;*NH>aN}p8cZ?W5)(%f z2MsAo*x1;gLh$0Tn;gDEQyQIS9lqia8^aFPQ@SZlqzli$kG&=eS%487o3f25f?QLv zS!gg7s3;~Ev;t^};c+sBY<+43uh3Kw9wIDKo0v#3ic$oXVy-qt5GmHBClEx6ttFic zI@{{Bn_T#)*05EJyOf|8B}oRYgb zSU2gBQUH+a7C9g|c4zh6z?QIHcVm+d!{eZOq}Bl7^;jOK)sr>Vg$=YGsjiAupL5lO zq2SdQ7PXw>F#5@K6##Pml+n!sf@6PJoum+Y{dKYMU>lHXC>_RtgaO1hsRj^e1JV>l zn3O?j3IL89v^36aP?`c8XoGsd5~UQQD>h6Iyel?LF6))BTB7vW(?*F=9Fig{QlJgl z<}ym5ORw`1HM2QVR{;1l;|Lb3(| zZ9+x?h&^Q#e7+_osa2xn-b`8=_hvHNWNe9U&SZ0oR0W<>)GIt6DpPXV_~fGjQ@K== zi#b*5Og(Y9r`9IUS|;u*883}Biu^T7!9p22<^N0?^Kq{75qnk9V!_)bDDJZH^t z!U!;DJ-IJ)sV8Y09Qo$S#OjuF+vJ#m*DYE34Cgpc`gu_R$Z=i@4+O{gtbRDzh7{-H zM8AoEuq{Y!0Ki+YJPvq4N&_2s3o;%Vj%iVr2>=~hB>mDuktG-NW|x3KTf{DL^kJ;- zIG^a~6BWYkPS~jXA9DChGHw6}V@bjQg5#2m8xZuCWZXhN>MoV_FaTg|?#kEzLF8`E zEDR8P#--HLO8_sKhc)D6mSw{Mz+1M5^9jqc;jrQGWqBY&1}oGpk{%9Uv4?x8$coG? z93iq&>PS7Amt5|W%)wiwG%%%+d1ga>x2@U~cz;%7^SHnUmDLvWoQ53pn!FzX5LvUK z@I|*~MRPel zl!?8Kvp6pNAm4&JURVZpqs8myUjdiMgI6WWbxDt6F! zQS_9K!1q+int4t35*1ZGfWMb3R518^SgMo{xUX8QnV-S^3v}M={aj7<(tG$(lo)dZNM#2K^*kSHYm4 zG??cj;^{h-8yo-$obt`p!=p$J@;l9$7aj;Yr#0r^7ziq-U%zXo^LOpuXFr|)_l>)G F@IMbd@O%IO diff --git a/common/src/proto/komp_ac.search.rs b/common/src/proto/komp_ac.search.rs index 57377743..e08b008f 100644 --- a/common/src/proto/komp_ac.search.rs +++ b/common/src/proto/komp_ac.search.rs @@ -351,6 +351,34 @@ pub mod searcher_client { .insert(GrpcMethod::new("komp_ac.search.Searcher", "Search")); self.inner.unary(req, path, codec).await } + /// Loads one current row at the zero-based offset using the requested filter + /// and ordering. Requires a table and a nonempty filter; limit is ignored. + /// Returns live authorized row data and one-based filtered navigation bounds. + /// A missing position returns NOT_FOUND. Search and row reads are not a snapshot. + pub async fn get_filtered_row( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.search.Searcher/GetFilteredRow", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("komp_ac.search.Searcher", "GetFilteredRow")); + self.inner.unary(req, path, codec).await + } pub async fn count( &mut self, request: impl tonic::IntoRequest, @@ -394,6 +422,17 @@ pub mod searcher_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + /// Loads one current row at the zero-based offset using the requested filter + /// and ordering. Requires a table and a nonempty filter; limit is ignored. + /// Returns live authorized row data and one-based filtered navigation bounds. + /// A missing position returns NOT_FOUND. Search and row reads are not a snapshot. + async fn get_filtered_row( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; async fn count( &self, request: tonic::Request, @@ -521,6 +560,49 @@ pub mod searcher_server { }; Box::pin(fut) } + "/komp_ac.search.Searcher/GetFilteredRow" => { + #[allow(non_camel_case_types)] + struct GetFilteredRowSvc(pub Arc); + impl tonic::server::UnaryService + for GetFilteredRowSvc { + type Response = super::super::tables_data::GetTableDataResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_filtered_row(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetFilteredRowSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/komp_ac.search.Searcher/Count" => { #[allow(non_camel_case_types)] struct CountSvc(pub Arc); diff --git a/komp-app/src/grpc.rs b/komp-app/src/grpc.rs index ffc3a431..43615b62 100644 --- a/komp-app/src/grpc.rs +++ b/komp-app/src/grpc.rs @@ -1222,6 +1222,28 @@ impl GrpcClient { self.search_client.search(request).await } + pub async fn get_filtered_table_row( + &mut self, + profile_name: String, + table_name: String, + free_query: String, + must: Vec, + offset: u32, + order: Option, + ) -> Result { + let request = self.authenticated_request(SearchRequest { + profile_name, + table_name: Some(table_name), + free_query, + must, + limit: Some(1), + offset: Some(offset), + order, + version_scope: 0, + })?; + self.search_client.get_filtered_row(request).await + } + pub async fn count_table_rows( &mut self, profile_name: String, diff --git a/komp-app/src/search.rs b/komp-app/src/search.rs index e987be98..0370d916 100644 --- a/komp-app/src/search.rs +++ b/komp-app/src/search.rs @@ -21,6 +21,13 @@ impl SearchGrpc { Ok(self.client.search(request).await?.into_inner()) } + pub async fn get_filtered_row( + &mut self, + request: Request, + ) -> Result { + Ok(self.client.get_filtered_row(request).await?.into_inner()) + } + pub async fn count(&mut self, request: Request) -> Result { Ok(self.client.count(request).await?.into_inner()) } diff --git a/search/src/lib.rs b/search/src/lib.rs index 6cfaf527..575a9ee4 100644 --- a/search/src/lib.rs +++ b/search/src/lib.rs @@ -1981,6 +1981,13 @@ impl Searcher for SearcherService { } + async fn get_filtered_row( + &self, + _request: Request, + ) -> Result, Status> { + Err(Status::unimplemented("Filtered row loading requires the authorized full-text search service")) + } + async fn count( &self, request: Request, diff --git a/server b/server index dcbcf6eb..b085516e 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit dcbcf6ebc920656b38e7ecdf2e43a119bdc9a272 +Subproject commit b085516e17a37f4f8448e7022dd33183860f9775