From 8b14e4d6d69879225b21e428dbc760968eaa5a5e Mon Sep 17 00:00:00 2001 From: Priec Date: Mon, 20 Jul 2026 17:44:54 +0200 Subject: [PATCH] accounting kernel4 --- Cargo.lock | 218 ++++++++++++++++++++++--- client | 2 +- common/proto/accounting.proto | 43 +++-- common/src/proto/descriptor.bin | Bin 125199 -> 125619 bytes common/src/proto/komp_ac.accounting.rs | 153 +++++------------ server | 2 +- tui-pages | 2 +- 7 files changed, 264 insertions(+), 156 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f325f7e..b6f0d73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -119,6 +128,18 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + [[package]] name = "anyhow" version = "1.0.102" @@ -959,6 +980,33 @@ dependencies = [ "phf 0.12.1", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.5.2" @@ -969,6 +1017,31 @@ dependencies = [ "inout", ] +[[package]] +name = "clap" +version = "4.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fb99565819980999fb7b4a1796046a5c949e6d4ff132cf5fadf5a641e20d776" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + [[package]] name = "client" version = "0.8.30" @@ -1265,6 +1338,41 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" +dependencies = [ + "alloca", + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "page_size", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" +dependencies = [ + "cast", + "itertools 0.13.0", +] + [[package]] name = "critical-section" version = "1.2.0" @@ -1571,7 +1679,7 @@ dependencies = [ "datafusion-sql", "futures", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "log", "object_store", "parking_lot", @@ -1600,7 +1708,7 @@ dependencies = [ "datafusion-physical-plan", "datafusion-session", "futures", - "itertools", + "itertools 0.14.0", "log", "object_store", "parking_lot", @@ -1625,7 +1733,7 @@ dependencies = [ "datafusion-physical-expr-common", "datafusion-physical-plan", "futures", - "itertools", + "itertools 0.14.0", "log", "object_store", ] @@ -1644,7 +1752,7 @@ dependencies = [ "half", "hashbrown 0.17.1", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "libc", "log", "object_store", @@ -1686,7 +1794,7 @@ dependencies = [ "datafusion-session", "futures", "glob", - "itertools", + "itertools 0.14.0", "log", "object_store", "parking_lot", @@ -1714,7 +1822,7 @@ dependencies = [ "datafusion-physical-plan", "datafusion-session", "futures", - "itertools", + "itertools 0.14.0", "object_store", "tokio", ] @@ -1810,7 +1918,7 @@ dependencies = [ "datafusion-functions-window-common", "datafusion-physical-expr-common", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "serde_json", "sqlparser", ] @@ -1824,7 +1932,7 @@ dependencies = [ "arrow", "datafusion-common", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", ] [[package]] @@ -1846,7 +1954,7 @@ dependencies = [ "datafusion-macros", "datafusion-physical-expr-common", "hex", - "itertools", + "itertools 0.14.0", "log", "memchr", "num-traits", @@ -1907,7 +2015,7 @@ dependencies = [ "datafusion-macros", "datafusion-physical-expr-common", "hashbrown 0.17.1", - "itertools", + "itertools 0.14.0", "itoa", "log", "memchr", @@ -1980,7 +2088,7 @@ dependencies = [ "datafusion-expr-common", "datafusion-physical-expr", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "log", "regex", "regex-syntax 0.8.11", @@ -2001,7 +2109,7 @@ dependencies = [ "half", "hashbrown 0.17.1", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "parking_lot", "petgraph 0.8.3", "tokio", @@ -2019,7 +2127,7 @@ dependencies = [ "datafusion-functions", "datafusion-physical-expr", "datafusion-physical-expr-common", - "itertools", + "itertools 0.14.0", ] [[package]] @@ -2034,7 +2142,7 @@ dependencies = [ "datafusion-expr-common", "hashbrown 0.17.1", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "parking_lot", "pin-project", ] @@ -2054,7 +2162,7 @@ dependencies = [ "datafusion-physical-expr-common", "datafusion-physical-plan", "datafusion-pruning", - "itertools", + "itertools 0.14.0", ] [[package]] @@ -2082,7 +2190,7 @@ dependencies = [ "half", "hashbrown 0.17.1", "indexmap 2.14.0", - "itertools", + "itertools 0.14.0", "log", "num-traits", "parking_lot", @@ -2161,7 +2269,7 @@ dependencies = [ "futures", "geo-types", "hickory-resolver", - "itertools", + "itertools 0.14.0", "logos", "native-tls", "num-bigint", @@ -3817,6 +3925,15 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -4689,7 +4806,7 @@ dependencies = [ "futures-util", "http", "humantime", - "itertools", + "itertools 0.14.0", "parking_lot", "percent-encoding", "thiserror 2.0.18", @@ -4831,6 +4948,16 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "palette" version = "0.7.6" @@ -5155,6 +5282,34 @@ dependencies = [ "time", ] +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "png" version = "0.18.1" @@ -5386,7 +5541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck 0.5.0", - "itertools", + "itertools 0.14.0", "log", "multimap", "petgraph 0.8.3", @@ -5407,7 +5562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5688,7 +5843,7 @@ dependencies = [ "critical-section", "hashbrown 0.17.1", "indoc", - "itertools", + "itertools 0.14.0", "kasuari", "lru 0.18.0", "palette", @@ -5742,7 +5897,7 @@ dependencies = [ "hashbrown 0.17.1", "indoc", "instability", - "itertools", + "itertools 0.14.0", "line-clipping", "ratatui-core", "serde", @@ -7237,7 +7392,7 @@ dependencies = [ "fnv", "fs4", "htmlescape", - "itertools", + "itertools 0.14.0", "levenshtein_automata", "log", "lru 0.16.4", @@ -7286,7 +7441,7 @@ checksum = "c57166f5bcfd478f370ab8445afb4678dce44801fa5ce5c451aaf8595583c5dc" dependencies = [ "downcast-rs", "fastdivide", - "itertools", + "itertools 0.14.0", "serde", "tantivy-bitpacker", "tantivy-common", @@ -7338,7 +7493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2cfc3ac5164cbadc28965ffb145a8f47582a60ae5897859ad8d4316596c606" dependencies = [ "futures-util", - "itertools", + "itertools 0.14.0", "tantivy-bitpacker", "tantivy-common", "tantivy-fst", @@ -7580,6 +7735,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.11.0" @@ -8015,6 +8180,7 @@ dependencies = [ name = "tui-pages" version = "0.8.30" dependencies = [ + "criterion", "crossterm", "nucleo", "ratatui", @@ -8183,7 +8349,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools", + "itertools 0.14.0", "unicode-segmentation", "unicode-width 0.2.2", ] diff --git a/client b/client index 40c6db6..0a4284f 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 40c6db688dce79f9ad19b976be71a9505ba8cd5f +Subproject commit 0a4284fa0d1f709e3e3fb01d00f76eec17094598 diff --git a/common/proto/accounting.proto b/common/proto/accounting.proto index 1404b62..2671953 100644 --- a/common/proto/accounting.proto +++ b/common/proto/accounting.proto @@ -4,8 +4,9 @@ package komp_ac.accounting; // Mutable informational journals. A journal may contain only debits, only // credits, or any non-zero balance. Balance is reported but never enforced. service Accounting { - // Create an empty journal and return its generated journal_id. - rpc CreateJournal(CreateJournalRequest) returns (Journal); + // Create a journal with its first lines when journal_id is absent, or append + // all supplied lines atomically when journal_id identifies an existing one. + rpc PostJournal(PostJournalRequest) returns (Journal); // Return journal lines and credits-minus-debits informational balance. rpc GetJournal(GetJournalRequest) returns (Journal); @@ -17,9 +18,6 @@ service Accounting { rpc ListUnbalancedJournals(ListUnbalancedJournalsRequest) returns (ListUnbalancedJournalsResponse); - // Append one manual debit or credit line to an existing journal. - rpc AddJournalLine(AddJournalLineRequest) returns (Journal); - // Soft-delete one line while retaining it for audit display. rpc SoftDeleteJournalLine(SoftDeleteJournalLineRequest) returns (Journal); } @@ -34,10 +32,30 @@ enum JournalSide { JOURNAL_SIDE_CREDIT = 2; } -message CreateJournalRequest { +message PostJournalRequest { string profile_name = 1; - string currency = 2; - string description = 3; + + // Absent creates a new journal. Present must identify an existing journal; + // an unknown id is never treated as a request to create one. + optional int64 journal_id = 2; + + // Required when creating. When appending, empty uses the journal currency; + // a supplied value must match it exactly. + string currency = 3; + + // Applied when creating and required to be empty when appending. + string description = 4; + + // At least one line is required. The lines are inserted atomically and the + // journal is allowed to remain unbalanced. + repeated JournalLineInput lines = 5; +} + +message JournalLineInput { + JournalSide side = 1; + string account_code = 2; + string amount = 3; + string description = 4; } message GetJournalRequest { @@ -98,15 +116,6 @@ message ListUnbalancedJournalsResponse { string next_page_token = 3; } -message AddJournalLineRequest { - string profile_name = 1; - int64 journal_id = 2; - JournalSide side = 3; - string account_code = 4; - string amount = 5; - string description = 6; -} - message SoftDeleteJournalLineRequest { string profile_name = 1; int64 journal_id = 2; diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 0a331362ee8d8d603585f16c45b0744fbda894b3..57d2f0b34773387e1a872ed5c329411a808084f0 100644 GIT binary patch delta 5011 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, + /// Required when creating. When appending, empty uses the journal currency; + /// a supplied value must match it exactly. #[prost(string, tag = "3")] + pub currency: ::prost::alloc::string::String, + /// Applied when creating and required to be empty when appending. + #[prost(string, tag = "4")] + pub description: ::prost::alloc::string::String, + /// At least one line is required. The lines are inserted atomically and the + /// journal is allowed to remain unbalanced. + #[prost(message, repeated, tag = "5")] + pub lines: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct JournalLineInput { + #[prost(enumeration = "JournalSide", tag = "1")] + pub side: i32, + #[prost(string, tag = "2")] + pub account_code: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub amount: ::prost::alloc::string::String, + #[prost(string, tag = "4")] pub description: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -87,21 +109,6 @@ pub struct ListUnbalancedJournalsResponse { pub next_page_token: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] -pub struct AddJournalLineRequest { - #[prost(string, tag = "1")] - pub profile_name: ::prost::alloc::string::String, - #[prost(int64, tag = "2")] - pub journal_id: i64, - #[prost(enumeration = "JournalSide", tag = "3")] - pub side: i32, - #[prost(string, tag = "4")] - pub account_code: ::prost::alloc::string::String, - #[prost(string, tag = "5")] - pub amount: ::prost::alloc::string::String, - #[prost(string, tag = "6")] - pub description: ::prost::alloc::string::String, -} -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct SoftDeleteJournalLineRequest { #[prost(string, tag = "1")] pub profile_name: ::prost::alloc::string::String, @@ -283,10 +290,11 @@ pub mod accounting_client { self.inner = self.inner.max_encoding_message_size(limit); self } - /// Create an empty journal and return its generated journal_id. - pub async fn create_journal( + /// Create a journal with its first lines when journal_id is absent, or append + /// all supplied lines atomically when journal_id identifies an existing one. + pub async fn post_journal( &mut self, - request: impl tonic::IntoRequest, + request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { self.inner .ready() @@ -298,13 +306,11 @@ pub mod accounting_client { })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( - "/komp_ac.accounting.Accounting/CreateJournal", + "/komp_ac.accounting.Accounting/PostJournal", ); let mut req = request.into_request(); req.extensions_mut() - .insert( - GrpcMethod::new("komp_ac.accounting.Accounting", "CreateJournal"), - ); + .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "PostJournal")); self.inner.unary(req, path, codec).await } /// Return journal lines and credits-minus-debits informational balance. @@ -389,30 +395,6 @@ pub mod accounting_client { ); self.inner.unary(req, path, codec).await } - /// Append one manual debit or credit line to an existing journal. - pub async fn add_journal_line( - &mut self, - request: impl tonic::IntoRequest, - ) -> std::result::Result, 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.accounting.Accounting/AddJournalLine", - ); - let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("komp_ac.accounting.Accounting", "AddJournalLine"), - ); - self.inner.unary(req, path, codec).await - } /// Soft-delete one line while retaining it for audit display. pub async fn soft_delete_journal_line( &mut self, @@ -455,10 +437,11 @@ pub mod accounting_server { /// Generated trait containing gRPC methods that should be implemented for use with AccountingServer. #[async_trait] pub trait Accounting: std::marker::Send + std::marker::Sync + 'static { - /// Create an empty journal and return its generated journal_id. - async fn create_journal( + /// Create a journal with its first lines when journal_id is absent, or append + /// all supplied lines atomically when journal_id identifies an existing one. + async fn post_journal( &self, - request: tonic::Request, + request: tonic::Request, ) -> std::result::Result, tonic::Status>; /// Return journal lines and credits-minus-debits informational balance. async fn get_journal( @@ -481,11 +464,6 @@ pub mod accounting_server { tonic::Response, tonic::Status, >; - /// Append one manual debit or credit line to an existing journal. - async fn add_journal_line( - &self, - request: tonic::Request, - ) -> std::result::Result, tonic::Status>; /// Soft-delete one line while retaining it for audit display. async fn soft_delete_journal_line( &self, @@ -570,13 +548,13 @@ pub mod accounting_server { } fn call(&mut self, req: http::Request) -> Self::Future { match req.uri().path() { - "/komp_ac.accounting.Accounting/CreateJournal" => { + "/komp_ac.accounting.Accounting/PostJournal" => { #[allow(non_camel_case_types)] - struct CreateJournalSvc(pub Arc); + struct PostJournalSvc(pub Arc); impl< T: Accounting, - > tonic::server::UnaryService - for CreateJournalSvc { + > tonic::server::UnaryService + for PostJournalSvc { type Response = super::Journal; type Future = BoxFuture< tonic::Response, @@ -584,11 +562,11 @@ pub mod accounting_server { >; fn call( &mut self, - request: tonic::Request, + request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::create_journal(&inner, request).await + ::post_journal(&inner, request).await }; Box::pin(fut) } @@ -599,7 +577,7 @@ pub mod accounting_server { let max_encoding_message_size = self.max_encoding_message_size; let inner = self.inner.clone(); let fut = async move { - let method = CreateJournalSvc(inner); + let method = PostJournalSvc(inner); let codec = tonic_prost::ProstCodec::default(); let mut grpc = tonic::server::Grpc::new(codec) .apply_compression_config( @@ -752,51 +730,6 @@ pub mod accounting_server { }; Box::pin(fut) } - "/komp_ac.accounting.Accounting/AddJournalLine" => { - #[allow(non_camel_case_types)] - struct AddJournalLineSvc(pub Arc); - impl< - T: Accounting, - > tonic::server::UnaryService - for AddJournalLineSvc { - type Response = super::Journal; - 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 { - ::add_journal_line(&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 = AddJournalLineSvc(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.accounting.Accounting/SoftDeleteJournalLine" => { #[allow(non_camel_case_types)] struct SoftDeleteJournalLineSvc(pub Arc); diff --git a/server b/server index cf30823..3d145bf 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit cf308231191a434c833d4625a29260c7b9d3cb00 +Subproject commit 3d145bfc4b79c9e96fc25bff21c645d869ef7f3f diff --git a/tui-pages b/tui-pages index 692e1c8..5ff36b0 160000 --- a/tui-pages +++ b/tui-pages @@ -1 +1 @@ -Subproject commit 692e1c83069adc7516d9e1905c3cd078e8e1e1e6 +Subproject commit 5ff36b0aea5d3b7fb5918da8d51997e6f1d4429a