diff --git a/.github/workflows/clippy_check.yaml b/.github/workflows/clippy_check.yaml index 6010bf2..31e3ec2 100644 --- a/.github/workflows/clippy_check.yaml +++ b/.github/workflows/clippy_check.yaml @@ -1,12 +1,11 @@ -on: push +on: [push, pull_request] + name: Clippy check + jobs: clippy_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - run: rustup component add clippy - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features + - uses: actions/checkout@v4 + - name: Run Clippy + run: cargo clippy --all-targets --all-features diff --git a/.gitignore b/.gitignore index 088ba6b..9b39523 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,8 @@ # will have compiled files and executables /target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock +# Ignore target on subpackages, e.g. proc-macros. +**/target # These are backup files generated by rustfmt **/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..049176f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2529 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "apache-avro" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce74162d8bc5bc22bd746e1849fb33f2c9416d2ce505d1d65ba49f170a207c90" +dependencies = [ + "bigdecimal", + "bon", + "digest", + "log", + "miniz_oxide", + "num-bigint", + "quad-rand", + "rand", + "regex-lite", + "serde", + "serde_bytes", + "serde_json", + "strum", + "strum_macros", + "thiserror 2.0.17", + "uuid", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base_topic_derive" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "bigdecimal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d6867f1565b3aad85681f1015055b087fcfd840d6aeee6eee7f2da317603695" +dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", + "serde", + "serde_json", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bon" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" +dependencies = [ + "bon-macros", + "rustversion", +] + +[[package]] +name = "bon-macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" +dependencies = [ + "darling", + "ident_case", + "prettyplease", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cc" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "colored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b136475da5ef7b6ac596c0e956e37bad51b85b987ff3d5e230e964936736b2" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b44ad32f92b75fb438b04b68547e521a548be8acc339a6dacc4a7121488f53e6" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5be8a7a562d315a5b92a630c30cec6bcf663e6673f00fbb69cca66a6f521b9" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "handle_command" +version = "0.1.0" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "krb5-src" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a04b2f0dfefd7b54af22d22768dc3ab1ed5e55e6d5ff6af3f619069aa17c0ba4" +dependencies = [ + "duct", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "md5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_pipe" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quad-rand" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a651516ddc9168ebd67b24afd085a718be02f8858fe406591b013d101ce2f40" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rdkafka" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f1856d72dbbbea0d2a5b2eaf6af7fb3847ef2746e883b11781446a51dbc85c0" +dependencies = [ + "futures-channel", + "futures-util", + "libc", + "log", + "rdkafka-sys", + "serde", + "serde_derive", + "serde_json", + "slab", + "tokio", +] + +[[package]] +name = "rdkafka-sys" +version = "4.9.0+2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5230dca48bc354d718269f3e4353280e188b610f7af7e2fcf54b7a79d5802872" +dependencies = [ + "cmake", + "libc", + "libz-sys", + "num_enum", + "openssl-sys", + "pkg-config", + "sasl2-sys", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-lite" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" + +[[package]] +name = "reqwest" +version = "0.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salobj" +version = "0.1.0" +dependencies = [ + "apache-avro", + "base_topic_derive", + "chrono", + "clap", + "futures", + "handle_command", + "log", + "md5", + "miniz_oxide", + "num-bigint", + "num-traits", + "rand", + "rdkafka", + "schema_registry_converter", + "serde", + "serde-xml-rs", + "serde_derive", + "serde_json", + "simple_logger", + "tokio", + "whoami", +] + +[[package]] +name = "sasl2-sys" +version = "0.1.22+2.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f2a7f7efd9fc98b3a9033272df10709f5ee3fa0eabbd61a527a3a1ed6bd3c6" +dependencies = [ + "cc", + "duct", + "krb5-src", + "libc", + "pkg-config", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "schema_registry_converter" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a88502ff545fb0501e0418f06e58936667b1bf99c15b4c7cdd769a917de6c3a2" +dependencies = [ + "apache-avro", + "byteorder", + "dashmap", + "futures", + "reqwest", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-xml-rs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53630160a98edebde0123eb4dfd0fce6adff091b2305db3154a9e920206eb510" +dependencies = [ + "log", + "serde", + "thiserror 1.0.69", + "xml-rs", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shared_child" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" +dependencies = [ + "libc", + "sigchld", + "windows-sys 0.60.2", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sigchld" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" +dependencies = [ + "libc", + "os_pipe", + "signal-hook", +] + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291bee647ce7310b0ea721bfd7e0525517b4468eb7c7e15eb8bd774343179702" +dependencies = [ + "colored", + "log", + "time", + "windows-sys 0.61.2", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", + "web-sys", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "xml-rs" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac060176f7020d62c3bcc1cdbcec619d54f48b07ad1963a3f80ce7a0c17755f" diff --git a/Cargo.toml b/Cargo.toml index 126dc92..39d4922 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,25 +6,26 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -apache-avro = "0.14.0" +apache-avro = "0.19.0" base_topic_derive = {path = "base_topic_derive"} handle_command = {path = "handle_command"} chrono = "0.4" clap = { version = "4.1.6", features = ["derive"] } -kafka = "0.9" -num-traits = "0.2" -schema_registry_converter = { version = "3.0.0", features = ["avro"] } -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -serde-xml-rs = "0.3.1" -tokio = { version = "1", features = ["full"] } -whoami = "^1.2" -log = "0.4.17" -simple_logger = "4.0.0" -md5 = "0.7.0" -rand = "0.8.5" -futures = "0.3.29" +num-traits = "0.2.19" +schema_registry_converter = { version = "4.5.0", features = ["avro"] } +serde = "1.0.219" +serde_derive = "1.0.219" +serde_json = "1.0.142" +serde-xml-rs = "0.8.1" +tokio = { version = "1.47.1", features = ["full"] } +whoami = "1.6.1" +log = "0.4.27" +simple_logger = "5.1.0" +md5 = "0.8.0" +rand = "0.9.2" +futures = "0.3.31" +rdkafka = { version = "0.38.0", features = ["cmake-build", "ssl", "gssapi-vendored"]} +miniz_oxide = "0.8.9" [dev-dependencies] num-bigint = "0.4" diff --git a/examples/read_test_topic.rs b/examples/read_test_topic.rs index c2e4d73..2aa24b3 100644 --- a/examples/read_test_topic.rs +++ b/examples/read_test_topic.rs @@ -1,5 +1,4 @@ use apache_avro::types::Value; -use kafka::client::KafkaClient; use std::collections::HashMap; use salobj::{ @@ -7,21 +6,16 @@ use salobj::{ sal_info::SalInfo, topics::{base_topic::BaseTopic, read_topic::ReadTopic}, }; +use simple_logger::SimpleLogger; use std::time::Duration; #[tokio::main] async fn main() { - let mut client = KafkaClient::new(vec!["localhost:9092".to_owned()]); - client.set_client_id("kafka-rust-console-producer".into()); - client.load_metadata_all().unwrap(); - + SimpleLogger::new().init().unwrap(); + log::set_max_level(log::LevelFilter::Debug); let domain = domain::Domain::new(); let component = "Test"; - let topic = "logevent_heartbeat"; - - let _ = client.load_metadata(&[topic]); - - assert!(client.topics().contains(&topic)); + let topic = "command_start"; let sal_info = SalInfo::new(component, 1).unwrap(); let max_history: usize = 10; @@ -42,10 +36,7 @@ async fn main() { if let Some(Value::Record(new_data)) = topic_reader.pop_back(false, Duration::from_secs(1)).await { - let data_dict: HashMap = new_data - .into_iter() - .map(|(field, value)| (field, value)) - .collect(); + let data_dict: HashMap = new_data.into_iter().collect(); let private_snd_stamp = data_dict.get("private_seqNum").unwrap(); println!("\t{private_snd_stamp:?}"); } else { diff --git a/examples/write_test_topic.rs b/examples/write_test_topic.rs index 5e0d897..8426696 100644 --- a/examples/write_test_topic.rs +++ b/examples/write_test_topic.rs @@ -1,8 +1,4 @@ use apache_avro::types::Value; -use kafka::{ - client::KafkaClient, - producer::{Producer, RequiredAcks}, -}; use salobj::{ domain, sal_info::SalInfo, @@ -12,13 +8,13 @@ use tokio::time; #[tokio::main] async fn main() { - let mut domain = domain::Domain::new(); + let domain = domain::Domain::new(); let component = "Test"; let topic = "logevent_heartbeat"; let sal_info = SalInfo::new(component, 1).unwrap(); - if let Err(error) = domain.register_topics(&sal_info.get_topics_name()) { + if let Err(error) = domain.register_topics(&sal_info.get_topics_name()).await { log::warn!("Failed to register topics: {error:?}. Continuing..."); } sal_info.register_schema().await; @@ -26,7 +22,7 @@ async fn main() { let mut topic_writer = WriteTopic::new(topic, &sal_info, &domain); let schema = sal_info - .get_topic_info(&topic) + .get_topic_info(topic) .unwrap() .get_schema() .unwrap(); diff --git a/src/bin/run_test_csc.rs b/src/bin/run_test_csc.rs index edbb36d..c3d5d91 100644 --- a/src/bin/run_test_csc.rs +++ b/src/bin/run_test_csc.rs @@ -39,7 +39,7 @@ async fn main() { log::info!("Running Test CSC with index {}.", cli.get_component_index(),); - let mut test_csc = TestCSC::new(cli.get_component_index()).unwrap(); + let mut test_csc = TestCSC::new(cli.get_component_index()).await.unwrap(); log::info!("Starting CSC."); test_csc.start().await; diff --git a/src/bin/set_summary_state.rs b/src/bin/set_summary_state.rs index 7d1e0c4..da5b0d4 100644 --- a/src/bin/set_summary_state.rs +++ b/src/bin/set_summary_state.rs @@ -84,6 +84,7 @@ async fn main() { &cli.get_component_name(), cli.get_component_index(), ) + .await .unwrap(); let timeout = Duration::from_secs(10); diff --git a/src/controller.rs b/src/controller.rs index 4ea5308..b8c4a92 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -25,17 +25,19 @@ pub struct Controller<'a> { } impl<'a> Controller<'a> { - pub fn new( + pub async fn new( domain: &mut domain::Domain, name: &str, index: isize, ) -> SalObjResult> { let sal_info = sal_info::SalInfo::new(name, index)?; - if let Err(error) = domain.register_topics(&sal_info.get_topics_name()) { + if let Err(error) = domain.register_topics(&sal_info.get_topics_name()).await { log::warn!("Failed to register topics: {error:?}. Continuing..."); } + sal_info.register_schema().await; + let commands: ControllerCommandSet = sal_info .get_command_names() .into_iter() @@ -149,12 +151,13 @@ impl<'a> Controller<'a> { #[cfg(test)] mod tests { use super::*; - #[test] - fn test_create() { + + #[tokio::test] + async fn test_create() { let mut domain = domain::Domain::new(); let name = "Test"; let index = 1; - let controller = Controller::new(&mut domain, name, index); + let controller = Controller::new(&mut domain, name, index).await; assert!(controller.is_ok()) } diff --git a/src/csc/test_csc/csc.rs b/src/csc/test_csc/csc.rs index 8c306a9..b82c239 100644 --- a/src/csc/test_csc/csc.rs +++ b/src/csc/test_csc/csc.rs @@ -75,9 +75,9 @@ pub struct TestCSC<'a> { } impl<'a> TestCSC<'a> { - pub fn new(index: isize) -> SalObjResult> { + pub async fn new(index: isize) -> SalObjResult> { let mut domain = Domain::new(); - let controller = Controller::new(&mut domain, "Test", index)?; + let controller = Controller::new(&mut domain, "Test", index).await?; let (command_sender, command_receiver): ( mpsc::Sender, mpsc::Receiver, @@ -115,15 +115,6 @@ impl<'a> TestCSC<'a> { let sal_info = SalInfo::new("Test", self.index).unwrap(); - log::debug!("Registering schema."); - sal_info.register_schema().await; - - log::debug!("Registering topics: {:?}.", sal_info.get_topics_name()); - - if let Err(error) = self.domain.register_topics(&sal_info.get_topics_name()) { - log::warn!("Failed to register topics: {error:?}. Continuing..."); - } - let mut heartbeat_writer = WriteTopic::new("logevent_heartbeat", &sal_info, &self.domain); let heartbeat_task = task::spawn(async move { @@ -163,11 +154,12 @@ impl<'a> TestCSC<'a> { task::spawn(async move { loop { if let Ok(command_data) = controller_command.process_command().await { + log::debug!("Received {command} with: {command_data:?}"); let ack_sender = controller_command_ack_sender.clone(); let _ = command_sender .send(( CmdData { - name: command.to_owned(), + name: command.to_string(), data: command_data, }, ack_sender, @@ -425,27 +417,32 @@ impl<'a> TestCSC<'a> { ack_channel, )); } - let original_scalars = scalars.clone(); - if self + match self .controller .write_event("logevent_scalars", &scalars) .await - .is_ok() { - log::debug!("setScalars sent event, updating telemetry."); - let _ = self.telemetry_sender.send(TelemetryPayload { - name: "scalars".to_owned(), - data: TestTelemetry::Scalars(scalars.clone()), - }); - log::debug!("setScalars telemetry sent, command completed."); + Ok(_) => { + log::debug!("setScalars sent event, updating telemetry."); + let _ = self.telemetry_sender.send(TelemetryPayload { + name: "scalars".to_owned(), + data: TestTelemetry::Scalars(scalars.clone()), + }); + log::debug!("setScalars telemetry sent, command completed."); - Ok((CommandAck::make_complete(original_scalars), ack_channel)) - } else { - log::debug!("setScalars command failed."); - Ok(( - CommandAck::make_failed(original_scalars, 1, "Failed to parse event data"), - ack_channel, - )) + Ok((CommandAck::make_complete(scalars), ack_channel)) + } + Err(error) => { + log::debug!("setScalars command failed."); + Ok(( + CommandAck::make_failed( + scalars, + 1, + &format!("Failed to parse event data: {error}."), + ), + ack_channel, + )) + } } } else { log::error!("Cannot parse data."); diff --git a/src/csc/test_csc/topics/scalars.rs b/src/csc/test_csc/topics/scalars.rs index d0ae6c4..eb4497e 100644 --- a/src/csc/test_csc/topics/scalars.rs +++ b/src/csc/test_csc/topics/scalars.rs @@ -27,11 +27,13 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, Codec, Schema, Writer, }; + use miniz_oxide::deflate::CompressionLevel; use std::collections::HashMap; #[test] @@ -93,7 +95,11 @@ mod tests { // topic_record.put("private_kafkaStamp", Value::Union(0, Box::new(Value::Double(1.234)))); // topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new(CompressionLevel::NoCompression)), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/domain.rs b/src/domain.rs index d836d89..aefdbc8 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -6,21 +6,22 @@ //! When developing applications with salobj you will want to reduce the number //! of [Domain] instances, ideally having only one per application. -use kafka::client::KafkaClient; -use kafka::error::Error as KafkaError; +use rdkafka::{ + admin::{AdminClient, AdminOptions, NewTopic}, + client::DefaultClientContext, + error::KafkaError, + ClientConfig, +}; use std::env; -use std::{process, thread, time::Duration}; +use std::process; use whoami::{self, fallible}; -const MAX_ITER_LOAD_METADATA: u8 = 5; -const POOL_CLIENT_WAIT_TIME: Duration = Duration::from_millis(500); const DEFAULT_LSST_KAFKA_CLIENT_ADDR: &str = "localhost:9092"; const DEFAULT_LSST_SCHEMA_REGISTRY_URL: &str = "http://127.0.0.1:8081"; pub struct Domain { origin: u32, identity: Option, - kafka_client: KafkaClient, } impl Default for Domain { @@ -35,7 +36,6 @@ impl Domain { Domain { origin: process::id(), identity: None, - kafka_client: KafkaClient::new(Domain::get_client_hosts()), } } @@ -58,36 +58,49 @@ impl Domain { } /// Register topics. - pub fn register_topics>(&mut self, topics: &[T]) -> Result<(), KafkaError> { - for _ in 0..MAX_ITER_LOAD_METADATA { - let result = self.kafka_client.load_metadata(topics); - match result { - Ok(_) => { - if topics - .iter() - .filter_map(|topic| { - if self - .kafka_client - .topics() - .partitions(topic.as_ref()) - .map(|p| p.len()) - .unwrap_or(0) - > 0 - { - None - } else { - Some(true) - } - }) - .next() - .is_none() - { - return Ok(()); + pub async fn register_topics>(&self, topics: &[T]) -> Result<(), KafkaError> { + let timeout = std::time::Duration::from_secs(5); + let client_config = Domain::get_admin_client_configuration(); + let admin_client: AdminClient = client_config.create()?; + let admin_options = AdminOptions::new(); + + let missing_topics: Vec = topics + .iter() + .filter_map(|topic| { + if let Ok(metadata) = admin_client + .inner() + .fetch_metadata(Some(topic.as_ref()), timeout) + { + if metadata.topics()[0].error().is_some() { + Some(topic.as_ref().to_string()) + } else { + None } + } else { + Some(topic.as_ref().to_string()) + } + }) + .collect(); + + for topic_name in missing_topics.into_iter() { + match admin_client + .create_topics( + &[NewTopic::new( + &topic_name, + 1, + rdkafka::admin::TopicReplication::Fixed(1), + )], + &admin_options, + ) + .await + { + Ok(topic_result) => { + log::info!("Topic {topic_name} created successfully: {topic_result:?}"); + } + Err(error) => { + log::error!("Failed to create topic {topic_name}: {error:?}"); } - Err(err) => return Err(err), } - thread::sleep(POOL_CLIENT_WAIT_TIME); } Ok(()) } @@ -99,7 +112,7 @@ impl Domain { /// default is only good enough for local testing. For production this /// environment variable should be set. pub fn get_client_hosts() -> Vec { - match env::var("LSST_KAFKA_CLIENT_ADDR") { + match env::var("LSST_KAFKA_BROKER_ADDR") { Ok(kafka_client_addr) => kafka_client_addr .split(',') .map(|addr| addr.to_owned()) @@ -120,6 +133,26 @@ impl Domain { Err(_) => DEFAULT_LSST_SCHEMA_REGISTRY_URL.to_owned(), } } + + pub fn get_producer_configuration() -> ClientConfig { + ClientConfig::new() + .set("bootstrap.servers", Domain::get_client_hosts()[0].clone()) + .clone() + } + + pub fn get_consumer_configuration(&self) -> ClientConfig { + ClientConfig::new() + .set("bootstrap.servers", Domain::get_client_hosts()[0].clone()) + .set("allow.auto.create.topics", "false") + .set("auto.offset.reset", "earliest") + .clone() + } + + pub fn get_admin_client_configuration() -> ClientConfig { + ClientConfig::new() + .set("bootstrap.servers", Domain::get_client_hosts()[0].clone()) + .clone() + } } #[cfg(test)] @@ -158,7 +191,7 @@ mod tests { #[test] fn get_client_hosts_env_set() { env::set_var( - "LSST_KAFKA_CLIENT_ADDR", + "LSST_KAFKA_BROKER_ADDR", "kafka_client_1:9092,kafka_client_2:9092", ); @@ -177,7 +210,7 @@ mod tests { let default_value = DEFAULT_LSST_SCHEMA_REGISTRY_URL.to_owned(); - env::remove_var("LSST_KAFKA_CLIENT_ADDR"); + env::remove_var("LSST_KAFKA_BROKER_ADDR"); assert_eq!(Domain::get_schema_registry_url(), default_value) } diff --git a/src/generics/configuration_applied.rs b/src/generics/configuration_applied.rs index 6062e9a..3fbb034 100644 --- a/src/generics/configuration_applied.rs +++ b/src/generics/configuration_applied.rs @@ -38,6 +38,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -56,7 +57,7 @@ mod tests { .collect(); let topic_schema = avro_schema.get("logevent_configurationApplied").unwrap(); - let mut topic_record = Record::new(&topic_schema).unwrap(); + let mut topic_record = Record::new(topic_schema).unwrap(); topic_record.put( "configurations", @@ -76,11 +77,17 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); - let reader = Reader::with_schema(&topic_schema, &input[..]).unwrap(); + let reader = Reader::with_schema(topic_schema, &input[..]).unwrap(); for record in reader { let topic = from_value::(&record.unwrap()).unwrap(); diff --git a/src/generics/configurations_available.rs b/src/generics/configurations_available.rs index 4d63efb..ab7d5d3 100644 --- a/src/generics/configurations_available.rs +++ b/src/generics/configurations_available.rs @@ -33,6 +33,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -73,7 +74,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/disable.rs b/src/generics/disable.rs index 14d1be6..c3ad788 100644 --- a/src/generics/disable.rs +++ b/src/generics/disable.rs @@ -12,6 +12,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -42,7 +43,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/enable.rs b/src/generics/enable.rs index 74f688a..4329c53 100644 --- a/src/generics/enable.rs +++ b/src/generics/enable.rs @@ -12,6 +12,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -42,7 +43,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/enter_control.rs b/src/generics/enter_control.rs index 4d7d7cd..07e0920 100644 --- a/src/generics/enter_control.rs +++ b/src/generics/enter_control.rs @@ -12,6 +12,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -42,7 +43,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/error_code.rs b/src/generics/error_code.rs index aa394c8..e9c6817 100644 --- a/src/generics/error_code.rs +++ b/src/generics/error_code.rs @@ -30,6 +30,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -64,7 +65,13 @@ mod tests { topic_record.put("private_rcvStamp", Value::Double(4.321)); topic_record.put("salIndex", Value::Int(1)); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/exit_control.rs b/src/generics/exit_control.rs index 665e07b..8ed828a 100644 --- a/src/generics/exit_control.rs +++ b/src/generics/exit_control.rs @@ -12,6 +12,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -42,7 +43,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/heartbeat.rs b/src/generics/heartbeat.rs index b1ed4d4..5770635 100644 --- a/src/generics/heartbeat.rs +++ b/src/generics/heartbeat.rs @@ -20,6 +20,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -51,7 +52,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/large_file_object_available.rs b/src/generics/large_file_object_available.rs index 60a36fd..0e7ab5c 100644 --- a/src/generics/large_file_object_available.rs +++ b/src/generics/large_file_object_available.rs @@ -47,6 +47,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -87,7 +88,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/log_level.rs b/src/generics/log_level.rs index 97c6159..0810270 100644 --- a/src/generics/log_level.rs +++ b/src/generics/log_level.rs @@ -24,6 +24,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -56,7 +57,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/log_message.rs b/src/generics/log_message.rs index 5b90bc5..86d62cc 100644 --- a/src/generics/log_message.rs +++ b/src/generics/log_message.rs @@ -55,6 +55,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -95,7 +96,13 @@ mod tests { record.put("private_kafkaStamp", Value::Double(1.234)); record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/set_log_level.rs b/src/generics/set_log_level.rs index 9582f4d..96e9e9d 100644 --- a/src/generics/set_log_level.rs +++ b/src/generics/set_log_level.rs @@ -24,6 +24,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -57,7 +58,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/simulation_mode.rs b/src/generics/simulation_mode.rs index f3af1eb..0200a44 100644 --- a/src/generics/simulation_mode.rs +++ b/src/generics/simulation_mode.rs @@ -20,6 +20,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -51,7 +52,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/software_version.rs b/src/generics/software_version.rs index 5908d44..9229822 100644 --- a/src/generics/software_version.rs +++ b/src/generics/software_version.rs @@ -41,6 +41,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -77,7 +78,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/standby.rs b/src/generics/standby.rs index 1199890..bdcca1b 100644 --- a/src/generics/standby.rs +++ b/src/generics/standby.rs @@ -12,6 +12,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -42,7 +43,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/start.rs b/src/generics/start.rs index 651d6fc..b423c0d 100644 --- a/src/generics/start.rs +++ b/src/generics/start.rs @@ -21,6 +21,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -56,7 +57,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/status_code.rs b/src/generics/status_code.rs index 397d931..6ac3034 100644 --- a/src/generics/status_code.rs +++ b/src/generics/status_code.rs @@ -20,6 +20,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -52,7 +53,13 @@ mod tests { topic_record.put("private_kafkaStamp", Value::Double(1.234)); topic_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&topic_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &topic_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(topic_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/generics/summary_state.rs b/src/generics/summary_state.rs index 3c2369c..221a499 100644 --- a/src/generics/summary_state.rs +++ b/src/generics/summary_state.rs @@ -35,6 +35,7 @@ mod tests { use super::*; use crate::component_info::ComponentInfo; use apache_avro::from_value; + use apache_avro::DeflateSettings; use apache_avro::Reader; use apache_avro::{ types::{Record, Value}, @@ -66,7 +67,13 @@ mod tests { summary_state_record.put("private_kafkaStamp", Value::Double(1.234)); summary_state_record.put("private_revCode", Value::String("xyz".to_string())); - let mut writer = Writer::with_codec(&summary_state_schema, Vec::new(), Codec::Deflate); + let mut writer = Writer::with_codec( + &summary_state_schema, + Vec::new(), + Codec::Deflate(DeflateSettings::new( + miniz_oxide::deflate::CompressionLevel::NoCompression, + )), + ); writer.append(summary_state_record).unwrap(); let input = writer.into_inner().unwrap(); diff --git a/src/remote.rs b/src/remote.rs index 3ea4c15..ba4b175 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -36,7 +36,7 @@ pub struct Remote<'b> { } impl<'b> Remote<'b> { - pub fn new( + pub async fn new( domain: &mut domain::Domain, name: &str, index: isize, @@ -56,7 +56,7 @@ impl<'b> Remote<'b> { let sal_info = sal_info::SalInfo::new(name, index)?; - if let Err(error) = domain.register_topics(&sal_info.get_topics_name()) { + if let Err(error) = domain.register_topics(&sal_info.get_topics_name()).await { log::warn!("Failed to register topics: {error:?}. Continuing..."); } @@ -105,12 +105,12 @@ impl<'b> Remote<'b> { }) } - pub fn from_name_index( + pub async fn from_name_index( domain: &mut domain::Domain, name: &str, index: isize, ) -> SalObjResult> { - Remote::new(domain, name, index, false, Vec::new(), Vec::new(), 1) + Remote::new(domain, name, index, false, Vec::new(), Vec::new(), 1).await } /// Get component name. @@ -245,22 +245,27 @@ impl<'b> Remote<'b> { #[cfg(test)] mod tests { use super::*; - #[test] - fn test_get_name() { + + #[tokio::test] + async fn test_get_name() { let mut domain = domain::Domain::new(); let name = "Test"; let index = 1; - let remote = Remote::from_name_index(&mut domain, name, index).unwrap(); + let remote = Remote::from_name_index(&mut domain, name, index) + .await + .unwrap(); assert_eq!("Test", remote.get_name()) } - #[test] - fn test_get_index() { + #[tokio::test] + async fn test_get_index() { let mut domain = domain::Domain::new(); let name = "Test"; let index = 1; - let remote = Remote::from_name_index(&mut domain, name, index).unwrap(); + let remote = Remote::from_name_index(&mut domain, name, index) + .await + .unwrap(); assert_eq!(index, remote.get_index()); } diff --git a/src/topics/read_topic.rs b/src/topics/read_topic.rs index 7d4ef64..2de4aad 100644 --- a/src/topics/read_topic.rs +++ b/src/topics/read_topic.rs @@ -1,3 +1,4 @@ +use rand::Rng; use std::time::{Duration, Instant}; use crate::{ @@ -7,23 +8,23 @@ use crate::{ topics::base_topic::BaseTopic, }; use apache_avro::types::Value; -use kafka::{ - consumer::{Consumer, FetchOffset, GroupOffsetStorage}, - error::Result as KafkaResult, +use rdkafka::{ + config::FromClientConfig, + consumer::{Consumer, StreamConsumer}, + error::KafkaResult, + message::Message, }; use schema_registry_converter::async_impl::avro::AvroDecoder; use std::collections::VecDeque; -use tokio::time::sleep; // Default value for the ``queue_len`` constructor argument. const DEFAULT_QUEUE_LEN: usize = 100; -const POOL_WAIT_TIME: std::time::Duration = std::time::Duration::from_micros(50); - /// Base struct for reading a topic. pub struct ReadTopic<'a> { /// The name of the topic. topic_name: String, + subject_name: String, /// The name of the topic in the data cloud. topic_publish_name: String, /// Maximum number of historical items to read when starting up. @@ -43,7 +44,7 @@ pub struct ReadTopic<'a> { /// Data queue. data_queue: VecDeque, /// Topic consumer. - consumer: KafkaResult, + consumer: KafkaResult, decoder: AvroDecoder<'a>, sal_index: Option, } @@ -63,26 +64,53 @@ impl<'a> ReadTopic<'a> { ) } - let fetch_offset = if max_history > 0 { - FetchOffset::Earliest - } else { - FetchOffset::Latest + let sal_index = sal_info.get_optional_index(); + + let consumer_configuration = { + let mut consumer_configuration = domain.get_consumer_configuration(); + let mut rng = rand::rng(); + let random_number: u32 = rng.random(); + consumer_configuration.set( + "group.id", + format!( + "{}.{}.{}.{}", + sal_info.get_name(), + topic_name, + domain.get_origin(), + random_number + ), + ); + if max_history == 0 { + consumer_configuration.set("auto.offset.reset", "latest"); + } + consumer_configuration }; - let sal_index = sal_info.get_optional_index(); + let consumer = StreamConsumer::from_config(&consumer_configuration); + + let subject_name = sal_info.make_schema_registry_topic_name(topic_name); + + if let Ok(consumer) = &consumer { + if let Err(error) = consumer.subscribe(&[&subject_name]) { + log::error!("Failed to subscribe to topic {subject_name}: {error}."); + } else { + log::trace!("Subscribed to topic {subject_name}. Consumer configuration {consumer_configuration:?}."); + } + match consumer.fetch_metadata(Some(&subject_name), Duration::new(5, 0)) { + Ok(metadata) => log::trace!("{subject_name} metadata {metadata:?}"), + Err(err) => log::error!("Failed to retrieve {subject_name} metadata: {err}."), + } + let watermarks = consumer.fetch_watermarks(&subject_name, 0, Duration::new(5, 0)); + log::debug!("{} watermarks: {:?}", topic_name, watermarks); + } ReadTopic { topic_name: topic_name.to_owned(), + subject_name, topic_publish_name: sal_info.make_schema_registry_topic_name(topic_name), max_history, data_queue: VecDeque::with_capacity(DEFAULT_QUEUE_LEN), - consumer: Consumer::from_hosts(Domain::get_client_hosts()) - .with_topic(sal_info.make_schema_registry_topic_name(topic_name)) - .with_fallback_offset(fetch_offset) - .with_group(format!("{}", domain.get_origin())) - .with_fetch_max_wait_time(Duration::from_millis(1)) - .with_offset_storage(GroupOffsetStorage::Kafka) - .create(), + consumer, current_data: None, decoder: SalInfo::make_decoder(), sal_index, @@ -168,7 +196,7 @@ impl<'a> ReadTopic<'a> { match self.pool(timeout).await { Ok(n_messages) => { let duration = start.elapsed(); - log::trace!( + log::debug!( "pop_front {} took {duration:?} to pool data. Got {n_messages} messages.", self.topic_name ); @@ -193,63 +221,47 @@ impl<'a> ReadTopic<'a> { async fn pool(&mut self, timeout: std::time::Duration) -> SalObjResult { match &mut self.consumer { Ok(consumer) => { - let timer_task = tokio::spawn(async move { - sleep(timeout).await; - }); - - let mut n_messages = 0; - - while !timer_task.is_finished() { - let start = Instant::now(); - match consumer.poll() { - Ok(messages) => { - let duration = start.elapsed(); - - let no_data = messages.is_empty(); - log::trace!( - "pool {} took {duration:?} to consume data, is empty? {no_data}.", - self.topic_name - ); - for ms in messages.iter() { - for m in ms.messages() { - let start = Instant::now(); - match self.decoder.decode(Some(m.value)).await { - Ok(data) => { - let duration = start.elapsed(); - log::trace!( - "pool {} took {duration:?} to decode data.", - self.topic_name - ); - let data_value = data.value; - if !ReadTopic::same_index(&self.sal_index, &data_value) - { - continue; - } - self.current_data = Some(data_value.clone()); - self.data_queue.push_back(data_value); - n_messages += 1; - } - Err(error) => return Err(SalObjError::from_error(error)), - }; - } - if let Err(error) = consumer.consume_messageset(ms) { - return Err(SalObjError::from_error(error)); + // for some reason I need to have this call for watermarks here or + // calling recv bellow will block and not make any progress. + let _ = consumer.fetch_watermarks(&self.subject_name, 0, timeout); + loop { + match consumer.recv().await { + Ok(message) => match self.decoder.decode(message.payload()).await { + Ok(data) => { + let data_value = data.value; + if !ReadTopic::same_index(&self.sal_index, &data_value) { + log::debug!( + "Received data for a different index for {}. Expected {:?}, received {:?}. Discarding.", + self.topic_name, + self.sal_index, + data_value, + ); + continue; } + self.current_data = Some(data_value.clone()); + self.data_queue.push_back(data_value); + log::trace!("Received data ok for {}!", self.topic_name); + return Ok(1); } - if n_messages > 0 && no_data { - timer_task.abort(); - return Ok(n_messages); + Err(error) => { + log::error!( + "Error decoding message for {}: {error}", + self.topic_name + ); + return Err(SalObjError::from_error(error)); } - sleep(POOL_WAIT_TIME).await; - } + }, Err(error) => { + log::error!("Error receiving message for {}: {error}", self.topic_name); return Err(SalObjError::from_error(error)); } } } - Ok(0) } - Err(error) => Err(SalObjError::new(&error.to_string())), + Err(error) => { + log::error!("Error with consumer for {}: {error}", self.topic_name); + Err(SalObjError::new(&error.to_string())) + } } } @@ -297,7 +309,7 @@ mod tests { #[tokio::test] async fn get_no_data() { - let mut domain = Domain::new(); + let domain = Domain::new(); let sal_info = SalInfo::new("Test", 1).unwrap(); let topics: Vec = sal_info @@ -311,7 +323,7 @@ mod tests { .collect(); println!("Loading metadata for topics: {topics:?}"); - domain.register_topics(&topics).unwrap(); + domain.register_topics(&topics).await.unwrap(); sal_info.register_schema().await; let read_topic = ReadTopic::new("scalars", &sal_info, &domain, 0); diff --git a/src/topics/remote_command.rs b/src/topics/remote_command.rs index 18fa3a2..8801b79 100644 --- a/src/topics/remote_command.rs +++ b/src/topics/remote_command.rs @@ -132,7 +132,10 @@ impl<'a> RemoteCommand<'a> { let identity = self.command_writer.get_identity(); let origin = self.command_writer.get_origin(); self.ack_reader.flush(); - log::debug!("Sending command..."); + log::debug!( + "Sending command {}...", + self.command_writer.get_topic_name() + ); match self.command_writer.write_typed(data).await { Ok(seq_num) => { log::debug!("Wainting ack for seq_num {seq_num}."); diff --git a/src/topics/topic_info.rs b/src/topics/topic_info.rs index edeab39..6a532e5 100644 --- a/src/topics/topic_info.rs +++ b/src/topics/topic_info.rs @@ -146,8 +146,6 @@ impl TopicInfo { #[cfg(test)] mod tests { - use super::*; - use apache_avro::{types::Record, Schema}; use std::collections::HashSet; fn get_expected_ackcmd_fields(indexed: bool) -> HashSet { diff --git a/src/topics/write_topic.rs b/src/topics/write_topic.rs index 6882ef6..0024eef 100644 --- a/src/topics/write_topic.rs +++ b/src/topics/write_topic.rs @@ -12,13 +12,18 @@ use crate::{ utils::types::WriteTopicResult, }; use chrono::Utc; -use kafka::{error::Result as KafkaResult, producer}; use rand::Rng; +use rdkafka::{ + config::FromClientConfig, + error::KafkaResult, + producer::{future_producer::FutureProducer, FutureRecord}, + util::Timeout, +}; use schema_registry_converter::{ async_impl::avro::AvroEncoder, schema_registry_common::SubjectNameStrategy, }; use serde::Serialize; -use std::{fmt::Debug, time::Duration}; +use std::fmt::Debug; /// Base struct for writing a topic. pub struct WriteTopic<'a> { @@ -33,7 +38,7 @@ pub struct WriteTopic<'a> { /// A string identifying the instance. identity: String, /// Data producer. - producer: KafkaResult, + producer: KafkaResult, /// Sequence number of the written samples. This number is incremented /// every time a sample is published. seq_num: i32, @@ -46,8 +51,8 @@ impl BaseTopic for WriteTopic<'_> {} impl<'a> WriteTopic<'a> { pub fn new(topic_name: &str, sal_info: &SalInfo, domain: &Domain) -> WriteTopic<'a> { - let mut rng = rand::thread_rng(); - let seq_num: i32 = rng.gen::().abs(); + let mut rng = rand::rng(); + let seq_num: i32 = rng.random::().abs(); // FIXME: This needs to be properly handled! let schema = sal_info .get_topic_info(topic_name) @@ -61,10 +66,7 @@ impl<'a> WriteTopic<'a> { indexed: sal_info.is_indexed(), origin: domain.get_origin() as i32, identity: domain.get_identity(), - producer: producer::Producer::from_hosts(Domain::get_client_hosts()) - .with_ack_timeout(Duration::from_secs(1)) - .with_required_acks(producer::RequiredAcks::One) - .create(), + producer: FutureProducer::from_config(&Domain::get_producer_configuration()), seq_num, encoder: SalInfo::make_encoder(), schema_registry_topic_name: sal_info.make_schema_registry_topic_name(topic_name), @@ -152,13 +154,25 @@ impl<'a> WriteTopic<'a> { match self.encoder.encode(data_fields, key_strategy).await { Ok(bytes) => match &mut self.producer { Ok(producer) => { - match producer.send(&producer::Record::from_key_value( - &self.schema_registry_topic_name, - format!("{{ \"name\": \"{}\" }}", self.schema_registry_topic_name), - bytes, - )) { + match producer + .send( + FutureRecord { + topic: &self.schema_registry_topic_name, + partition: None, + payload: Some(&bytes), + key: Some(&format!( + "{{ \"name\": \"{}\" }}", + self.schema_registry_topic_name + )), + timestamp: None, + headers: None, + }, + Timeout::Never, + ) + .await + { Ok(_) => Ok(self.seq_num), - Err(error) => Err(SalObjError::from_error(error)), + Err((error, _)) => Err(SalObjError::from_error(error)), } } Err(error) => Err(SalObjError::new(&error.to_string())), @@ -181,15 +195,6 @@ impl<'a> WriteTopic<'a> { where T: BaseSALTopic + Serialize + Debug, { - // read current time in microseconds, as int, convert to f32 then - // convert to seconds. - if data.get_private_seq_num() != self.seq_num { - return Err(SalObjError::new(&format!( - "Input data has wrong sequence number. Must be {}, got {}.", - self.seq_num, - data.get_private_seq_num(), - ))); - } self.seq_num += 1; if let Ok(data_value) = to_value(data) { @@ -207,13 +212,25 @@ impl<'a> WriteTopic<'a> { match self.encoder.encode(data_fields, key_strategy).await { Ok(bytes) => match &mut self.producer { Ok(producer) => { - match producer.send(&producer::Record::from_key_value( - &self.schema_registry_topic_name, - format!("{{ \"name\": \"{}\" }}", self.schema_registry_topic_name), - bytes, - )) { + match producer + .send( + FutureRecord { + topic: &self.schema_registry_topic_name, + partition: None, + payload: Some(&bytes), + key: Some(&format!( + "{{ \"name\": \"{}\" }}", + self.schema_registry_topic_name + )), + timestamp: None, + headers: None, + }, + Timeout::Never, + ) + .await + { Ok(_) => Ok(data.get_private_seq_num()), - Err(error) => Err(SalObjError::from_error(error)), + Err((error, _)) => Err(SalObjError::from_error(error)), } } Err(error) => Err(SalObjError::new(&error.to_string())), diff --git a/src/utils/schema_utils.rs b/src/utils/schema_utils.rs index 2d8b583..30dd386 100644 --- a/src/utils/schema_utils.rs +++ b/src/utils/schema_utils.rs @@ -9,45 +9,50 @@ use std::path::Path; use std::{env, fs}; pub fn glob_schema_files(name: &str) -> Result, Box> { - let schema_dir_path = env::var("LSST_SCHEMA_PATH")?; - let schema_dir = Path::new(&schema_dir_path).join(name); + if let Ok(schema_dir_path) = env::var("LSST_SCHEMA_PATH") { + let schema_dir = Path::new(&schema_dir_path).join(name); - if !schema_dir.exists() { - return Err(Box::new(SalObjError::new(&format!( - "Schema path does not exists: {schema_dir_path}." - )))); - } + if !schema_dir.exists() { + return Err(Box::new(SalObjError::new(&format!( + "Schema path does not exists: {schema_dir_path}." + )))); + } - let json_files: Vec = schema_dir - .read_dir()? - .filter_map(|file_name| match file_name { - Ok(file_name) => { - let file_path = file_name.path().to_str()?.to_owned(); + let json_files: Vec = schema_dir + .read_dir()? + .filter_map(|file_name| match file_name { + Ok(file_name) => { + let file_path = file_name.path().to_str()?.to_owned(); + + if file_path.ends_with(".json") { + Some(file_path) + } else { + None + } + } + Err(_) => None, + }) + .collect(); - if file_path.ends_with(".json") { - Some(file_path) - } else { - None + Ok(json_files + .into_iter() + .filter_map(|filename| match fs::read_to_string(&filename) { + Ok(schema) => { + let filename = Path::new(&filename) + .file_name()? + .to_str()? + .to_owned() + .replace(".json", ""); + Some((filename, schema)) } - } - Err(_) => None, - }) - .collect(); - - Ok(json_files - .into_iter() - .filter_map(|filename| match fs::read_to_string(&filename) { - Ok(schema) => { - let filename = Path::new(&filename) - .file_name()? - .to_str()? - .to_owned() - .replace(".json", ""); - Some((filename, schema)) - } - Err(_) => None, - }) - .collect()) + Err(_) => None, + }) + .collect()) + } else { + Err(Box::new(SalObjError::new( + "Environment variable LSST_SCHEMA_PATH not set.", + ))) + } } pub fn parse_hash_table(hash_table: &str) -> Result, Box> { diff --git a/tests/test_base_csc.rs b/tests/test_base_csc.rs index a82276d..6cb5d13 100644 --- a/tests/test_base_csc.rs +++ b/tests/test_base_csc.rs @@ -8,7 +8,7 @@ use salobj::{ generics::summary_state::SummaryState, remote::Remote, sal_enums::{SalRetCode, State}, - topics::{base_sal_topic::BaseSALTopic, base_topic::BaseTopic, write_topic::WriteTopic}, + topics::{base_topic::BaseTopic, write_topic::WriteTopic}, }; use simple_logger::SimpleLogger; use std::time::Duration; @@ -38,7 +38,7 @@ macro_rules! process_command { .run_command_typed(&$cmd, &$data, Duration::from_secs(5), true) .await { - println!("{ack_cmd:?}"); + log::debug!("{ack_cmd:?}"); let cmd_name: Vec<&str> = $cmd.split("_").collect(); assert_eq!(*ack_cmd.get_ack_enum(), SalRetCode::CmdFailed); @@ -60,33 +60,38 @@ async fn test_state_transition() { log::set_max_level(log::LevelFilter::Debug); - let mut test_csc = TestCSC::new(123).unwrap(); + let mut test_csc = TestCSC::new(123).await.unwrap(); test_csc.start().await; - let _ = task::spawn(async move { + let run_csc_task = task::spawn(async move { println!("Running CSC."); let _ = test_csc.run().await; }); let mut domain = Domain::new(); - let mut remote = Remote::from_name_index(&mut domain, "Test", 123).unwrap(); + let mut remote = Remote::from_name_index(&mut domain, "Test", 123) + .await + .unwrap(); - let timeout = Duration::from_secs(10); + let timeout = Duration::from_secs(20); // Check that the initial state is Standby - if let Ok(Some(summary_state)) = remote + match remote .pop_event_back("logevent_summaryState", false, timeout) .await { - let summary_state = from_value::(&summary_state) - .unwrap() - .get_summary_state(); - assert_eq!(summary_state, State::Standby); - } else { - panic!("Could not get initial summary state"); - } + Ok(Some(summary_state)) => { + let summary_state = from_value::(&summary_state) + .unwrap() + .get_summary_state(); + assert_eq!(summary_state, State::Standby); + } + Ok(None) => panic!("No summary state data!"), + Err(error) => panic!("Could not get initial summary state: {error:?}"), + }; + println!("Test commands are rejected if CSC is in Standby."); // Check that all commands that should be rejected while in standby are // rejected. let standby_test_commands = ["setScalars", "setArrays", "wait"]; @@ -95,16 +100,19 @@ async fn test_state_transition() { for cmd_name in standby_test_commands { println!("Testing {cmd_name}"); let cmd = format!("command_{cmd_name}"); - assert_command_fails!(cmd, remote, current_state); } + println!("Sending CSC to Disabled."); + // Send the CSC to Disabled and test the same thing. let cmd = "command_start"; let schema = remote.get_command_schema(cmd).unwrap(); let mut record = WriteTopic::make_data_type(&schema).unwrap(); record.put("configurationOverride", Value::String("".to_owned())); + println!("Test commands are rejected if CSC is in Disabled."); + if let Ok(ack_cmd) = remote .run_command(cmd.to_string(), &mut record, timeout, true) .await @@ -123,4 +131,5 @@ async fn test_state_transition() { assert_command_fails!(cmd, remote, current_state); } + run_csc_task.abort(); }