From 80a61eebc6ffd17ddf834815c0a85e0f15f4cb1c Mon Sep 17 00:00:00 2001 From: Priec Date: Mon, 6 Jul 2026 23:13:05 +0200 Subject: [PATCH] snapshoting system for the documents1 --- Cargo.lock | 36 +-- client | 2 +- common/build.rs | 2 + common/proto/document_data.proto | 28 ++ common/src/lib.rs | 3 + common/src/proto/descriptor.bin | Bin 80187 -> 82029 bytes common/src/proto/komp_ac.document_data.rs | 344 ++++++++++++++++++++++ server | 2 +- tui-canvas | 2 +- tui-pages | 2 +- 10 files changed, 393 insertions(+), 28 deletions(-) create mode 100644 common/proto/document_data.proto create mode 100644 common/src/proto/komp_ac.document_data.rs diff --git a/Cargo.lock b/Cargo.lock index 38bd806..8ae516c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "client" -version = "0.8.16" +version = "0.8.18" dependencies = [ "anyhow", "async-trait", @@ -668,7 +668,7 @@ dependencies = [ "serde", "serde_json", "steel-core", - "steel-decimal 1.0.3", + "steel-decimal", "strum", "strum_macros", "time", @@ -721,7 +721,7 @@ dependencies = [ [[package]] name = "common" -version = "0.8.16" +version = "0.8.18" dependencies = [ "prost", "prost-build", @@ -4177,7 +4177,7 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "search" -version = "0.8.16" +version = "0.8.18" dependencies = [ "anyhow", "common", @@ -4272,7 +4272,7 @@ dependencies = [ [[package]] name = "server" -version = "0.8.16" +version = "0.8.18" dependencies = [ "anyhow", "bcrypt", @@ -4299,7 +4299,7 @@ dependencies = [ "serde_json", "sqlx", "steel-core", - "steel-decimal 1.1.0", + "steel-decimal", "steel-derive", "tantivy", "thiserror 2.0.18", @@ -4780,23 +4780,11 @@ dependencies = [ "xdg", ] -[[package]] -name = "steel-decimal" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89e403c72338066141ad32c5f5b85904a43862c602249e22c0d678bccf792c8" -dependencies = [ - "regex", - "rust_decimal", - "rust_decimal_macros", - "steel-core", - "steel-derive", - "thiserror 2.0.18", -] - [[package]] name = "steel-decimal" version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "265dbafa67b48ba44e2c0e2189275b313ae527764b691538091c49c5debc602d" dependencies = [ "regex", "rust_decimal", @@ -5660,7 +5648,7 @@ checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" [[package]] name = "tui-canvas" -version = "0.8.16" +version = "0.8.18" dependencies = [ "anyhow", "arboard", @@ -5679,7 +5667,7 @@ dependencies = [ "toml", "tracing", "tracing-subscriber", - "tui-canvas-validation-core 0.8.16", + "tui-canvas-validation-core 0.8.18", "unicode-width 0.2.2", ] @@ -5696,7 +5684,7 @@ dependencies = [ [[package]] name = "tui-canvas-validation-core" -version = "0.8.16" +version = "0.8.18" dependencies = [ "regex", "serde", @@ -5706,7 +5694,7 @@ dependencies = [ [[package]] name = "tui-pages" -version = "0.8.16" +version = "0.8.18" dependencies = [ "crossterm", "nucleo", diff --git a/client b/client index 76abc12..3bce44d 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 76abc12f073271dd824174d83db264efe589164e +Subproject commit 3bce44d1459072af1c3bdda0b727bd3ae0756c96 diff --git a/common/build.rs b/common/build.rs index 8b62bea..f15ef84 100644 --- a/common/build.rs +++ b/common/build.rs @@ -204,6 +204,7 @@ fn main() -> Result<(), Box> { .compile_protos( &[ "proto/common.proto", + "proto/document_data.proto", "proto/adresar.proto", "proto/auth.proto", "proto/backup.proto", @@ -228,6 +229,7 @@ fn main() -> Result<(), Box> { println!("cargo:rerun-if-changed=build.rs"); for proto in [ "proto/common.proto", + "proto/document_data.proto", "proto/adresar.proto", "proto/auth.proto", "proto/backup.proto", diff --git a/common/proto/document_data.proto b/common/proto/document_data.proto new file mode 100644 index 0000000..463941e --- /dev/null +++ b/common/proto/document_data.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; +package komp_ac.document_data; + +service DocumentDataService { + rpc SaveGeneratedPrintJson(SaveGeneratedPrintJsonRequest) returns (SaveGeneratedPrintJsonResponse); +} + +message SourceRecord { + string profile_name = 1; + string table_name = 2; + int64 table_def_id = 3; + int64 record_id = 4; +} + +message SaveGeneratedPrintJsonRequest { + optional int64 schema_id = 1; + repeated SourceRecord source_records = 2; + optional string template_name = 3; + optional string template_kind = 4; + optional string template_path = 5; + string data_json = 6; +} + +message SaveGeneratedPrintJsonResponse { + int64 document_run_id = 1; + int64 snapshot_id = 2; + int32 version_number = 3; +} diff --git a/common/src/lib.rs b/common/src/lib.rs index 55585ce..3341377 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -16,6 +16,9 @@ pub mod proto { pub mod common { include!("proto/komp_ac.common.rs"); } + pub mod document_data { + include!("proto/komp_ac.document_data.rs"); + } pub mod table_structure { include!("proto/komp_ac.table_structure.rs"); } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index a98bac9cccfeb43178fe220e3eb791fd689c7a1c..f6e89ba97c0a15a9f381b993f937bc814040b5fb 100644 GIT binary patch delta 1787 zcmZ`&%Wm676y*$uGC7p>7)cf-#g5@5hT8%{5ws}KO@Y)wYzGJe`U40?oWOD-QY9&G zS)eG8T?%B~Z)kR1blV@uCuHAl`USmrIKw<(?{w~YaPC8Y{m1_O*?C)#AO7g@L6R*t zE18y25|{COoo8hxMlZ6}I*J$bPsoGUgtyPLO}>z!Tx5Cj=Ix^&t9{-s<7Y2rl*s4N zG70Q`a%6{G)sE%!(?ra;mn%KeOwn##I86@zp?vo|zLJk*D)YFM$?C-R`pdDP6}L63K$vikU~b;(rlNuO5m(+9s1zIW5a zi*=S3QXKMbv-y0JHiHkhO*!18u-V((uZlEY7Z+KHBC3|lO$ikDc;`yy#WG8ybhCOU zb2UyU+}716s(Al*!UxCt5RakTbD3W)7gGF6_|Elj72njm%|5@<`Sp5zP1A30I*A)@ zu%5`--&?#Tm}Sl0yuUlF_BiLXWeH|m4uRix%Ob+I-5K{eYgyD1Hlvcaxq|>G*1Ba7 z1+@FUK{lX=3yfnBw`H|e97E5RJH$Aq;#@jK3j#+}wo6?DLFsxUgCNfhCfWy-M*~d} z2a&PCrP-c0FdW#tow2sT3pt%=ih_;PErY9uP<&y}P@oQ-JEx zue6XrO3$QF(gNg<4Ts9$&>#rueetCZfr<3#T}@F|A=Gc7IH0~?w?-(1ls^0~a94mJ zrGIcorvMO5iVaT@O$bg)G$A-G(S+FOYeK*_sG1aput{N%GH6m5qzsxA1}TFk1%yLt zI(HPRFN07AY(r1z4jixzM>}d&RIsr%gH=@=&KqQ7_fWM)aaRFVC(ZysUZ7VG2!w%K ze+v-g1yl7u0VPlqeV_oqHfd~l3lq0KP~gBe(FaQD*RYQ%ov9~MwSZ~k!_28$UmP3{|s9?F8}}l delta 18 acmaFcz`FYr%Z6gc=A|6lmvS(kFb4oqln2}Z diff --git a/common/src/proto/komp_ac.document_data.rs b/common/src/proto/komp_ac.document_data.rs new file mode 100644 index 0000000..e443d79 --- /dev/null +++ b/common/src/proto/komp_ac.document_data.rs @@ -0,0 +1,344 @@ +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SourceRecord { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub table_name: ::prost::alloc::string::String, + #[prost(int64, tag = "3")] + pub table_def_id: i64, + #[prost(int64, tag = "4")] + pub record_id: i64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SaveGeneratedPrintJsonRequest { + #[prost(int64, optional, tag = "1")] + pub schema_id: ::core::option::Option, + #[prost(message, repeated, tag = "2")] + pub source_records: ::prost::alloc::vec::Vec, + #[prost(string, optional, tag = "3")] + pub template_name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "4")] + pub template_kind: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "5")] + pub template_path: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, tag = "6")] + pub data_json: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SaveGeneratedPrintJsonResponse { + #[prost(int64, tag = "1")] + pub document_run_id: i64, + #[prost(int64, tag = "2")] + pub snapshot_id: i64, + #[prost(int32, tag = "3")] + pub version_number: i32, +} +/// Generated client implementations. +pub mod document_data_service_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct DocumentDataServiceClient { + inner: tonic::client::Grpc, + } + impl DocumentDataServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl DocumentDataServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> DocumentDataServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + DocumentDataServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn save_generated_print_json( + &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.document_data.DocumentDataService/SaveGeneratedPrintJson", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.document_data.DocumentDataService", + "SaveGeneratedPrintJson", + ), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod document_data_service_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with DocumentDataServiceServer. + #[async_trait] + pub trait DocumentDataService: std::marker::Send + std::marker::Sync + 'static { + async fn save_generated_print_json( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct DocumentDataServiceServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl DocumentDataServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for DocumentDataServiceServer + where + T: DocumentDataService, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/komp_ac.document_data.DocumentDataService/SaveGeneratedPrintJson" => { + #[allow(non_camel_case_types)] + struct SaveGeneratedPrintJsonSvc(pub Arc); + impl< + T: DocumentDataService, + > tonic::server::UnaryService + for SaveGeneratedPrintJsonSvc { + type Response = super::SaveGeneratedPrintJsonResponse; + 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 { + ::save_generated_print_json( + &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 = SaveGeneratedPrintJsonSvc(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) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new( + tonic::body::Body::default(), + ); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for DocumentDataServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "komp_ac.document_data.DocumentDataService"; + impl tonic::server::NamedService for DocumentDataServiceServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/server b/server index 4af01c3..f2e6dd5 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 4af01c35f7fec23c338972401397ea11c418120a +Subproject commit f2e6dd5250044ecbb93417fa2cae558cc066c078 diff --git a/tui-canvas b/tui-canvas index 232034d..b7aa87c 160000 --- a/tui-canvas +++ b/tui-canvas @@ -1 +1 @@ -Subproject commit 232034d380c3399d712b734ceeb50e4daf035b49 +Subproject commit b7aa87cf6bb7cd5503288badec6e7decce605702 diff --git a/tui-pages b/tui-pages index 09fb78d..9a7d24c 160000 --- a/tui-pages +++ b/tui-pages @@ -1 +1 @@ -Subproject commit 09fb78d1f3ae311ee458624a631c7df0cb82a0e2 +Subproject commit 9a7d24caf498c40f2b570e38f16db59bb9b4b78d