diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f06efac..2b3def2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ env: RUST_BACKTRACE: 1 RUSTFLAGS: "-D warnings" CARGO_INCREMENTAL: 0 - RUST_VERSION: "1.82" # Minimum version for dependencies + RUST_VERSION: "1.88" # Minimum version for dependencies jobs: # Security audit for dependencies @@ -66,7 +66,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" components: rustfmt, clippy - name: Cache dependencies @@ -92,7 +92,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - rust: ["1.82", "stable", "beta"] + rust: ["1.88", "stable", "beta"] exclude: # Skip beta on Windows to save CI time - os: windows-latest @@ -130,7 +130,7 @@ jobs: - name: Read MSRV from Cargo.toml id: msrv run: | - MSRV=$(grep -oP 'rust-version = "\K[^"]+' Cargo.toml || echo "1.82") + MSRV=$(grep -oP 'rust-version = "\K[^"]+' Cargo.toml || echo "1.88") echo "msrv=$MSRV" >> $GITHUB_OUTPUT - name: Install Rust ${{ steps.msrv.outputs.msrv }} @@ -153,7 +153,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - rust: ["1.82"] + rust: ["1.88"] steps: - uses: actions/checkout@v4 @@ -186,7 +186,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -207,7 +207,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -226,7 +226,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -246,7 +246,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -254,7 +254,7 @@ jobs: - name: Install tarpaulin run: | if ! command -v cargo-tarpaulin &> /dev/null; then - cargo install cargo-tarpaulin --version 0.33.0 + cargo install cargo-tarpaulin --version 0.34.1 --locked fi - name: Generate coverage diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index ea097f0..f5a1ef8 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -9,7 +9,7 @@ env: RUST_BACKTRACE: 1 RUSTFLAGS: "-D warnings" CARGO_INCREMENTAL: 0 - RUST_VERSION: "1.82" + RUST_VERSION: "1.88" jobs: # Security audit for dependencies @@ -47,7 +47,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" components: rustfmt, clippy - name: Cache dependencies @@ -79,7 +79,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -100,7 +100,7 @@ jobs: - name: Read MSRV from Cargo.toml id: msrv run: | - MSRV=$(grep -oP 'rust-version = "\K[^"]+' Cargo.toml || echo "1.82") + MSRV=$(grep -oP 'rust-version = "\K[^"]+' Cargo.toml || echo "1.88") echo "msrv=$MSRV" >> $GITHUB_OUTPUT - name: Install Rust ${{ steps.msrv.outputs.msrv }} @@ -125,7 +125,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 @@ -144,7 +144,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.82" + toolchain: "1.88" - name: Cache dependencies uses: Swatinem/rust-cache@v2 diff --git a/Cargo.lock b/Cargo.lock index 2e68c92..919ad7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,36 +2,15 @@ # 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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] -[[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" @@ -43,9 +22,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -58,9 +37,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -73,22 +52,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -97,6 +76,12 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "arcstr" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d" + [[package]] name = "arraydeque" version = "0.5.1" @@ -122,18 +107,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -148,20 +133,43 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5ce75405893cd713f9ab8e297d8e438f624dde7d706108285f7e17a25a180f" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "179c3777a8b5e70e90ea426114ffc565b2c1a9f82f6c4a0c5a34aa6ef5e781b6" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" -version = "0.7.9" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ - "async-trait", "axum-core", "bytes", + "form_urlencoded", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-util", "itoa", "matchit", @@ -169,12 +177,11 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower", "tower-layer", @@ -184,38 +191,30 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.5" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ - "async-trait", "bytes", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "futures-core", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", "tracing", ] [[package]] -name = "backtrace" -version = "0.3.75" +name = "backon" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", + "fastrand", ] [[package]] @@ -232,17 +231,11 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -254,13 +247,53 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bollard" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41711ad46fda47cd701f6908e59d1bd6b9a2b7464c0d0aeab95c6d37096ff8a" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "home", + "http", + "http-body-util", + "hyper", + "hyper-named-pipe", + "hyper-rustls", + "hyper-util", + "hyperlocal", + "log", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + [[package]] name = "bollard-stubs" -version = "1.42.0-rc.3" +version = "1.45.0-rc.26.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" +checksum = "6d7c5415e3a6bc6d3e99eff6268e488fd4ee25e7b28c10f08fa6760bd9de16e4" dependencies = [ "serde", + "serde_repr", "serde_with", ] @@ -278,24 +311,27 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.31" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -305,17 +341,16 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -326,9 +361,9 @@ checksum = "2842d01fb68c3f111867212ee647a52b0897ce0ee072e0640c965ae2a6acbdf6" [[package]] name = "clap" -version = "4.5.42" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -336,33 +371,42 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.42" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "cmake" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "b042e5d8a74ae91bb0961acd039822472ec99f8ab0948cbf6d1369588f8be586" +dependencies = [ + "cc", +] [[package]] name = "colorchoice" @@ -386,17 +430,18 @@ dependencies = [ [[package]] name = "config" -version = "0.15.13" +version = "0.15.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1eb4fb07bc7f012422df02766c7bd5971effb894f573865642f06fa3265440" +checksum = "b30fa8254caad766fc03cb0ccae691e14bf3bd72bfff27f72802ce729551b3d6" dependencies = [ "async-trait", - "convert_case", + "convert_case 0.6.0", "json5", "pathdiff", "ron", "rust-ini", - "serde", + "serde-untagged", + "serde_core", "serde_json", "toml", "winnow", @@ -432,6 +477,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -457,31 +511,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "crunchy" version = "0.2.4" @@ -490,9 +519,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -500,9 +529,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -510,37 +539,37 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.4" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 1.0.109", + "strsim", + "syn", ] [[package]] name = "darling_macro" -version = "0.13.4" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "deadpool" -version = "0.10.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ - "async-trait", "deadpool-runtime", + "lazy_static", "num_cpus", "serde", "tokio", @@ -548,11 +577,13 @@ dependencies = [ [[package]] name = "deadpool-postgres" -version = "0.12.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda39fa1cfff190d8924d447ad04fd22772c250438ca5ce1dfb3c80621c05aaa" +checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" dependencies = [ + "async-trait", "deadpool", + "getrandom 0.2.16", "serde", "tokio", "tokio-postgres", @@ -570,12 +601,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -595,6 +626,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -603,7 +655,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -615,6 +667,29 @@ dependencies = [ "const-random", ] +[[package]] +name = "docker_credential" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" version = "1.15.0" @@ -639,14 +714,25 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -661,6 +747,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fnv" version = "1.0.7" @@ -690,13 +782,19 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.31" @@ -753,7 +851,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -805,43 +903,37 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "h2" -version = "0.3.27" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", + "http", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -849,23 +941,10 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.4.11" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" @@ -875,20 +954,26 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "hashlink" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -919,38 +1004,24 @@ dependencies = [ ] [[package]] -name = "http" -version = "0.2.12" +name = "home" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "bytes", - "fnv", - "itoa", + "windows-sys 0.61.2", ] [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -958,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] @@ -969,8 +1040,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -988,61 +1059,40 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.32" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[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", - "h2 0.4.11", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", ] [[package]] -name = "hyper-rustls" -version = "0.24.2" +name = "hyper-named-pipe" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "rustls 0.21.12", + "hex", + "hyper", + "hyper-util", + "pin-project-lite", "tokio", - "tokio-rustls 0.24.1", + "tower-service", + "winapi", ] [[package]] @@ -1051,68 +1101,88 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.3.1", - "hyper 1.6.0", + "http", + "hyper", "hyper-util", - "rustls 0.23.31", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower-service", - "webpki-roots 1.0.2", + "webpki-roots", ] [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper 0.14.32", + "http-body-util", + "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.6.0", + "http", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] -name = "iana-time-zone" -version = "0.1.63" +name = "hyperlocal" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.61.2", -] + "hex", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] [[package]] name = "iana-time-zone-haiku" @@ -1125,9 +1195,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1138,9 +1208,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1151,11 +1221,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1166,42 +1235,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1217,9 +1282,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1238,23 +1303,25 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "equivalent", - "hashbrown 0.15.4", + "autocfg", + "hashbrown 0.12.3", + "serde", ] [[package]] -name = "io-uring" -version = "0.7.9" +name = "indexmap" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "libc", + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -1265,9 +1332,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -1275,9 +1342,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "iso8601" @@ -1294,11 +1361,21 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -1317,15 +1394,17 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e" dependencies = [ + "aws-lc-rs", "base64 0.22.1", + "getrandom 0.2.16", "js-sys", - "ring", "serde", "serde_json", + "signature", ] [[package]] @@ -1336,9 +1415,20 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" @@ -1348,31 +1438,30 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru-slab" @@ -1382,18 +1471,18 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] name = "matchit" -version = "0.7.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "md-5" @@ -1426,9 +1515,9 @@ dependencies = [ "postgres-types", "pretty_assertions", "prometheus", - "rand 0.8.5", + "rand", "redis", - "reqwest 0.11.27", + "reqwest", "serde", "serde_json", "serde_yaml", @@ -1437,7 +1526,7 @@ dependencies = [ "test-case", "testcontainers", "testcontainers-modules", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-postgres", "tokio-stream", @@ -1451,38 +1540,41 @@ dependencies = [ [[package]] name = "meilisearch-index-setting-macro" -version = "0.26.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "517f9cbfcc9368d71c021bef83b1d448c2b29f5734a25da6174ddf31deead340" +checksum = "45be1063aa1851aacf36a93f5d0d243e0cb7693cde4dd110cd5c0e66eb59dcc7" dependencies = [ - "convert_case", + "convert_case 0.8.0", "proc-macro2", "quote", "structmeta", - "syn 2.0.104", + "syn", ] [[package]] name = "meilisearch-sdk" -version = "0.26.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa561e4357a47bc64b1d87b6a081416cd58e2e3c00a30813e8936baed3b5a121" +checksum = "06c230967213165b7c42c93ba253478eccf7478432a09cc5ff6c586dd8e11656" dependencies = [ "async-trait", "bytes", "either", - "futures", + "futures-channel", + "futures-core", "futures-io", + "futures-util", "iso8601", "jsonwebtoken", "log", "meilisearch-index-setting-macro", "pin-project-lite", - "reqwest 0.12.22", + "reqwest", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.17", "time", + "tokio", "uuid", "wasm-bindgen-futures", "web-sys", @@ -1491,9 +1583,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mime" @@ -1501,24 +1593,15 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[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.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -1558,12 +1641,21 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", +] + +[[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", ] [[package]] @@ -1572,6 +1664,15 @@ 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" @@ -1592,12 +1693,22 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.7" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "memchr", + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", ] [[package]] @@ -1608,17 +1719,17 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.9.1", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -1635,7 +1746,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1646,9 +1757,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -1656,6 +1767,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-multimap" version = "0.7.3" @@ -1666,17 +1783,11 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1684,15 +1795,40 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", +] + +[[package]] +name = "parse-display" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" +dependencies = [ + "parse-display-derive", + "regex", + "regex-syntax", +] + +[[package]] +name = "parse-display-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "regex-syntax", + "structmeta", + "syn", ] [[package]] @@ -1703,26 +1839,25 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" dependencies = [ "memchr", - "thiserror 2.0.12", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.1" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" dependencies = [ "pest", "pest_generator", @@ -1730,22 +1865,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.1" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "pest_meta" -version = "2.8.1" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ "pest", "sha2", @@ -1753,42 +1888,23 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_shared", + "serde", ] [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -1809,21 +1925,21 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "postgres-derive" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69700ea4603c5ef32d447708e6a19cd3e8ac197a000842e97f527daea5e4175f" +checksum = "56df96f5394370d1b20e49de146f9e6c25aa9ae750f449c9d665eafecb3ccae6" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "postgres-protocol" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" +checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" dependencies = [ "base64 0.22.1", "byteorder", @@ -1832,32 +1948,32 @@ dependencies = [ "hmac", "md-5", "memchr", - "rand 0.9.2", + "rand", "sha2", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "chrono", "fallible-iterator", "postgres-derive", "postgres-protocol", - "serde", + "serde_core", "serde_json", "uuid", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1889,41 +2005,40 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" +checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" dependencies = [ - "bitflags 2.9.1", + "bitflags", "hex", - "lazy_static", "procfs-core", "rustix 0.38.44", ] [[package]] name = "procfs-core" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" +checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" dependencies = [ - "bitflags 2.9.1", + "bitflags", "hex", ] [[package]] name = "prometheus" -version = "0.13.4" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" +checksum = "3ca5326d8d0b950a9acd87e6a3f94745394f62e4dae1b1ee22b2bc0c394af43a" dependencies = [ "cfg-if", "fnv", @@ -1933,20 +2048,34 @@ dependencies = [ "parking_lot", "procfs", "protobuf", - "thiserror 1.0.69", + "thiserror 2.0.17", ] [[package]] name = "protobuf" -version = "2.28.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", +] [[package]] name = "quinn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -1954,9 +2083,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.31", - "socket2 0.5.10", - "thiserror 2.0.12", + "rustls", + "socket2", + "thiserror 2.0.17", "tokio", "tracing", "web-time", @@ -1964,20 +2093,20 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand", "ring", "rustc-hash", - "rustls 0.23.31", + "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.17", "tinyvec", "tracing", "web-time", @@ -1985,23 +2114,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2012,37 +2141,16 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha 0.9.0", + "rand_chacha", "rand_core 0.9.3", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_chacha" version = "0.9.0" @@ -2068,180 +2176,140 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "getrandom 0.3.4", ] [[package]] name = "redis" -version = "0.24.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c580d9cbbe1d1b479e8d67cf9daf6a62c957e6846048408b80b43ac3f6af84cd" +checksum = "e2dc509b442812959ab125c74be2a930dd9b603038b6da9df9ec013aa23a4e9c" dependencies = [ "arc-swap", - "async-trait", + "arcstr", + "backon", "bytes", + "cfg-if", "combine", - "futures", + "futures-channel", "futures-util", "itoa", + "num-bigint", "percent-encoding", "pin-project-lite", "ryu", "sha1_smol", - "socket2 0.4.10", + "socket2", "tokio", - "tokio-retry", "tokio-util", "url", + "xxhash-rust", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags", ] [[package]] -name = "regex" -version = "1.11.1" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "regex-syntax 0.6.29", + "ref-cast-impl", ] [[package]] -name = "regex-automata" -version = "0.4.9" +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-automata", + "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "regex-automata" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-rustls 0.24.2", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", "hyper-tls", - "ipnet", + "hyper-util", "js-sys", "log", "mime", "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.24.1", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.4", - "winreg", -] - -[[package]] -name = "reqwest" -version = "0.12.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "h2 0.4.11", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-rustls 0.27.7", - "hyper-util", - "js-sys", - "log", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.31", + "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", - "tokio-rustls 0.26.2", + "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -2251,7 +2319,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.2", + "webpki-roots", ] [[package]] @@ -2264,38 +2332,34 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] [[package]] name = "ron" -version = "0.8.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" dependencies = [ - "base64 0.21.7", - "bitflags 2.9.1", + "bitflags", + "once_cell", "serde", "serde_derive", + "typeid", + "unicode-ident", ] [[package]] name = "rust-ini" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7295b7ce3bf4806b419dc3420745998b447178b7005e2011947b38fc5aa6791" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" dependencies = [ "cfg-if", "ordered-multimap", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -2308,7 +2372,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags", "errno", "libc", "linux-raw-sys 0.4.15", @@ -2317,57 +2381,58 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.21.12" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ - "log", + "once_cell", "ring", - "rustls-webpki 0.101.7", - "sct", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] -name = "rustls" -version = "0.23.31" +name = "rustls-native-certs" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "once_cell", - "ring", + "openssl-probe", + "rustls-pemfile", "rustls-pki-types", - "rustls-webpki 0.103.4", - "subtle", - "zeroize", + "schannel", + "security-framework", ] [[package]] name = "rustls-pemfile" -version = "1.0.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.21.7", + "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ "web-time", "zeroize", @@ -2375,30 +2440,20 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.4" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2408,36 +2463,50 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "schemars" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] [[package]] -name = "sct" -version = "0.7.1" +name = "schemars" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" dependencies = [ - "ring", - "untrusted", + "dyn-clone", + "ref-cast", + "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 2.9.1", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -2446,9 +2515,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -2456,53 +2525,88 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -2519,24 +2623,33 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ - "serde", + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.12.1", + "schemars 0.9.0", + "schemars 1.1.0", + "serde_core", + "serde_json", "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2545,7 +2658,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", + "indexmap 2.12.1", "itoa", "ryu", "serde", @@ -2586,13 +2699,22 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "siphasher" version = "1.0.1" @@ -2613,39 +2735,19 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stringprep" @@ -2658,12 +2760,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -2679,7 +2775,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.104", + "syn", ] [[package]] @@ -2690,7 +2786,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2701,32 +2797,15 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -2744,40 +2823,39 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "sysinfo" -version = "0.30.13" +version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" dependencies = [ - "cfg-if", - "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", - "rayon", + "objc2-core-foundation", + "objc2-io-kit", "windows", ] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -2785,15 +2863,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", - "rustix 1.0.8", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -2814,7 +2892,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2825,32 +2903,43 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "test-case-core", ] [[package]] name = "testcontainers" -version = "0.15.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d2931d7f521af5bae989f716c3fa43a6af9af7ec7a5e21b59ae40878cec00" +checksum = "2ef8374cea2c164699681ecc39316c3e1d953831a7a5721e36c7736d974e15fa" dependencies = [ + "async-trait", + "bollard", "bollard-stubs", + "bytes", + "dirs", + "docker_credential", + "either", "futures", - "hex", - "hmac", "log", - "rand 0.8.5", + "memchr", + "parse-display", + "pin-project-lite", "serde", "serde_json", - "sha2", + "serde_with", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tokio-util", + "url", ] [[package]] name = "testcontainers-modules" -version = "0.3.7" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8debb5e215d9e89ea93255fffff00bf037ea44075d7a2669a21a8a988d6b52fd" +checksum = "359d9a225791e1b9f60aab01f9ae9471898b9b9904b5db192104a71e96785079" dependencies = [ "testcontainers", ] @@ -2866,11 +2955,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -2881,18 +2970,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2906,9 +2995,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -2921,15 +3010,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -2946,9 +3035,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -2956,9 +3045,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -2971,33 +3060,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3012,9 +3098,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" +checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" dependencies = [ "async-trait", "byteorder", @@ -3029,41 +3115,20 @@ dependencies = [ "pin-project-lite", "postgres-protocol", "postgres-types", - "rand 0.9.2", - "socket2 0.5.10", + "rand", + "socket2", "tokio", "tokio-util", "whoami", ] -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.31", + "rustls", "tokio", ] @@ -3094,9 +3159,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -3107,11 +3172,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.4" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ae868b5a0f67631c14589f7e250c1ea2c574ee5ba21c6c8dd4b1485705a5a1" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ - "serde", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -3120,18 +3185,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] @@ -3145,7 +3210,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -3154,15 +3219,15 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.9.1", + "bitflags", "bytes", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "iri-string", "pin-project-lite", "tower", @@ -3185,9 +3250,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "log", "pin-project-lite", @@ -3197,20 +3262,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", @@ -3239,15 +3304,15 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "chrono", "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "serde", "serde_json", "sharded-slab", @@ -3265,11 +3330,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -3285,24 +3356,24 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" @@ -3316,6 +3387,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -3324,13 +3401,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3347,13 +3425,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -3391,12 +3469,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -3407,35 +3485,22 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" 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 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -3446,9 +3511,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3456,22 +3521,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.104", - "wasm-bindgen-backend", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] @@ -3491,9 +3556,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -3511,26 +3576,20 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - -[[package]] -name = "webpki-roots" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] [[package]] name = "whoami" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall", + "libredox", "wasite", "web-sys", ] @@ -3559,21 +3618,24 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.52.0" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", ] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.61.2", ] [[package]] @@ -3584,31 +3646,55 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3617,13 +3703,49 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -3632,7 +3754,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -3668,7 +3799,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "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 0.2.1", ] [[package]] @@ -3704,19 +3844,28 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "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-threading" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.1.3", ] [[package]] @@ -3733,9 +3882,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -3751,9 +3900,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -3769,9 +3918,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -3781,9 +3930,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -3799,9 +3948,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -3817,9 +3966,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -3835,9 +3984,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -3853,49 +4002,42 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] -name = "winreg" -version = "0.50.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "writeable" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] -name = "writeable" -version = "0.6.1" +name = "xxhash-rust" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yaml-rust2" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce2a4ff45552406d02501cea6c18d8a7e50228e7736a872951fe2fe75c91be7" +checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" dependencies = [ "arraydeque", "encoding_rs", @@ -3910,21 +4052,21 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yaup" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a59e7d27bed43f7c37c25df5192ea9d435a8092a902e02203359ac9ce3e429d9" +checksum = "b0144f1a16a199846cb21024da74edd930b43443463292f536b7110b4855b5c6" dependencies = [ + "form_urlencoded", "serde", - "url", + "thiserror 1.0.69", ] [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3932,34 +4074,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3979,21 +4121,21 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -4002,9 +4144,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbb9122ea75b11bf96e7492afb723e8a7fbe12c67417aa95e7e3d18144d37cd" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -4013,11 +4155,11 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index b48aca9..99866cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "meilibridge" version = "0.1.6" -edition = "2021" -rust-version = "1.82" +edition = "2024" +rust-version = "1.88" authors = ["Omkar Todkar"] description = "High-performance PostgreSQL to Meilisearch connector" license = "MIT" @@ -37,7 +37,7 @@ uuid = { version = "1.18", features = ["v4", "serde"] } # PostgreSQL tokio-postgres = { version = "0.7", features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-1"] } -deadpool-postgres = { version = "0.12", features = ["serde"] } +deadpool-postgres = { version = "0.14.1", features = ["serde"] } postgres-types = { version = "0.2", features = ["derive"] } postgres-protocol = "0.6" @@ -46,17 +46,17 @@ bytes = "1.5" byteorder = "1.5" # Redis -redis = { version = "0.24", features = ["tokio-comp", "connection-manager"] } +redis = { version = "1.0.1", features = ["tokio-comp", "connection-manager"] } # System monitoring -sysinfo = "0.30" +sysinfo = "0.37.2" # Meilisearch -meilisearch-sdk = "0.26" -reqwest = { version = "0.11", features = ["json", "rustls-tls"] } +meilisearch-sdk = "0.31.0" +reqwest = { version = "0.12.25", features = ["json", "rustls-tls"] } # Web framework -axum = "0.7" +axum = "0.8.7" tower = "0.5" tower-http = { version = "0.6", features = ["trace", "cors"] } @@ -66,13 +66,13 @@ async-trait = "0.1" tokio-stream = { version = "0.1", features = ["sync"] } # Random number generation -rand = "0.8" +rand = "0.9.2" # Lazy static initialization lazy_static = "1.4" # Metrics -prometheus = { version = "0.13", features = ["process"] } +prometheus = { version = "0.14.0", features = ["process"] } # CLI clap = { version = "4.5", features = ["derive", "env"] } @@ -88,8 +88,8 @@ once_cell = "1.19" test-case = "3.3.1" tempfile = "3.10" async-trait = "0.1" -testcontainers = "0.15" -testcontainers-modules = { version = "0.3", features = ["postgres", "redis"] } +testcontainers = "0.22.0" +testcontainers-modules = { version = "0.10.0", features = ["postgres", "redis"] } [[test]] name = "unit" diff --git a/README.md b/README.md index b10abb0..e7b20e9 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Get MeiliBridge running in under 2 minutes! - PostgreSQL 10+ with logical replication enabled - Meilisearch 1.0+ instance -- Docker (recommended) or Rust 1.70+ (for manual build) +- Docker (recommended) or Rust 1.88+ (for manual build) ### PostgreSQL Setup @@ -362,7 +362,7 @@ Available metrics: - `GET /health` - Overall system health - `GET /health/liveness` - Kubernetes liveness probe - `GET /health/readiness` - Kubernetes readiness probe -- `GET /health/:component` - Component-specific health (postgresql, meilisearch, redis) +- `GET /health/{component}` - Component-specific health (postgresql, meilisearch, redis) ### Grafana Dashboard @@ -378,14 +378,14 @@ Import our [Grafana dashboard](monitoring/grafana-dashboard.json) for visualizin #### Sync Task Management - `GET /tasks` - List all sync tasks -- `GET /tasks/:id` - Get sync task details +- `GET /tasks/{id}` - Get sync task details - `POST /tasks` - Create new sync task -- `PUT /tasks/:id` - Update sync task -- `DELETE /tasks/:id` - Delete sync task -- `POST /tasks/:id/pause` - Pause sync task -- `POST /tasks/:id/resume` - Resume sync task -- `POST /tasks/:id/full-sync` - Trigger full table sync -- `GET /tasks/:id/stats` - Get task statistics +- `PUT /tasks/{id}` - Update sync task +- `DELETE /tasks/{id}` - Delete sync task +- `POST /tasks/{id}/pause` - Pause sync task +- `POST /tasks/{id}/resume` - Resume sync task +- `POST /tasks/{id}/full-sync` - Trigger full table sync +- `GET /tasks/{id}/stats` - Get task statistics #### CDC Control - `POST /cdc/pause` - Pause all CDC processing @@ -394,7 +394,7 @@ Import our [Grafana dashboard](monitoring/grafana-dashboard.json) for visualizin #### Dead Letter Queue - `GET /dead-letters` - Get DLQ statistics -- `POST /dead-letters/:task_id/reprocess` - Reprocess failed events +- `POST /dead-letters/{task_id}/reprocess` - Reprocess failed events #### Cache Management - `GET /cache/stats` - Get statement cache statistics diff --git a/docker/Dockerfile b/docker/Dockerfile index 6d9201b..9240b39 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ # Multi-stage build for optimal image size # Build stage -FROM rust:1.82-bookworm AS builder +FROM rust:1.88-bookworm AS builder # Add labels for metadata ARG BUILD_DATE diff --git a/docs/api-development.md b/docs/api-development.md index 9a19923..5200052 100644 --- a/docs/api-development.md +++ b/docs/api-development.md @@ -163,7 +163,7 @@ Health check endpoint. } ``` -#### GET /health/:component +#### GET /health/{component} Get health status for a specific component. **Parameters**: @@ -222,7 +222,7 @@ List all sync tasks. } ``` -#### GET /tasks/:id +#### GET /tasks/{id} Get specific task details. **Response**: @@ -299,18 +299,18 @@ Create a new sync task. } ``` -#### PUT /tasks/:id +#### PUT /tasks/{id} Update task configuration. **Request Body**: Same as POST /tasks -#### DELETE /tasks/:id +#### DELETE /tasks/{id} Delete a sync task. **Query Parameters**: - `force`: Force delete even if task is active (default: false) -#### POST /tasks/:id/pause +#### POST /tasks/{id}/pause Pause a sync task. **Response**: @@ -325,10 +325,10 @@ Pause a sync task. } ``` -#### POST /tasks/:id/resume +#### POST /tasks/{id}/resume Resume a paused sync task. -#### POST /tasks/:id/full-sync +#### POST /tasks/{id}/full-sync Trigger a full synchronization for a task. **Request Body** (optional): @@ -340,7 +340,7 @@ Trigger a full synchronization for a task. } ``` -#### GET /tasks/:id/stats +#### GET /tasks/{id}/stats Get detailed statistics for a task. **Response**: @@ -389,7 +389,7 @@ Get dead letter queue statistics. } ``` -#### POST /dead-letters/:task_id/reprocess +#### POST /dead-letters/{task_id}/reprocess Reprocess dead letter entries for a task. **Request Body**: @@ -442,7 +442,7 @@ Get CDC status and statistics. #### GET /sources List configured sources. -#### GET /sources/:id +#### GET /sources/{id} Get source details and status. #### POST /sources/test diff --git a/docs/getting-started.md b/docs/getting-started.md index d6dc589..bfd7bfc 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -21,7 +21,7 @@ This guide covers installation, setup, and deployment of MeiliBridge for both de - **Network**: Stable internet connection for package downloads ### Required Software -- **Rust**: 1.70.0 or higher +- **Rust**: 1.88 or higher - **PostgreSQL**: 10+ with logical replication support - **Meilisearch**: 1.0+ (destination database) - **Redis**: 6.0+ (for checkpoint storage and dead letter queue) diff --git a/src/api/cache_handlers.rs b/src/api/cache_handlers.rs index aacd2e6..7607483 100644 --- a/src/api/cache_handlers.rs +++ b/src/api/cache_handlers.rs @@ -1,6 +1,6 @@ use crate::api::state::ApiState; use crate::error::MeiliBridgeError; -use axum::{extract::State, Json}; +use axum::{Json, extract::State}; use serde::Serialize; #[derive(Debug, Serialize)] diff --git a/src/api/diagnostics.rs b/src/api/diagnostics.rs index 881b6ac..ddc7089 100644 --- a/src/api/diagnostics.rs +++ b/src/api/diagnostics.rs @@ -1,9 +1,9 @@ use crate::api::ApiState; use crate::models::Position; use axum::{ + Json, extract::{Path, Query, State}, http::StatusCode, - Json, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/src/api/handlers.rs b/src/api/handlers.rs index a77f775..2e1ce52 100644 --- a/src/api/handlers.rs +++ b/src/api/handlers.rs @@ -2,10 +2,10 @@ use crate::api::ApiState; use crate::config::SyncTaskConfig; use crate::error::MeiliBridgeError; use axum::{ + Json, extract::{Path, State}, http::StatusCode, response::IntoResponse, - Json, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -40,7 +40,7 @@ pub struct ErrorResponse { impl From for ErrorResponse { fn from(err: MeiliBridgeError) -> Self { Self { - error: format!("{:?}", err), + error: format!("{err:?}"), message: err.to_string(), } } @@ -120,8 +120,7 @@ pub async fn get_task( })) } else { Err(MeiliBridgeError::NotFound(format!( - "Task '{}' not found", - task_id + "Task '{task_id}' not found", ))) } } @@ -235,7 +234,7 @@ pub async fn reprocess_dead_letters( // Update metrics crate::metrics::DEAD_LETTER_REPROCESS_TOTAL - .with_label_values(&[&task_id, "initiated"]) + .with_label_values(&[task_id.as_str(), "initiated"]) .inc_by(count as f64); Ok(StatusCode::ACCEPTED) @@ -298,7 +297,7 @@ pub async fn delete_task( /// Get Prometheus metrics pub async fn get_metrics() -> Result { crate::metrics::export_metrics() - .map_err(|e| MeiliBridgeError::Pipeline(format!("Failed to export metrics: {}", e))) + .map_err(|e| MeiliBridgeError::Pipeline(format!("Failed to export metrics: {e}"))) } /// Get health check for a specific component @@ -311,8 +310,7 @@ pub async fn get_component_health( Ok((StatusCode::OK, Json(health))) } else { Err(MeiliBridgeError::NotFound(format!( - "Component '{}' not found", - component + "Component '{component}' not found", ))) } } else { diff --git a/src/api/server.rs b/src/api/server.rs index c0d380b..8c325c1 100644 --- a/src/api/server.rs +++ b/src/api/server.rs @@ -1,10 +1,9 @@ -use crate::api::{cache_handlers, diagnostics, handlers, middleware, ApiState}; +use crate::api::{ApiState, cache_handlers, diagnostics, handlers, middleware}; use crate::config::Config; use crate::error::{MeiliBridgeError, Result}; use axum::{ - middleware as axum_middleware, + Router, middleware as axum_middleware, routing::{delete, get, post, put}, - Router, }; use std::net::SocketAddr; use tower_http::cors::CorsLayer; @@ -27,15 +26,15 @@ impl ApiServer { Router::new() // Health check .route("/health", get(handlers::health)) - .route("/health/:component", get(handlers::get_component_health)) + .route("/health/{component}", get(handlers::get_component_health)) // Task management .route("/tasks", get(handlers::get_tasks)) .route("/tasks", post(handlers::create_task)) - .route("/tasks/:id", get(handlers::get_task)) - .route("/tasks/:id", delete(handlers::delete_task)) - .route("/tasks/:id/pause", put(handlers::pause_task)) - .route("/tasks/:id/resume", put(handlers::resume_task)) - .route("/tasks/:id/full-sync", post(handlers::full_sync_task)) + .route("/tasks/{id}", get(handlers::get_task)) + .route("/tasks/{id}", delete(handlers::delete_task)) + .route("/tasks/{id}/pause", put(handlers::pause_task)) + .route("/tasks/{id}/resume", put(handlers::resume_task)) + .route("/tasks/{id}/full-sync", post(handlers::full_sync_task)) // CDC control .route("/cdc/pause", put(handlers::pause_cdc)) .route("/cdc/resume", put(handlers::resume_cdc)) @@ -46,7 +45,7 @@ impl ApiServer { // Dead letter queue .route("/dead-letters", get(handlers::get_dead_letter_stats)) .route( - "/dead-letters/:task_id/reprocess", + "/dead-letters/{task_id}/reprocess", post(handlers::reprocess_dead_letters), ) // Metrics endpoint @@ -56,7 +55,7 @@ impl ApiServer { .route("/cache/clear", post(cache_handlers::clear_cache)) // Diagnostic endpoints .route( - "/diagnostics/pipeline/:table", + "/diagnostics/pipeline/{table}", get(diagnostics::get_pipeline_diagnostics), ) .route( @@ -68,11 +67,11 @@ impl ApiServer { get(diagnostics::get_connections_diagnostics), ) .route( - "/diagnostics/trace/:event_id", + "/diagnostics/trace/{event_id}", get(diagnostics::get_event_trace), ) .route( - "/diagnostics/replay/:table", + "/diagnostics/replay/{table}", post(diagnostics::replay_events), ) .route( @@ -94,9 +93,9 @@ impl ApiServer { let host = &self.config.api.host; let port = self.config.api.port; - let addr: SocketAddr = format!("{}:{}", host, port) + let addr: SocketAddr = format!("{host}:{port}") .parse() - .map_err(|e| MeiliBridgeError::Configuration(format!("Invalid API address: {}", e)))?; + .map_err(|e| MeiliBridgeError::Configuration(format!("Invalid API address: {e}")))?; info!("Starting API server on {}", addr); @@ -108,20 +107,14 @@ impl ApiServer { Ok(listener) => break listener, Err(e) if retry_count < max_retries => { warn!( - "Failed to bind to {}: {}. Retrying in 2 seconds... ({}/{})", - addr, - e, + "Failed to bind to {addr}: {e}. Retrying in 2 seconds... ({}/{max_retries})", retry_count + 1, - max_retries ); retry_count += 1; tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; } Err(e) => { - error!( - "Failed to bind to {} after {} retries: {}", - addr, max_retries, e - ); + error!("Failed to bind to {addr} after {max_retries} retries: {e}"); return Err(MeiliBridgeError::Io(e)); } } diff --git a/src/checkpoint/manager.rs b/src/checkpoint/manager.rs index 5be22e8..67b3e25 100644 --- a/src/checkpoint/manager.rs +++ b/src/checkpoint/manager.rs @@ -3,8 +3,8 @@ use crate::error::{MeiliBridgeError, Result}; use crate::models::{Checkpoint, Position}; use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{mpsc, watch, RwLock}; -use tokio::time::{interval, Duration}; +use tokio::sync::{RwLock, mpsc, watch}; +use tokio::time::{Duration, interval}; use tracing::{debug, error, info, warn}; /// Commands for checkpoint management diff --git a/src/checkpoint/storage.rs b/src/checkpoint/storage.rs index 1494141..9ec2437 100644 --- a/src/checkpoint/storage.rs +++ b/src/checkpoint/storage.rs @@ -94,20 +94,19 @@ impl RedisStorage { } pub async fn connect(&mut self) -> Result<()> { - let client = redis::Client::open(self.config.url.as_str()).map_err(|e| { - MeiliBridgeError::Config(format!("Failed to create Redis client: {}", e)) - })?; + let client = redis::Client::open(self.config.url.as_str()) + .map_err(|e| MeiliBridgeError::Config(format!("Failed to create Redis client: {e}")))?; // Test connection let mut con = client - .get_async_connection() + .get_multiplexed_async_connection() .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to connect to Redis: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to connect to Redis: {e}")))?; redis::cmd("PING") - .query_async::<_, String>(&mut con) + .query_async::(&mut con) .await - .map_err(|e| MeiliBridgeError::Config(format!("Redis ping failed: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Redis ping failed: {e}")))?; self.client = Some(client); info!("Connected to Redis for checkpoint storage"); @@ -118,16 +117,16 @@ impl RedisStorage { format!("{}{}", self.key_prefix, task_id) } - async fn get_connection(&self) -> Result { + async fn get_connection(&self) -> Result { let client = self .client .as_ref() .ok_or_else(|| MeiliBridgeError::Config("Redis client not initialized".to_string()))?; client - .get_async_connection() + .get_multiplexed_async_connection() .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to get Redis connection: {}", e))) + .map_err(|e| MeiliBridgeError::Config(format!("Failed to get Redis connection: {e}"))) } } @@ -147,9 +146,9 @@ impl CheckpointStorage for RedisStorage { .arg(&value) .arg("EX") .arg(ttl) - .query_async::<_, ()>(&mut con) + .query_async::<()>(&mut con) .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to save checkpoint: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to save checkpoint: {e}")))?; debug!( "Saved checkpoint for task '{}' to Redis", @@ -166,7 +165,7 @@ impl CheckpointStorage for RedisStorage { .arg(&key) .query_async(&mut con) .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to load checkpoint: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to load checkpoint: {e}")))?; match value { Some(json) => { @@ -183,9 +182,9 @@ impl CheckpointStorage for RedisStorage { redis::cmd("DEL") .arg(&key) - .query_async::<_, ()>(&mut con) + .query_async::<()>(&mut con) .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to delete checkpoint: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to delete checkpoint: {e}")))?; debug!("Deleted checkpoint for task '{}' from Redis", task_id); Ok(()) @@ -200,7 +199,7 @@ impl CheckpointStorage for RedisStorage { .arg(&pattern) .query_async(&mut con) .await - .map_err(|e| MeiliBridgeError::Config(format!("Failed to list checkpoints: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to list checkpoints: {e}")))?; let mut checkpoints = Vec::new(); @@ -210,9 +209,7 @@ impl CheckpointStorage for RedisStorage { .arg(&key) .query_async(&mut con) .await - .map_err(|e| { - MeiliBridgeError::Config(format!("Failed to load checkpoint: {}", e)) - })?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to load checkpoint: {e}")))?; if let Some(json) = value { match serde_json::from_str::(&json) { @@ -228,7 +225,7 @@ impl CheckpointStorage for RedisStorage { async fn is_healthy(&self) -> bool { if let Ok(mut con) = self.get_connection().await { redis::cmd("PING") - .query_async::<_, String>(&mut con) + .query_async::(&mut con) .await .is_ok() } else { diff --git a/src/config/loader.rs b/src/config/loader.rs index fabea69..a863e3c 100644 --- a/src/config/loader.rs +++ b/src/config/loader.rs @@ -7,11 +7,15 @@ use std::path::Path; pub struct ConfigLoader; impl ConfigLoader { - pub fn load() -> Result { + pub fn load(path: Option<&str>) -> Result { let mut builder = ConfigBuilder::builder(); // Load from config file if specified - if let Ok(config_path) = env::var("CONFIG_PATH") { + let config_path = path + .map(String::from) + .or_else(|| env::var("CONFIG_PATH").ok()); + + if let Some(config_path) = config_path { builder = builder.add_source(File::with_name(&config_path)); } else { // Try to load default config files @@ -32,10 +36,10 @@ impl ConfigLoader { // Load environment-specific config if let Ok(env_name) = env::var("APP_ENV") { let env_configs = [ - format!("config.{}.yaml", env_name), - format!("config.{}.yml", env_name), - format!("{}.yaml", env_name), - format!("{}.yml", env_name), + format!("config.{env_name}.yaml"), + format!("config.{env_name}.yml"), + format!("{env_name}.yaml"), + format!("{env_name}.yml"), ]; for file in &env_configs { @@ -57,11 +61,11 @@ impl ConfigLoader { // Build and deserialize let config = builder .build() - .map_err(|e| MeiliBridgeError::Config(format!("Failed to build config: {}", e)))?; + .map_err(|e| MeiliBridgeError::Config(format!("Failed to build config: {e}")))?; - let config: Config = config.try_deserialize().map_err(|e| { - MeiliBridgeError::Config(format!("Failed to deserialize config: {}", e)) - })?; + let config: Config = config + .try_deserialize() + .map_err(|e| MeiliBridgeError::Config(format!("Failed to deserialize config: {e}")))?; // Validate configuration Self::validate(&config)?; @@ -105,13 +109,13 @@ impl ConfigLoader { for (i, task) in config.sync_tasks.iter().enumerate() { if task.table.is_empty() { - errors.push(format!("Sync task {} has empty table name", i)); + errors.push(format!("Sync task {i} has empty table name")); } if task.index.is_empty() { - errors.push(format!("Sync task {} has empty index name", i)); + errors.push(format!("Sync task {i} has empty index name")); } if task.options.batch_size == 0 { - errors.push(format!("Sync task {} batch_size must be > 0", i)); + errors.push(format!("Sync task {i} batch_size must be > 0")); } } @@ -139,8 +143,7 @@ impl ConfigLoader { /// Load configuration from a specific file pub fn load_from_file(path: &str) -> Result { - env::set_var("CONFIG_PATH", path); - Self::load() + Self::load(Some(path)) } /// Create a sample configuration file diff --git a/src/config/validation.rs b/src/config/validation.rs index c4fb98f..113a381 100644 --- a/src/config/validation.rs +++ b/src/config/validation.rs @@ -1,4 +1,4 @@ -use crate::config::{Condition, Config, FieldMapping, FieldTransform, SyncTaskConfig}; +use crate::config::{Condition, Config, FieldMapping, SyncTaskConfig}; use crate::error::Result; use crate::source::postgres::connection::PostgresConnector; use crate::source::postgres::full_sync::FullSyncHandler; @@ -136,13 +136,13 @@ impl ConfigValidator { } // Validate event types - if let Some(event_types) = &filter.event_types { - if event_types.is_empty() { - report.add_warning(format!( - "Empty event_types filter for table '{}' will filter out all events", - task.table - )); - } + if let Some(event_types) = &filter.event_types + && event_types.is_empty() + { + report.add_warning(format!( + "Empty event_types filter for table '{}' will filter out all events", + task.table + )); } Ok(()) @@ -299,7 +299,7 @@ impl ConfigValidator { // Create a connector to query schema let mut connector = PostgresConnector::new((**pg_config).clone()); if let Err(e) = connector.connect().await { - report.add_warning(format!("Cannot validate fields against schema: {}", e)); + report.add_warning(format!("Cannot validate fields against schema: {e}")); return Ok(()); } @@ -323,13 +323,19 @@ impl ConfigValidator { ); } - // Check if all referenced fields exist - for field in referenced_fields { - if !column_set.contains(&field) { - report.add_error(format!( - "Table '{}': Filter references non-existent field '{}'", - task.table, field - )); + // Check if referenced fields exist in mapping + if let Some(mapping) = &task.mapping { + if let Some(tables) = &mapping.tables.get(&task.table) { + if let Some(fields) = &tables.fields { + for field in referenced_fields { + if !fields.contains_key(&field) { + report.add_warning(format!( + "Table '{}': Filter condition references field '{}' which is not in the mapping", + task.table, field + )); + } + } + } } } } @@ -372,37 +378,37 @@ impl ConfigValidator { if let Some(transform) = &task.transform { if let Some(table_transforms) = transform.fields.get(&task.table) { for field_transform in table_transforms.values() { - match field_transform { - FieldTransform::Rename { from, .. } => { - if !column_set.contains(from) { - report.add_error(format!( - "Table '{}': Transform references non-existent field '{}'", - task.table, from - )); - } + if let crate::config::pipeline::FieldTransform::Extract { + from, + path, + .. + } = field_transform + { + if !column_set.contains(from) { + report.add_error(format!( + "Table '{}': Transform extracts from non-existent field '{}'", + task.table, from + )); } - FieldTransform::Convert { field, .. } => { - if !column_set.contains(field) { - report.add_error(format!( - "Table '{}': Transform references non-existent field '{}'", - task.table, field - )); - } + if path.is_empty() { + report.add_error(format!( + "Table '{}': Transform has empty extraction path", + task.table + )); } - _ => {} // Other transforms don't reference fields } } } } // Validate soft delete field - if let Some(soft_delete) = &task.soft_delete { - if !column_set.contains(&soft_delete.field) { - report.add_error(format!( - "Table '{}': Soft delete references non-existent field '{}'", - task.table, soft_delete.field - )); - } + if let Some(soft_delete) = &task.soft_delete + && !column_set.contains(&soft_delete.field) + { + report.add_error(format!( + "Table '{}': Soft delete references non-existent field '{}'", + task.table, soft_delete.field + )); } report.add_info(format!( diff --git a/src/delivery/checkpoint.rs b/src/delivery/checkpoint.rs index 00eecdd..7be5500 100644 --- a/src/delivery/checkpoint.rs +++ b/src/delivery/checkpoint.rs @@ -44,8 +44,7 @@ impl TransactionalCheckpoint { // Check if transaction already exists if txns.iter().any(|t| t.transaction_id == transaction_id) { return Err(MeiliBridgeError::Pipeline(format!( - "Transaction {} already exists", - transaction_id + "Transaction {transaction_id} already exists", ))); } @@ -72,7 +71,7 @@ impl TransactionalCheckpoint { .iter_mut() .find(|t| t.transaction_id == transaction_id) .ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Transaction {} not found", transaction_id)) + MeiliBridgeError::Pipeline(format!("Transaction {transaction_id} not found")) })?; if txn.prepared { @@ -119,15 +118,14 @@ impl TransactionalCheckpoint { .iter() .position(|t| t.transaction_id == transaction_id) .ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Transaction {} not found", transaction_id)) + MeiliBridgeError::Pipeline(format!("Transaction {transaction_id} not found")) })?; let txn = &mut txns[txn_index]; if !txn.prepared { return Err(MeiliBridgeError::Pipeline(format!( - "Transaction {} not prepared", - transaction_id + "Transaction {transaction_id} not prepared", ))); } @@ -138,7 +136,7 @@ impl TransactionalCheckpoint { // Load the checkpoint let checkpoint = self.storage.load(&txn.task_id).await?.ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Checkpoint not found for task {}", txn.task_id)) + MeiliBridgeError::Pipeline(format!("Checkpoint not found for task {0}", txn.task_id)) })?; // Update checkpoint metadata to mark as committed @@ -168,7 +166,7 @@ impl TransactionalCheckpoint { .iter() .position(|t| t.transaction_id == transaction_id) .ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Transaction {} not found", transaction_id)) + MeiliBridgeError::Pipeline(format!("Transaction {transaction_id} not found")) })?; let txn = &txns[txn_index]; @@ -224,10 +222,10 @@ impl TransactionalCheckpoint { if let Some(cp) = checkpoint { // Check if checkpoint is committed - if let Some(committed) = cp.metadata.get("committed").and_then(|v| v.as_bool()) { - if committed { - return Ok(Some(cp)); - } + if let Some(committed) = cp.metadata.get("committed").and_then(|v| v.as_bool()) + && committed + { + return Ok(Some(cp)); } } diff --git a/src/delivery/deduplication.rs b/src/delivery/deduplication.rs index 22a73a6..5057578 100644 --- a/src/delivery/deduplication.rs +++ b/src/delivery/deduplication.rs @@ -92,7 +92,7 @@ impl EventDeduplicator { if *count == 1 { self.key_set.remove(&oldest_key); } else { - self.key_set.insert(oldest_key.clone(), count - 1); + self.key_set.insert(oldest_key, count - 1); } } self.stats.window_evictions += 1; diff --git a/src/delivery/transaction.rs b/src/delivery/transaction.rs index 6785e86..b323626 100644 --- a/src/delivery/transaction.rs +++ b/src/delivery/transaction.rs @@ -5,7 +5,7 @@ use crate::models::Position; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; -use tokio::time::{timeout, Duration}; +use tokio::time::{Duration, timeout}; use tracing::{debug, error, info, warn}; /// Transaction state in two-phase commit @@ -56,8 +56,7 @@ impl TwoPhaseCommit { if txns.contains_key(&transaction_id) { return Err(MeiliBridgeError::Pipeline(format!( - "Transaction {} already exists", - transaction_id + "Transaction {transaction_id} already exists", ))); } @@ -81,7 +80,7 @@ impl TwoPhaseCommit { let mut txns = self.transactions.write().await; let txn = txns.get_mut(transaction_id).ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Transaction {} not found", transaction_id)) + MeiliBridgeError::Pipeline(format!("Transaction {transaction_id} not found")) })?; if txn.state != TransactionState::Started { @@ -103,7 +102,7 @@ impl TwoPhaseCommit { let mut txns = self.transactions.write().await; let txn = txns.get_mut(transaction_id).ok_or_else(|| { - MeiliBridgeError::Pipeline(format!("Transaction {} not found", transaction_id)) + MeiliBridgeError::Pipeline(format!("Transaction {transaction_id} not found")) })?; if txn.state != TransactionState::Prepared { diff --git a/src/destination/adapter.rs b/src/destination/adapter.rs index 0986582..0bbe14d 100644 --- a/src/destination/adapter.rs +++ b/src/destination/adapter.rs @@ -1,5 +1,5 @@ use crate::error::Result; -use crate::models::{stream_event::Event, Position}; +use crate::models::{Position, stream_event::Event}; use async_trait::async_trait; use serde_json::Value; use std::collections::HashMap; diff --git a/src/destination/circuit_breaker.rs b/src/destination/circuit_breaker.rs index f282edb..ac37aa3 100644 --- a/src/destination/circuit_breaker.rs +++ b/src/destination/circuit_breaker.rs @@ -53,7 +53,7 @@ impl MeilisearchCircuitBreaker { // Update metrics crate::metrics::CIRCUIT_BREAKER_CALLS - .with_label_values(&[&self.name, "rejected"]) + .with_label_values(&[self.name.as_str(), "rejected"]) .inc(); Err(CircuitBreakerError::CircuitOpen) @@ -76,7 +76,7 @@ impl MeilisearchCircuitBreaker { // Update metrics crate::metrics::CIRCUIT_BREAKER_CALLS - .with_label_values(&[&self.name, "success"]) + .with_label_values(&[self.name.as_str(), "success"]) .inc(); } Err(e) => { @@ -85,7 +85,7 @@ impl MeilisearchCircuitBreaker { // Update metrics crate::metrics::CIRCUIT_BREAKER_CALLS - .with_label_values(&[&self.name, "failure"]) + .with_label_values(&[self.name.as_str(), "failure"]) .inc(); } } @@ -168,7 +168,9 @@ impl CircuitBreakerBuilder { pub fn error_rate(self, _rate: f64) -> Self { // Note: circuit_breaker 0.1.1 doesn't support error rate, only consecutive failures - warn!("Error rate configuration not supported in circuit_breaker 0.1.1, using consecutive failures instead"); + warn!( + "Error rate configuration not supported in circuit_breaker 0.1.1, using consecutive failures instead" + ); self } diff --git a/src/destination/meilisearch/adapter.rs b/src/destination/meilisearch/adapter.rs index 6593024..3e42e32 100644 --- a/src/destination/meilisearch/adapter.rs +++ b/src/destination/meilisearch/adapter.rs @@ -173,7 +173,7 @@ impl MeilisearchAdapter { } Err(e) => { result.failed_count += doc_count; - result.add_failure(format!("Upsert error: {}", e)); + result.add_failure(format!("Upsert error: {e}")); } } } @@ -195,7 +195,7 @@ impl MeilisearchAdapter { } Err(e) => { result.failed_count += delete_count; - result.add_failure(format!("Delete error: {}", e)); + result.add_failure(format!("Delete error: {e}")); } } } @@ -379,7 +379,7 @@ impl DestinationAdapter for MeilisearchAdapter { } Err(e) => { result.failed_count += chunk.len(); - result.add_failure(format!("Import error: {}", e)); + result.add_failure(format!("Import error: {e}")); } } } @@ -427,8 +427,7 @@ impl DestinationAdapter for MeilisearchAdapter { Ok(()) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Index deletion failed: {:?}", - task_info + "Index deletion failed: {task_info:?}", ))) } } diff --git a/src/destination/meilisearch/batch_processor.rs b/src/destination/meilisearch/batch_processor.rs index 5a644d7..92518c0 100644 --- a/src/destination/meilisearch/batch_processor.rs +++ b/src/destination/meilisearch/batch_processor.rs @@ -1,5 +1,5 @@ use crate::error::{MeiliBridgeError, Result}; -use crate::models::{stream_event::Event, CdcEvent, EventType}; +use crate::models::{CdcEvent, EventType, stream_event::Event}; use serde_json::Value; use tracing::{debug, warn}; @@ -59,8 +59,7 @@ impl BatchProcessor { } } else { return Err(MeiliBridgeError::Meilisearch(format!( - "Missing primary key field '{}' in delete event", - pk_field + "Missing primary key field '{pk_field}' in delete event", ))); } } else { diff --git a/src/destination/meilisearch/client.rs b/src/destination/meilisearch/client.rs index 2c9da42..ef59038 100644 --- a/src/destination/meilisearch/client.rs +++ b/src/destination/meilisearch/client.rs @@ -37,8 +37,7 @@ impl MeilisearchClient { Ok(()) } Err(e) => Err(MeiliBridgeError::Meilisearch(format!( - "Failed to connect to Meilisearch: {}", - e + "Failed to connect to Meilisearch: {e}", ))), } } @@ -54,5 +53,5 @@ impl MeilisearchClient { /// Convert Meilisearch SDK errors to our error type pub fn convert_error(error: MeilisearchError) -> MeiliBridgeError { - MeiliBridgeError::Meilisearch(format!("{:?}", error)) + MeiliBridgeError::Meilisearch(format!("{error:?}")) } diff --git a/src/destination/meilisearch/protected_client.rs b/src/destination/meilisearch/protected_client.rs index 4ba01eb..3557b15 100644 --- a/src/destination/meilisearch/protected_client.rs +++ b/src/destination/meilisearch/protected_client.rs @@ -2,7 +2,7 @@ use crate::config::MeilisearchConfig; use crate::destination::circuit_breaker::{ CircuitBreakerBuilder, CircuitBreakerError, MeilisearchCircuitBreaker, }; -use crate::destination::meilisearch::client::{convert_error, MeilisearchClient}; +use crate::destination::meilisearch::client::{MeilisearchClient, convert_error}; use crate::error::{MeiliBridgeError, Result}; use meilisearch_sdk::indexes::Index; use serde_json::Value; @@ -118,8 +118,7 @@ impl ProtectedMeilisearchClient { .map_err(convert_error) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Failed to create index: {:?}", - task_info + "Failed to create index: {task_info:?}", ))) } } @@ -156,8 +155,7 @@ impl ProtectedMeilisearchClient { .map_err(convert_error) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Failed to create index: {:?}", - task_info + "Failed to create index: {task_info:?}", ))) } } @@ -198,8 +196,7 @@ impl ProtectedMeilisearchClient { Ok(()) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Add documents failed: {:?}", - task_info + "Add documents failed: {task_info:?}", ))) } } @@ -229,8 +226,7 @@ impl ProtectedMeilisearchClient { Ok(()) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Add documents failed: {:?}", - task_info + "Add documents failed: {task_info:?}", ))) } } @@ -261,8 +257,7 @@ impl ProtectedMeilisearchClient { Ok(()) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Delete documents failed: {:?}", - task_info + "Delete documents failed: {task_info:?}", ))) } } @@ -292,8 +287,7 @@ impl ProtectedMeilisearchClient { Ok(()) } else { Err(MeiliBridgeError::Meilisearch(format!( - "Delete documents failed: {:?}", - task_info + "Delete documents failed: {task_info:?}", ))) } } diff --git a/src/dlq/mod.rs b/src/dlq/mod.rs index 6327cbd..d63b293 100644 --- a/src/dlq/mod.rs +++ b/src/dlq/mod.rs @@ -8,7 +8,7 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{mpsc, RwLock}; +use tokio::sync::{RwLock, mpsc}; use tracing::{error, info, warn}; /// Dead letter queue entry @@ -246,8 +246,8 @@ impl DeadLetterQueue { let task_id = entry.task_id.clone(); warn!( - "Adding event to dead letter queue. Task: {}, Error: {}, Retries: {}", - entry.task_id, entry.error, entry.retry_count + "Adding event to dead letter queue. Task: {task_id}, Error: {0}, Retries: {retry_count}", + entry.error ); self.storage.store(entry).await?; @@ -266,7 +266,7 @@ impl DeadLetterQueue { let count = entries.len(); if count == 0 { - info!("No dead letter entries found for task: {}", task_id); + info!("No dead letter entries found for task: {task_id}"); return Ok(0); } @@ -274,10 +274,7 @@ impl DeadLetterQueue { MeiliBridgeError::Configuration("Reprocess channel not configured".to_string()) })?; - info!( - "Reprocessing {} dead letter entries for task: {}", - count, task_id - ); + info!("Reprocessing {count} dead letter entries for task: {task_id}",); for mut entry in entries { // Update retry information @@ -291,8 +288,7 @@ impl DeadLetterQueue { if let Err(e) = reprocess_tx.send(entry.clone()).await { error!("Failed to send entry for reprocessing: {}", e); return Err(MeiliBridgeError::Pipeline(format!( - "Failed to reprocess entry: {}", - e + "Failed to reprocess entry: {e}", ))); } @@ -312,10 +308,7 @@ impl DeadLetterQueue { /// Clear all entries for a task pub async fn clear_task(&self, task_id: &str) -> Result { let count = self.storage.clear_task(task_id).await?; - info!( - "Cleared {} dead letter entries for task: {}", - count, task_id - ); + info!("Cleared {count} dead letter entries for task: {task_id}",); Ok(count) } } diff --git a/src/dlq/redis_storage.rs b/src/dlq/redis_storage.rs index 98dc096..294c6f2 100644 --- a/src/dlq/redis_storage.rs +++ b/src/dlq/redis_storage.rs @@ -14,7 +14,7 @@ pub struct RedisDlqStorage { impl RedisDlqStorage { pub fn new(redis_url: &str, key_prefix: String) -> Result { let client = Client::open(redis_url).map_err(|e| { - MeiliBridgeError::Configuration(format!("Failed to create Redis client: {}", e)) + MeiliBridgeError::Configuration(format!("Failed to create Redis client: {e}")) })?; Ok(Self { client, key_prefix }) @@ -61,10 +61,10 @@ impl DlqStorage for RedisDlqStorage { .zadd(&task_key, &entry.id, entry.created_at.timestamp()) // Add to all entries index .zadd(&all_key, &entry.id, entry.created_at.timestamp()) - .query_async::<_, ()>(&mut conn) + .query_async::<()>(&mut conn) .await .map_err(|e| { - MeiliBridgeError::Redis(format!("Failed to store dead letter entry: {}", e)) + MeiliBridgeError::Redis(format!("Failed to store dead letter entry: {e}")) })?; // Update metrics @@ -86,7 +86,7 @@ impl DlqStorage for RedisDlqStorage { let entry_ids: Vec = conn .zrange(&task_key, 0, (limit - 1) as isize) .await - .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get task entries: {}", e)))?; + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get task entries: {e}")))?; if entry_ids.is_empty() { return Ok(vec![]); @@ -110,7 +110,7 @@ impl DlqStorage for RedisDlqStorage { let entry_data: Option = conn .get(&entry_key) .await - .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get entry: {}", e)))?; + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get entry: {e}")))?; match entry_data { Some(data) => { @@ -136,9 +136,9 @@ impl DlqStorage for RedisDlqStorage { .del(&entry_key) .zrem(&task_key, id) .zrem(&all_key, id) - .query_async::<_, ()>(&mut conn) + .query_async::<()>(&mut conn) .await - .map_err(|e| MeiliBridgeError::Redis(format!("Failed to remove entry: {}", e)))?; + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to remove entry: {e}")))?; // Update metrics self.update_dlq_size_metric(&entry.task_id).await?; @@ -160,7 +160,7 @@ impl DlqStorage for RedisDlqStorage { let entry_ids: Vec = conn .zrange(&all_key, 0, -1) .await - .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get all entries: {}", e)))?; + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get all entries: {e}")))?; let mut entries_by_task = HashMap::new(); let mut entries_by_error = HashMap::new(); @@ -209,7 +209,7 @@ impl DlqStorage for RedisDlqStorage { let entry_ids: Vec = conn .zrange(&task_key, 0, -1) .await - .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get task entries: {}", e)))?; + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get task entries: {e}")))?; let count = entry_ids.len(); @@ -227,8 +227,8 @@ impl DlqStorage for RedisDlqStorage { // Clear the task index pipe.del(&task_key); - pipe.query_async::<_, ()>(&mut conn).await.map_err(|e| { - MeiliBridgeError::Redis(format!("Failed to clear task entries: {}", e)) + pipe.query_async::<()>(&mut conn).await.map_err(|e| { + MeiliBridgeError::Redis(format!("Failed to clear task entries: {e}")) })?; info!( @@ -251,9 +251,10 @@ impl RedisDlqStorage { let mut conn = self.get_connection().await?; let task_key = self.task_index_key(task_id); - let size: usize = conn.zcard(&task_key).await.map_err(|e| { - MeiliBridgeError::Redis(format!("Failed to get task queue size: {}", e)) - })?; + let size: usize = conn + .zcard(&task_key) + .await + .map_err(|e| MeiliBridgeError::Redis(format!("Failed to get task queue size: {e}")))?; crate::metrics::DEAD_LETTER_QUEUE_SIZE .with_label_values(&[task_id]) diff --git a/src/error/retry.rs b/src/error/retry.rs index 609a0e3..b5d9aeb 100644 --- a/src/error/retry.rs +++ b/src/error/retry.rs @@ -78,7 +78,7 @@ where let mut actual_delay = delay_ms; if config.jitter { use rand::Rng; - let jitter = rand::thread_rng().gen_range(0..=delay_ms / 4); + let jitter = rand::rng().random_range(0..=delay_ms / 4); actual_delay = delay_ms.saturating_add(jitter); } diff --git a/src/health/mod.rs b/src/health/mod.rs index cac91df..4521c14 100644 --- a/src/health/mod.rs +++ b/src/health/mod.rs @@ -164,7 +164,7 @@ impl HealthCheck for PostgresHealthCheck { { let mut connector = self.connector.write().await; if let Err(e) = connector.ensure_connected().await { - return HealthCheckResult::unhealthy(format!("Failed to connect: {}", e)); + return HealthCheckResult::unhealthy(format!("Failed to connect: {e}")); } } @@ -185,10 +185,10 @@ impl HealthCheck for PostgresHealthCheck { serde_json::json!(pool.status().available), ) } - Err(e) => HealthCheckResult::unhealthy(format!("Query failed: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("Query failed: {e}")), } } - Err(e) => HealthCheckResult::unhealthy(format!("Failed to get client: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("Failed to get client: {e}")), } } @@ -217,7 +217,7 @@ impl HealthCheck for MeilisearchHealthCheck { ) { Ok(client) => client, Err(e) => { - return HealthCheckResult::unhealthy(format!("Failed to create client: {}", e)) + return HealthCheckResult::unhealthy(format!("Failed to create client: {e}")); } }; @@ -226,7 +226,7 @@ impl HealthCheck for MeilisearchHealthCheck { Ok(health) => { HealthCheckResult::healthy().with_detail("status", serde_json::json!(health.status)) } - Err(e) => HealthCheckResult::unhealthy(format!("Health check failed: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("Health check failed: {e}")), } } @@ -252,7 +252,7 @@ impl HealthCheck for RedisHealthCheck { // Try to connect to Redis match redis::Client::open(self.url.as_str()) { Ok(client) => { - match client.get_tokio_connection().await { + match client.get_multiplexed_async_connection().await { Ok(mut conn) => { // Execute a PING command let ping_result: Result = @@ -276,8 +276,10 @@ impl HealthCheck for RedisHealthCheck { { if let Some(version) = version_line.split(':').nth(1) { result = result.with_detail( - "version", - serde_json::json!(version.trim()), + "redis_version", + serde_json::Value::String( + version.trim().to_string(), + ), ); } } @@ -288,13 +290,13 @@ impl HealthCheck for RedisHealthCheck { Ok(_) => { HealthCheckResult::degraded("Unexpected PING response".to_string()) } - Err(e) => HealthCheckResult::unhealthy(format!("PING failed: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("PING failed: {e}")), } } - Err(e) => HealthCheckResult::unhealthy(format!("Connection failed: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("Connection failed: {e}")), } } - Err(e) => HealthCheckResult::unhealthy(format!("Failed to create client: {}", e)), + Err(e) => HealthCheckResult::unhealthy(format!("Failed to create client: {e}")), } } @@ -333,7 +335,7 @@ impl HealthCheck for ApiHealthCheck { } Err(e) => { // API might not be accessible locally, but that doesn't mean it's unhealthy - HealthCheckResult::degraded(format!("Could not reach API: {}", e)) + HealthCheckResult::degraded(format!("Could not reach API: {e}")) .with_detail("port", serde_json::json!(self.port)) } } diff --git a/src/lib.rs b/src/lib.rs index 28dc1d0..eae7ca9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::collapsible_if)] + pub mod api; pub mod checkpoint; pub mod config; diff --git a/src/main.rs b/src/main.rs index f25db7e..86fc957 100644 --- a/src/main.rs +++ b/src/main.rs @@ -116,7 +116,7 @@ fn init_tracing(log_level: &str) { .fmt_fields(tracing_subscriber::fmt::format::DefaultFields::new()) .event_format(CustomFormatter); - let filter = format!("meilibridge={},info", log_level); + let filter = format!("meilibridge={log_level},info"); let filter_layer = tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(filter)); @@ -167,7 +167,7 @@ where } else { name }; - write!(writer, "[{:8}", truncated_name)?; + write!(writer, "[{truncated_name:8}")?; } else { write!(writer, "[{:8}", "unnamed")?; } @@ -178,7 +178,7 @@ where .strip_prefix("ThreadId(") .and_then(|s| s.strip_suffix(")")) { - write!(writer, "-{}] ", id_num)?; + write!(writer, "-{id_num}] ")?; } else { write!(writer, "-??] ")?; } @@ -198,7 +198,7 @@ fn load_config(path: Option<&str>) -> Result { } None => { info!("Loading configuration from default locations"); - ConfigLoader::load() + ConfigLoader::load(None) } } } @@ -287,7 +287,7 @@ async fn run_service(config: Config) -> Result<()> { .with_health_registry(health_registry.clone()); // If using PostgreSQL, create a statement cache reference - if let Some(meilibridge::config::SourceConfig::PostgreSQL(ref pg_config)) = &config.source { + if let Some(meilibridge::config::SourceConfig::PostgreSQL(pg_config)) = &config.source { let cache_config = meilibridge::source::postgres::CacheConfig { max_size: pg_config.statement_cache.max_size, enabled: pg_config.statement_cache.enabled, @@ -300,7 +300,7 @@ async fn run_service(config: Config) -> Result<()> { // Also check multiple sources for PostgreSQL (use first one found) for named_source in &config.sources { - if let meilibridge::config::SourceConfig::PostgreSQL(ref pg_config) = &named_source.config { + if let meilibridge::config::SourceConfig::PostgreSQL(pg_config) = &named_source.config { let cache_config = meilibridge::source::postgres::CacheConfig { max_size: pg_config.statement_cache.max_size, enabled: pg_config.statement_cache.enabled, diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index c4e35bd..4f419b9 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -1,7 +1,7 @@ use lazy_static::lazy_static; use prometheus::{ - register_counter_vec, register_gauge_vec, register_histogram_vec, CounterVec, Encoder, - GaugeVec, HistogramVec, TextEncoder, + CounterVec, Encoder, GaugeVec, HistogramVec, TextEncoder, register_counter_vec, + register_gauge_vec, register_histogram_vec, }; use std::time::Duration; diff --git a/src/models/progress.rs b/src/models/progress.rs index 61f72be..17512b1 100644 --- a/src/models/progress.rs +++ b/src/models/progress.rs @@ -52,9 +52,9 @@ impl Position { impl fmt::Display for Position { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Position::PostgreSQL { lsn } => write!(f, "pg:{}", lsn), - Position::MySQL { file, position } => write!(f, "mysql:{}:{}", file, position), - Position::MongoDB { resume_token } => write!(f, "mongo:{}", resume_token), + Position::PostgreSQL { lsn } => write!(f, "pg:{lsn}"), + Position::MySQL { file, position } => write!(f, "mysql:{file}:{position}"), + Position::MongoDB { resume_token } => write!(f, "mongo:{resume_token}"), } } } diff --git a/src/pipeline/adaptive_batching.rs b/src/pipeline/adaptive_batching.rs index 286cad9..a606fe7 100644 --- a/src/pipeline/adaptive_batching.rs +++ b/src/pipeline/adaptive_batching.rs @@ -57,7 +57,7 @@ struct MemoryMonitor { impl MemoryMonitor { fn new(threshold_percentage: f64) -> Self { let mut system = System::new_with_specifics( - RefreshKind::new().with_memory(MemoryRefreshKind::everything()), + RefreshKind::nothing().with_memory(MemoryRefreshKind::everything()), ); system.refresh_memory(); diff --git a/src/pipeline/at_least_once_helpers.rs b/src/pipeline/at_least_once_helpers.rs index 7c54ced..63a5e54 100644 --- a/src/pipeline/at_least_once_helpers.rs +++ b/src/pipeline/at_least_once_helpers.rs @@ -1,7 +1,7 @@ //! Helper functions for at-least-once delivery in the pipeline use crate::delivery::DeduplicationKey; -use crate::models::{stream_event::Event, Position}; +use crate::models::{Position, stream_event::Event}; /// Extract position from event pub fn extract_position_from_event(event: &Event) -> Option { diff --git a/src/pipeline/backpressure.rs b/src/pipeline/backpressure.rs index b252c9b..0ab8dc9 100644 --- a/src/pipeline/backpressure.rs +++ b/src/pipeline/backpressure.rs @@ -2,8 +2,8 @@ use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{mpsc, RwLock}; -use tokio::time::{interval, Duration}; +use tokio::sync::{RwLock, mpsc}; +use tokio::time::{Duration, interval}; use tracing::{debug, info, warn}; /// Configuration for backpressure management diff --git a/src/pipeline/cdc_coordinator.rs b/src/pipeline/cdc_coordinator.rs index cf1ba99..ca07aae 100644 --- a/src/pipeline/cdc_coordinator.rs +++ b/src/pipeline/cdc_coordinator.rs @@ -5,9 +5,9 @@ use crate::source::adapter::SourceAdapter; use futures::StreamExt; use std::collections::HashMap; use std::sync::Arc; +use tokio::sync::RwLock; use tokio::sync::mpsc; use tokio::sync::watch; -use tokio::sync::RwLock; use tracing::{debug, error, info, warn}; /// Coordinates CDC event consumption and distribution to sync tasks diff --git a/src/pipeline/filter.rs b/src/pipeline/filter.rs index 938a99f..94a48f4 100644 --- a/src/pipeline/filter.rs +++ b/src/pipeline/filter.rs @@ -1,6 +1,6 @@ use crate::config::FilterConfig; use crate::error::Result; -use crate::models::{stream_event::Event, EventType}; +use crate::models::{EventType, stream_event::Event}; use serde_json::Value; use std::collections::HashMap; use tracing::debug; @@ -123,17 +123,17 @@ impl EventFilter { /// Check if a table is allowed fn is_table_allowed(&self, table: &str) -> bool { // If whitelist is defined, table must be in it - if let Some(whitelist) = &self.config.tables.whitelist { - if !whitelist.contains(&table.to_string()) { - return false; - } + if let Some(whitelist) = &self.config.tables.whitelist + && !whitelist.contains(&table.to_string()) + { + return false; } // If blacklist is defined, table must not be in it - if let Some(blacklist) = &self.config.tables.blacklist { - if blacklist.contains(&table.to_string()) { - return false; - } + if let Some(blacklist) = &self.config.tables.blacklist + && blacklist.contains(&table.to_string()) + { + return false; } true diff --git a/src/pipeline/mapper.rs b/src/pipeline/mapper.rs index b2e7baa..733b7ce 100644 --- a/src/pipeline/mapper.rs +++ b/src/pipeline/mapper.rs @@ -54,7 +54,6 @@ impl FieldMapper { if let Some(obj) = data.as_object() { let data_map: HashMap = obj.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); - let mapped = self.map_fields(data_map, field_mappings)?; data = Value::Object(mapped.into_iter().collect()); } @@ -148,7 +147,7 @@ impl FieldMapper { let prefix = self.config.unmapped_fields_prefix.as_deref().unwrap_or("_"); for (k, v) in data { if !mapped_sources.contains(&k) { - result.insert(format!("{}{}", prefix, k), v); + result.insert(format!("{prefix}{k}"), v); } } } diff --git a/src/pipeline/memory_monitor.rs b/src/pipeline/memory_monitor.rs index 1223881..5475f59 100644 --- a/src/pipeline/memory_monitor.rs +++ b/src/pipeline/memory_monitor.rs @@ -1,8 +1,8 @@ use crate::error::Result; -use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use tokio::sync::mpsc; -use tokio::time::{interval, Duration}; +use tokio::time::{Duration, interval}; use tracing::{info, warn}; /// Tracks memory usage and enforces limits diff --git a/src/pipeline/orchestrator.rs b/src/pipeline/orchestrator.rs index 6102cb6..55850e9 100644 --- a/src/pipeline/orchestrator.rs +++ b/src/pipeline/orchestrator.rs @@ -8,14 +8,14 @@ use crate::metrics; use crate::models::event::{ Event as ModelsEvent, EventData as ModelsEventData, EventType as ModelsEventType, }; -use crate::models::{stream_event::Event, Position}; use crate::models::{EventId, EventMetadata, EventSource}; +use crate::models::{Position, stream_event::Event}; +use crate::pipeline::{AdaptiveBatchingManager, MemoryMonitor}; use crate::pipeline::{ - filter::EventFilter, mapper::FieldMapper, soft_delete::SoftDeleteHandler, - transformer::EventTransformer, BackpressureConfig, BackpressureEvent, BackpressureManager, - CdcCoordinator, ParallelTableProcessor, WorkStealingCoordinator, + BackpressureConfig, BackpressureEvent, BackpressureManager, CdcCoordinator, + ParallelTableProcessor, WorkStealingCoordinator, filter::EventFilter, mapper::FieldMapper, + soft_delete::SoftDeleteHandler, transformer::EventTransformer, }; -use crate::pipeline::{AdaptiveBatchingManager, MemoryMonitor}; use crate::source::adapter::SourceAdapter; use crate::source::postgres::PostgresAdapter; use chrono::Utc; @@ -23,8 +23,8 @@ use futures::StreamExt; use serde_json::Value; use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{mpsc, watch, RwLock}; -use tokio::time::{interval, Duration}; +use tokio::sync::{RwLock, mpsc, watch}; +use tokio::time::{Duration, interval}; use tracing::{debug, error, info, trace, warn}; /// Parameters for batch processing with at-least-once delivery @@ -581,7 +581,7 @@ impl PipelineOrchestrator { if let Err(e) = checkpoint_manager .cleanup_checkpoints( active_task_ids.clone(), - checkpoint_retention_config.max_checkpoints_per_task, + 100, // Max checkpoints per task ) .await { @@ -639,8 +639,7 @@ impl PipelineOrchestrator { // Get the source adapter let source_adapter = self.source_adapters.get_mut(&source_name).ok_or_else(|| { MeiliBridgeError::Pipeline(format!( - "Source adapter '{}' not found for sync tasks", - source_name + "Source adapter '{source_name}' not found for sync tasks", )) })?; @@ -1707,7 +1706,7 @@ impl PipelineOrchestrator { .at_least_once_manager .rollback(&transaction_id) .await?; - return Err(MeiliBridgeError::Pipeline(format!("Send failed: {}", e))); + return Err(MeiliBridgeError::Pipeline(format!("Send failed: {e}"))); } } } @@ -1828,7 +1827,7 @@ impl PipelineOrchestrator { None => { return Err(MeiliBridgeError::Pipeline( "No response from destination".to_string(), - )) + )); } } @@ -2068,7 +2067,7 @@ impl PipelineOrchestrator { .sync_tasks .iter() .find(|t| t.id == task_id) - .ok_or_else(|| MeiliBridgeError::NotFound(format!("Task '{}' not found", task_id)))? + .ok_or_else(|| MeiliBridgeError::NotFound(format!("Task '{task_id}' not found")))? .clone(); info!("Triggering full sync for task '{}'", task_id); diff --git a/src/pipeline/parallel_processor.rs b/src/pipeline/parallel_processor.rs index d850822..f747d6f 100644 --- a/src/pipeline/parallel_processor.rs +++ b/src/pipeline/parallel_processor.rs @@ -5,8 +5,8 @@ use crate::pipeline::{ transformer::EventTransformer, }; use std::sync::Arc; -use tokio::sync::{mpsc, RwLock, Semaphore}; -use tokio::time::{interval, Duration}; +use tokio::sync::{RwLock, Semaphore, mpsc}; +use tokio::time::{Duration, interval}; use tracing::{debug, info, warn}; /// Configuration for parallel processing @@ -385,27 +385,19 @@ impl WorkStealingCoordinator { Some((small_table, small_proc, small_size)), Some((large_table, large_proc, large_size)), ) = (queue_info.first(), queue_info.last()) + && *large_size > *small_size + 100 { - if *large_size > *small_size + 100 { - // Only steal if significant imbalance - let steal_count = (large_size - small_size) / 2; - let stolen = large_proc.steal_events(steal_count).await; - - if !stolen.is_empty() { - debug!( - "Work stealing: Moved {} events from '{}' to '{}'", - stolen.len(), - large_table, - small_table - ); - - // Record metrics - metrics::WORK_STEALING_OPERATIONS - .with_label_values(&[large_table, small_table]) - .inc(); - - small_proc.enqueue_events(stolen).await; - } + // Only steal if significant imbalance + debug!( + "Attempting work stealing: {} ({}) -> {} ({})", + large_table, large_size, small_table, small_size + ); + + // Try to steal a batch from the largest queue + let stolen = large_proc.steal_events(50).await; + if !stolen.is_empty() { + debug!("Stole {} events from {}", stolen.len(), large_table); + small_proc.enqueue_events(stolen).await; } } } diff --git a/src/pipeline/soft_delete.rs b/src/pipeline/soft_delete.rs index 9479362..7af073b 100644 --- a/src/pipeline/soft_delete.rs +++ b/src/pipeline/soft_delete.rs @@ -1,7 +1,7 @@ //! Soft delete handling for the pipeline use crate::config::SoftDeleteConfig; -use crate::models::{stream_event::Event, EventType}; +use crate::models::{EventType, stream_event::Event}; use serde_json::Value; use tracing::{debug, trace}; @@ -31,20 +31,19 @@ impl SoftDeleteHandler { } // Check if the field value matches any delete value - if let Some(field_value) = cdc_event.data.get(&self.config.field) { - if self.is_soft_deleted(field_value) { - debug!( - "Transforming UPDATE to DELETE for table '{}' due to soft delete field '{}' = {:?}", - cdc_event.table, self.config.field, field_value - ); + if let Some(field_value) = cdc_event.data.get(&self.config.field) + && self.is_soft_deleted(field_value) + { + debug!( + "Transforming UPDATE to DELETE for table '{}' due to soft delete field '{}' = {:?}", + cdc_event.table, self.config.field, field_value + ); - // Transform to a Delete event - return Some(Event::Delete { - table: cdc_event.table.clone(), - old_data: Value::Object(cdc_event.data.clone().into_iter().collect()), - position: cdc_event.position.clone(), - }); - } + // Transform to DELETE event + let mut delete_event = cdc_event.clone(); + delete_event.event_type = crate::models::event::EventType::Delete; + // For DELETE, we only need the primary key, but keeping data is fine + return Some(Event::Cdc(delete_event)); } Some(event) @@ -61,20 +60,20 @@ impl SoftDeleteHandler { } // Check if the field value matches any delete value - if let Some(field_value) = new_data.get(&self.config.field) { - if self.is_soft_deleted(field_value) { - debug!( - "Transforming UPDATE to DELETE for table '{}' due to soft delete field '{}' = {:?}", - table, self.config.field, field_value - ); + if let Some(field_value) = new_data.get(&self.config.field) + && self.is_soft_deleted(field_value) + { + debug!( + "Transforming UPDATE to DELETE for table '{}' due to soft delete field '{}' = {:?}", + table, self.config.field, field_value + ); - // Transform to a Delete event - return Some(Event::Delete { - table: table.clone(), - old_data: old_data.clone(), - position: position.clone(), - }); - } + // Transform to DELETE event + return Some(Event::Delete { + table: table.clone(), + old_data: old_data.clone(), + position: position.clone(), + }); } Some(event) @@ -89,15 +88,14 @@ impl SoftDeleteHandler { } // Check if the field value matches any delete value - if let Some(field_value) = data.get(&self.config.field) { - if self.is_soft_deleted(field_value) { - trace!( - "Filtering out soft-deleted record from full sync for table '{}': {} = {:?}", - table, self.config.field, field_value - ); - // Filter out soft-deleted records during full sync - return None; - } + if let Some(field_value) = data.get(&self.config.field) + && self.is_soft_deleted(field_value) + { + trace!( + "Filtering out soft-deleted record from full sync for table '{}': {} = {:?}", + table, self.config.field, field_value + ); + return None; } Some(event) diff --git a/src/pipeline/streaming_processor.rs b/src/pipeline/streaming_processor.rs index 6a41492..712ca85 100644 --- a/src/pipeline/streaming_processor.rs +++ b/src/pipeline/streaming_processor.rs @@ -34,7 +34,7 @@ impl StreamingJsonProcessor { // Parse JSON in streaming mode let mut de = Deserializer::from_reader(limited_reader); let value = Value::deserialize(&mut de) - .map_err(|e| MeiliBridgeError::Validation(format!("Failed to parse JSON: {}", e)))?; + .map_err(|e| MeiliBridgeError::Validation(format!("Failed to parse JSON: {e}")))?; // Estimate memory usage let estimated_size = Self::estimate_value_size(&value); @@ -209,7 +209,7 @@ impl ZeroCopyEventRouter { // Extract table name without parsing entire document if let Some(table_start) = find_json_string_value(event_data, b"\"table\"") { let table = std::str::from_utf8(&event_data[table_start.0..table_start.1]) - .map_err(|e| MeiliBridgeError::Validation(format!("Invalid UTF-8: {}", e)))?; + .map_err(|e| MeiliBridgeError::Validation(format!("Invalid UTF-8: {e}")))?; Ok(EventView { table, @@ -233,7 +233,7 @@ impl<'a> EventView<'a> { /// Parse the full event only when needed pub fn parse_full(&self) -> Result { serde_json::from_slice(self.raw_data) - .map_err(|e| MeiliBridgeError::Validation(format!("Failed to parse event: {}", e))) + .map_err(|e| MeiliBridgeError::Validation(format!("Failed to parse event: {e}"))) } } diff --git a/src/pipeline/transformer.rs b/src/pipeline/transformer.rs index 57d4b0b..9525aeb 100644 --- a/src/pipeline/transformer.rs +++ b/src/pipeline/transformer.rs @@ -154,7 +154,7 @@ impl EventTransformer { .parse::() .map(|n| Value::Number(serde_json::Number::from_f64(n).unwrap())) .map_err(|_| { - MeiliBridgeError::Pipeline(format!("Cannot convert '{}' to number", s)) + MeiliBridgeError::Pipeline(format!("Cannot convert '{s}' to number")) }), _ => Err(MeiliBridgeError::Pipeline( "Cannot convert value to number".to_string(), @@ -171,8 +171,7 @@ impl EventTransformer { other => Value::Array(vec![other.clone()]), }), _ => Err(MeiliBridgeError::Pipeline(format!( - "Unknown type conversion: {}", - to_type + "Unknown type conversion: {to_type}", ))), } } diff --git a/src/recovery/dead_letter.rs b/src/recovery/dead_letter.rs index d277c26..d8cb7e6 100644 --- a/src/recovery/dead_letter.rs +++ b/src/recovery/dead_letter.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use std::sync::Arc; use tokio::fs; use tokio::io::AsyncWriteExt; -use tokio::sync::{mpsc, RwLock}; +use tokio::sync::{RwLock, mpsc}; use tracing::{debug, error, info, warn}; /// Dead letter entry @@ -163,8 +163,7 @@ impl FileDeadLetterStorage { } fn get_entry_path(&self, task_id: &str, entry_id: &str) -> PathBuf { - self.get_task_dir(task_id) - .join(format!("{}.json", entry_id)) + self.get_task_dir(task_id).join(format!("{entry_id}.json")) } } diff --git a/src/recovery/retry.rs b/src/recovery/retry.rs index 524c92c..a853ec1 100644 --- a/src/recovery/retry.rs +++ b/src/recovery/retry.rs @@ -90,8 +90,8 @@ impl ExponentialBackoff { // Apply jitter if enabled if self.policy.jitter { use rand::Rng; - let mut rng = rand::thread_rng(); - let jitter_factor = rng.gen_range(0.5..1.5); + let mut rng = rand::rng(); + let jitter_factor = rng.random_range(0.5..1.5); delay = delay.mul_f64(jitter_factor); } diff --git a/src/recovery/retry_v2.rs b/src/recovery/retry_v2.rs index bc66049..b45baba 100644 --- a/src/recovery/retry_v2.rs +++ b/src/recovery/retry_v2.rs @@ -90,8 +90,8 @@ impl ExponentialBackoff { // Apply jitter if enabled if self.policy.jitter { use rand::Rng; - let mut rng = rand::thread_rng(); - let jitter_factor = rng.gen_range(0.5..1.5); + let mut rng = rand::rng(); + let jitter_factor = rng.random_range(0.5..1.5); delay = delay.mul_f64(jitter_factor); } diff --git a/src/source/postgres/adapter.rs b/src/source/postgres/adapter.rs index 48cc74a..d1eb5bb 100644 --- a/src/source/postgres/adapter.rs +++ b/src/source/postgres/adapter.rs @@ -141,7 +141,7 @@ impl SourceAdapter for PostgresAdapter { // Parse LSN let pg_lsn: PgLsn = lsn .parse() - .map_err(|_| MeiliBridgeError::Source(format!("Invalid LSN: {}", lsn)))?; + .map_err(|_| MeiliBridgeError::Source(format!("Invalid LSN: {lsn}")))?; self.last_lsn = Some(pg_lsn); debug!("Set start position to: {}", lsn); @@ -159,7 +159,7 @@ impl SourceAdapter for PostgresAdapter { // Parse LSN let pg_lsn: PgLsn = lsn .parse() - .map_err(|_| MeiliBridgeError::Source(format!("Invalid LSN: {}", lsn)))?; + .map_err(|_| MeiliBridgeError::Source(format!("Invalid LSN: {lsn}")))?; self.last_lsn = Some(pg_lsn); debug!("Acknowledged position: {}", lsn); diff --git a/src/source/postgres/connection.rs b/src/source/postgres/connection.rs index 8fe09d3..d2a2018 100644 --- a/src/source/postgres/connection.rs +++ b/src/source/postgres/connection.rs @@ -34,14 +34,14 @@ impl PostgresConnector { // Test the connection let client = pool.get().await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to get connection from pool: {}", e)) + MeiliBridgeError::Source(format!("Failed to get connection from pool: {e}")) })?; // Verify we can query the database client .simple_query("SELECT 1") .await - .map_err(|e| MeiliBridgeError::Source(format!("Connection test failed: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Connection test failed: {e}")))?; self.pool = Some(pool); info!("Successfully connected to PostgreSQL"); @@ -60,18 +60,16 @@ impl PostgresConnector { .max_size(self.config.pool.max_size as usize) .runtime(Runtime::Tokio1) .build() - .map_err(|e| MeiliBridgeError::Source(format!("Failed to create pool: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Failed to create pool: {e}")))?; Ok(pool) } fn build_pg_config(&self) -> Result { let mut config = match &self.config.connection { - PostgreSQLConnection::ConnectionString(conn_str) => { - conn_str.parse::().map_err(|e| { - MeiliBridgeError::Config(format!("Invalid connection string: {}", e)) - })? - } + PostgreSQLConnection::ConnectionString(conn_str) => conn_str + .parse::() + .map_err(|e| MeiliBridgeError::Config(format!("Invalid connection string: {e}")))?, PostgreSQLConnection::Parameters { host, port, @@ -103,7 +101,7 @@ impl PostgresConnector { .ok_or_else(|| MeiliBridgeError::Source("Not connected to PostgreSQL".to_string()))?; pool.get().await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to get connection from pool: {}", e)) + MeiliBridgeError::Source(format!("Failed to get connection from pool: {e}")) }) } @@ -120,7 +118,7 @@ impl PostgresConnector { config.keepalives_retries(3); let (client, connection) = config.connect(NoTls).await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to create replication connection: {}", e)) + MeiliBridgeError::Source(format!("Failed to create replication connection: {e}")) })?; // Spawn connection handler with error logging @@ -153,7 +151,7 @@ impl PostgresConnector { // rather than using the pooled one directly let config = self.build_pg_config()?; let (client, connection) = config.connect(NoTls).await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to create cached connection: {}", e)) + MeiliBridgeError::Source(format!("Failed to create cached connection: {e}")) })?; // Spawn connection handler @@ -220,8 +218,7 @@ impl ReplicationSlotManager { } Ok(None) => Ok(None), Err(e) => Err(MeiliBridgeError::Source(format!( - "Failed to get slot LSN: {}", - e + "Failed to get slot LSN: {e}", ))), } } @@ -247,7 +244,7 @@ impl ReplicationSlotManager { let drop_query = format!("SELECT pg_drop_replication_slot('{}')", self.slot_name); client.execute(&drop_query, &[]).await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to drop slot: {}", e)) + MeiliBridgeError::Source(format!("Failed to drop slot: {e}")) })?; } } @@ -256,8 +253,7 @@ impl ReplicationSlotManager { } Err(e) => { return Err(MeiliBridgeError::Source(format!( - "Failed to check slot: {}", - e + "Failed to check slot: {e}", ))); } } @@ -270,7 +266,7 @@ impl ReplicationSlotManager { client .execute(&query, &[]) .await - .map_err(|e| MeiliBridgeError::Source(format!("Failed to create slot: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Failed to create slot: {e}")))?; info!("Created replication slot '{}'", self.slot_name); Ok(()) @@ -292,8 +288,7 @@ impl ReplicationSlotManager { } Err(e) => { return Err(MeiliBridgeError::Source(format!( - "Failed to check publication: {}", - e + "Failed to check publication: {e}", ))); } } @@ -309,9 +304,10 @@ impl ReplicationSlotManager { self.publication_name, table_list ); - client.execute(&query, &[]).await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to create publication: {}", e)) - })?; + client + .execute(&query, &[]) + .await + .map_err(|e| MeiliBridgeError::Source(format!("Failed to create publication: {e}")))?; info!("Created publication '{}'", self.publication_name); Ok(()) diff --git a/src/source/postgres/full_sync.rs b/src/source/postgres/full_sync.rs index 33dfd48..ea36ceb 100644 --- a/src/source/postgres/full_sync.rs +++ b/src/source/postgres/full_sync.rs @@ -27,14 +27,14 @@ impl FullSyncHandler { let cached_conn = self.connector.get_cached_connection().await?; // Get total count first (using cached statement) - let count_query = format!("SELECT COUNT(*) FROM {}", table); + let count_query = format!("SELECT COUNT(*) FROM {table}"); let count_row = cached_conn.query_one::<()>(&count_query, &[]).await?; let total_count: i64 = count_row.get(0); info!("Total rows to sync for {}: {}", table, total_count); // Prepare the main query once (will be cached) - let select_query = format!("SELECT row_to_json(t) FROM {} t LIMIT $1 OFFSET $2", table); + let select_query = format!("SELECT row_to_json(t) FROM {table} t LIMIT $1 OFFSET $2"); let mut offset = 0i64; let mut synced_count = 0i64; @@ -76,7 +76,11 @@ impl FullSyncHandler { let stats = cached_conn.cache_stats().await; info!( "Full sync completed for {}. Synced {} rows. Cache stats: {} hits, {} misses, {:.2}% hit rate", - table, synced_count, stats.hits, stats.misses, stats.hit_rate * 100.0 + table, + synced_count, + stats.hits, + stats.misses, + stats.hit_rate * 100.0 ); // Export metrics diff --git a/src/source/postgres/pgoutput.rs b/src/source/postgres/pgoutput.rs index 7d38487..bbf8ecd 100644 --- a/src/source/postgres/pgoutput.rs +++ b/src/source/postgres/pgoutput.rs @@ -373,7 +373,7 @@ impl PgOutputParser { bytes.push(byte); } String::from_utf8(bytes) - .map_err(|e| MeiliBridgeError::Source(format!("Invalid UTF-8 string: {}", e))) + .map_err(|e| MeiliBridgeError::Source(format!("Invalid UTF-8 string: {e}"))) } pub fn get_relation(&self, relation_id: u32) -> Option<&RelationMessage> { diff --git a/src/source/postgres/replication/consumer.rs b/src/source/postgres/replication/consumer.rs index 02b15d4..cf1ae5b 100644 --- a/src/source/postgres/replication/consumer.rs +++ b/src/source/postgres/replication/consumer.rs @@ -45,7 +45,9 @@ impl ReplicationConsumer { if plugin == "pgoutput" { // Drop and recreate with test_decoding - warn!("Slot uses pgoutput plugin which requires binary protocol. Recreating with test_decoding..."); + warn!( + "Slot uses pgoutput plugin which requires binary protocol. Recreating with test_decoding..." + ); self.recreate_slot_with_test_decoding().await?; } @@ -85,7 +87,7 @@ impl ReplicationConsumer { self.client .execute(&query, &[]) .await - .map_err(|e| MeiliBridgeError::Source(format!("Failed to create slot: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Failed to create slot: {e}")))?; info!( "Created replication slot '{}' with test_decoding plugin", @@ -119,8 +121,7 @@ impl ReplicationConsumer { // Use pg_logical_slot_get_changes for test_decoding let query = format!( - "SELECT lsn::text, xid::text, data FROM pg_logical_slot_get_changes('{}', NULL, NULL)", - slot_name + "SELECT lsn::text, xid::text, data FROM pg_logical_slot_get_changes('{slot_name}', NULL, NULL)", ); match client.query(&query, &[]).await { @@ -146,7 +147,9 @@ impl ReplicationConsumer { match tx.send(Ok(event)).await { Ok(_) => debug!("CDC: Event sent to coordinator"), Err(_) => { - info!("CDC: Replication consumer stopping - channel closed"); + info!( + "CDC: Replication consumer stopping - channel closed" + ); return; } } @@ -177,11 +180,12 @@ impl ReplicationConsumer { if e.to_string().contains("connection") || consecutive_errors >= MAX_CONSECUTIVE_ERRORS { - error!("Connection lost or max errors reached, stopping replication consumer"); + error!( + "Connection lost or max errors reached, stopping replication consumer" + ); let _ = tx .send(Err(MeiliBridgeError::Source(format!( - "Database connection lost after {} consecutive errors", - consecutive_errors + "Database connection lost after {consecutive_errors} consecutive errors", )))) .await; return; diff --git a/src/source/postgres/replication/test_decoder.rs b/src/source/postgres/replication/test_decoder.rs index 38c8054..8eab74d 100644 --- a/src/source/postgres/replication/test_decoder.rs +++ b/src/source/postgres/replication/test_decoder.rs @@ -249,8 +249,8 @@ fn sanitize_value(raw: &str) -> String { #[cfg(test)] mod tests { use super::*; - use crate::models::stream_event::Event; use crate::models::EventType; + use crate::models::stream_event::Event; #[test] fn parses_update_with_whitespace_values() { diff --git a/src/source/postgres/retry_helper.rs b/src/source/postgres/retry_helper.rs index d17db95..468c994 100644 --- a/src/source/postgres/retry_helper.rs +++ b/src/source/postgres/retry_helper.rs @@ -1,5 +1,5 @@ -use crate::error::retry::{with_retry, RetryConfig, Retryable}; use crate::error::MeiliBridgeError; +use crate::error::retry::{RetryConfig, Retryable, with_retry}; use deadpool_postgres::Pool; use tokio_postgres::Client; use tracing::debug; @@ -114,8 +114,8 @@ enum PostgresRetryError { impl std::fmt::Display for PostgresRetryError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - PostgresRetryError::Postgres(e) => write!(f, "{}", e), - PostgresRetryError::Pool(msg) => write!(f, "Pool error: {}", msg), + PostgresRetryError::Postgres(e) => write!(f, "{e}"), + PostgresRetryError::Pool(msg) => write!(f, "Pool error: {msg}"), } } } diff --git a/src/source/postgres/statement_cache.rs b/src/source/postgres/statement_cache.rs index 075b35c..87adef6 100644 --- a/src/source/postgres/statement_cache.rs +++ b/src/source/postgres/statement_cache.rs @@ -52,7 +52,7 @@ impl StatementCache { if !self.config.enabled { // Cache disabled, prepare directly return client.prepare(query).await.map_err(|e| { - MeiliBridgeError::Source(format!("Failed to prepare statement: {}", e)) + MeiliBridgeError::Source(format!("Failed to prepare statement: {e}")) }); } @@ -73,7 +73,7 @@ impl StatementCache { let stmt = client .prepare(query) .await - .map_err(|e| MeiliBridgeError::Source(format!("Failed to prepare statement: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Failed to prepare statement: {e}")))?; // Add to cache let mut cache = self.cache.write().await; @@ -204,7 +204,7 @@ impl CachedConnection { self.client .query(&stmt, params) .await - .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {}", e))) + .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {e}"))) } /// Execute a query that returns at most one row @@ -220,7 +220,7 @@ impl CachedConnection { self.client .query_opt(&stmt, params) .await - .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {}", e))) + .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {e}"))) } /// Execute a query that returns exactly one row @@ -236,7 +236,7 @@ impl CachedConnection { self.client .query_one(&stmt, params) .await - .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {}", e))) + .map_err(|e| MeiliBridgeError::Source(format!("Query execution failed: {e}"))) } /// Execute a statement @@ -249,7 +249,7 @@ impl CachedConnection { self.client .execute(&stmt, params) .await - .map_err(|e| MeiliBridgeError::Source(format!("Statement execution failed: {}", e))) + .map_err(|e| MeiliBridgeError::Source(format!("Statement execution failed: {e}"))) } /// Get the underlying client for operations that don't support caching diff --git a/src/source/postgres/types.rs b/src/source/postgres/types.rs index 3dc9f95..5adc8da 100644 --- a/src/source/postgres/types.rs +++ b/src/source/postgres/types.rs @@ -1,5 +1,5 @@ use crate::error::{MeiliBridgeError, Result}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::str; /// PostgreSQL type OIDs @@ -58,7 +58,7 @@ pub mod oids { /// Decode a PostgreSQL value from its text representation pub fn decode_value(bytes: &[u8], type_oid: u32) -> Result { let text = str::from_utf8(bytes) - .map_err(|e| MeiliBridgeError::Source(format!("Invalid UTF-8: {}", e)))?; + .map_err(|e| MeiliBridgeError::Source(format!("Invalid UTF-8: {e}")))?; // Handle array types if is_array_type(type_oid) { diff --git a/src/source/postgres/wal_consumer.rs b/src/source/postgres/wal_consumer.rs index b46141c..6a3b0ba 100644 --- a/src/source/postgres/wal_consumer.rs +++ b/src/source/postgres/wal_consumer.rs @@ -1,5 +1,5 @@ use crate::error::Result; -use crate::models::{stream_event::Event, CdcEvent, EventType}; +use crate::models::{CdcEvent, EventType, stream_event::Event}; use crate::source::postgres::pgoutput::{PgOutputMessage, PgOutputParser}; use chrono::Utc; use futures::Stream; @@ -57,8 +57,7 @@ impl WalConsumer { loop { // Poll for changes using pg_logical_slot_peek_changes let query = format!( - "SELECT lsn, xid, data FROM pg_logical_slot_peek_changes('{}', NULL, NULL, 'proto_version', '1', 'publication_names', '{}')", - slot_name, publication_name + "SELECT lsn, xid, data FROM pg_logical_slot_peek_changes('{slot_name}', NULL, NULL, 'proto_version', '1', 'publication_names', '{publication_name}')", ); match client.query(&query, &[]).await { @@ -73,11 +72,10 @@ impl WalConsumer { // Parse the logical decoding message if let Some(event) = parse_logical_decoding_message(&data, &parser) + && tx.send(Ok(event)).await.is_err() { - if tx.send(Ok(event)).await.is_err() { - info!("WAL consumer stopping - channel closed"); - return; - } + info!("WAL consumer stopping - channel closed"); + return; } last_lsn = lsn; @@ -85,8 +83,7 @@ impl WalConsumer { // Advance the replication slot let advance_query = format!( - "SELECT pg_replication_slot_advance('{}', '{}')", - slot_name, last_lsn + "SELECT pg_replication_slot_advance('{slot_name}', '{last_lsn}')", ); if let Err(e) = client.execute(&advance_query, &[]).await { diff --git a/src/sync/task_manager.rs b/src/sync/task_manager.rs index f23452b..1dd88a2 100644 --- a/src/sync/task_manager.rs +++ b/src/sync/task_manager.rs @@ -4,8 +4,8 @@ use crate::models::Position; use crate::pipeline::PipelineOrchestrator; use std::collections::HashMap; use std::sync::Arc; -use tokio::sync::{mpsc, watch, RwLock}; -use tokio::time::{interval, Duration}; +use tokio::sync::{RwLock, mpsc, watch}; +use tokio::time::{Duration, interval}; use tracing::{debug, error, info, warn}; /// Status of a sync task @@ -269,12 +269,12 @@ impl SyncTaskManager { info!("Pausing task '{}'", task_id); let mut statuses_map = statuses.write().await; - if let Some(status) = statuses_map.get_mut(task_id) { - if status.state == TaskState::Running { - status.state = TaskState::Paused; - status.last_updated = chrono::Utc::now(); - info!("Task '{}' state changed to Paused", task_id); - } + if let Some(status) = statuses_map.get_mut(task_id) + && status.state == TaskState::Running + { + status.state = TaskState::Paused; + status.last_updated = chrono::Utc::now(); + info!("Task '{}' state changed to Paused", task_id); } } @@ -283,12 +283,12 @@ impl SyncTaskManager { info!("Resuming task '{}'", task_id); let mut statuses_map = statuses.write().await; - if let Some(status) = statuses_map.get_mut(task_id) { - if status.state == TaskState::Paused { - status.state = TaskState::Running; - status.last_updated = chrono::Utc::now(); - info!("Task '{}' state changed to Running", task_id); - } + if let Some(status) = statuses_map.get_mut(task_id) + && status.state == TaskState::Paused + { + status.state = TaskState::Running; + status.last_updated = chrono::Utc::now(); + info!("Task '{}' state changed to Running", task_id); } } @@ -382,8 +382,7 @@ impl SyncTaskManager { Ok(()) } else { Err(MeiliBridgeError::Pipeline(format!( - "Task '{}' not found", - task_id + "Task '{task_id}' not found", ))) } } @@ -408,8 +407,7 @@ impl SyncTaskManager { Ok(()) } else { Err(MeiliBridgeError::Pipeline(format!( - "Task '{}' not found", - task_id + "Task '{task_id}' not found", ))) } } diff --git a/tests/integration.rs b/tests/integration.rs index f8d702e..cefcb2f 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,5 +1,7 @@ // Integration test entry point +#![allow(clippy::collapsible_if)] + #[path = "integration/mod.rs"] mod integration; diff --git a/tests/integration/api/server_test.rs b/tests/integration/api/server_test.rs index 4312ba1..2e1b8d0 100644 --- a/tests/integration/api/server_test.rs +++ b/tests/integration/api/server_test.rs @@ -1,8 +1,8 @@ // API server integration tests +use crate::common::TestApiServer; use crate::common::api_helpers::assertions::*; use crate::common::fixtures::*; -use crate::common::TestApiServer; use reqwest::{Client, StatusCode}; use serde_json::json; use std::sync::Arc; @@ -72,7 +72,7 @@ mod api_server_tests { let client = Client::new(); let response = client - .get(format!("http://{}/tasks", addr)) + .get(format!("http://{addr}/tasks")) .send() .await .unwrap(); @@ -90,7 +90,7 @@ mod api_server_tests { let client = Client::new(); let response = client - .get(format!("http://{}/tasks/nonexistent", addr)) + .get(format!("http://{addr}/tasks/nonexistent")) .send() .await .unwrap(); @@ -110,7 +110,7 @@ mod api_server_tests { let client = Client::new(); let response = client - .get(format!("http://{}/cdc/status", addr)) + .get(format!("http://{addr}/cdc/status")) .send() .await .unwrap(); @@ -159,7 +159,7 @@ mod api_server_tests { }); let response = client - .post(format!("http://{}/tasks", addr)) + .post(format!("http://{addr}/tasks")) .json(&new_task) .send() .await @@ -188,7 +188,7 @@ mod api_server_tests { let handle = tokio::spawn(async move { let response = client_clone - .get(format!("http://{}/health", addr_str)) + .get(format!("http://{addr_str}/health")) .header("X-Request-ID", i.to_string()) .send() .await @@ -215,7 +215,7 @@ mod api_server_tests { // Test non-existent component let response = client - .get(format!("http://{}/health/nonexistent", addr)) + .get(format!("http://{addr}/health/nonexistent")) .send() .await .unwrap(); diff --git a/tests/integration/api/task_endpoints_test.rs b/tests/integration/api/task_endpoints_test.rs index 467d8f4..b426a3a 100644 --- a/tests/integration/api/task_endpoints_test.rs +++ b/tests/integration/api/task_endpoints_test.rs @@ -83,7 +83,7 @@ mod task_endpoints_tests { ]; for state in states { - let state_str = format!("{:?}", state); + let state_str = format!("{state:?}"); assert!(!state_str.is_empty()); } } diff --git a/tests/integration/common/api_helpers.rs b/tests/integration/common/api_helpers.rs index 6f77104..6116153 100644 --- a/tests/integration/common/api_helpers.rs +++ b/tests/integration/common/api_helpers.rs @@ -1,8 +1,8 @@ // Common API testing helpers -use axum::routing::{delete, get, post, put}; use axum::Router; -use meilibridge::api::{handlers, ApiState}; +use axum::routing::{delete, get, post, put}; +use meilibridge::api::{ApiState, handlers}; use meilibridge::config::Config; use meilibridge::health::HealthRegistry; use meilibridge::pipeline::PipelineOrchestrator; @@ -45,7 +45,7 @@ impl TestApiServer { // Wait for server to start tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; - let base_url = format!("http://{}", addr); + let base_url = format!("http://{addr}"); let client = Client::new(); Self { @@ -64,7 +64,7 @@ impl TestApiServer { /// Make a GET request pub async fn get(&self, path: &str) -> reqwest::Response { self.client - .get(format!("{}{}", self.base_url, path)) + .get(format!("{}{path}", self.base_url)) .send() .await .expect("Failed to send GET request") @@ -73,7 +73,7 @@ impl TestApiServer { /// Make a POST request with JSON body pub async fn post_json(&self, path: &str, json: &T) -> reqwest::Response { self.client - .post(format!("{}{}", self.base_url, path)) + .post(format!("{}{path}", self.base_url)) .json(json) .send() .await @@ -83,7 +83,7 @@ impl TestApiServer { /// Make a PUT request with JSON body pub async fn put_json(&self, path: &str, json: &T) -> reqwest::Response { self.client - .put(format!("{}{}", self.base_url, path)) + .put(format!("{}{path}", self.base_url)) .json(json) .send() .await @@ -93,7 +93,7 @@ impl TestApiServer { /// Make a DELETE request pub async fn delete(&self, path: &str) -> reqwest::Response { self.client - .delete(format!("{}{}", self.base_url, path)) + .delete(format!("{}{path}", self.base_url)) .send() .await .expect("Failed to send DELETE request") @@ -126,14 +126,14 @@ pub fn create_api_router(state: ApiState) -> Router { Router::new() // Health check .route("/health", get(handlers::health)) - .route("/health/:component", get(handlers::get_component_health)) + .route("/health/{component}", get(handlers::get_component_health)) // Task management .route("/tasks", get(handlers::get_tasks)) .route("/tasks", post(handlers::create_task)) - .route("/tasks/:id", get(handlers::get_task)) - .route("/tasks/:id", delete(handlers::delete_task)) - .route("/tasks/:id/pause", put(handlers::pause_task)) - .route("/tasks/:id/resume", put(handlers::resume_task)) + .route("/tasks/{id}", get(handlers::get_task)) + .route("/tasks/{id}", delete(handlers::delete_task)) + .route("/tasks/{id}/pause", put(handlers::pause_task)) + .route("/tasks/{id}/resume", put(handlers::resume_task)) // CDC control .route("/cdc/status", get(handlers::get_cdc_status)) // Metrics @@ -155,8 +155,7 @@ pub mod assertions { let status = response.status(); assert_eq!( status, expected, - "Expected status {} but got {}", - expected, status + "Expected status {expected} but got {status}", ); response } @@ -168,11 +167,10 @@ pub mod assertions { .expect("Failed to parse JSON response"); let actual = json .get(field) - .unwrap_or_else(|| panic!("Field '{}' not found in response", field)); + .unwrap_or_else(|| panic!("Field '{field}' not found in response")); assert_eq!( actual, expected, - "Field '{}' expected to be {:?} but was {:?}", - field, expected, actual + "Field '{field}' expected to be {expected:?} but was {actual:?}", ); // Return the parsed JSON for further assertions json diff --git a/tests/integration/common/containers.rs b/tests/integration/common/containers.rs index 3527f51..fca122b 100644 --- a/tests/integration/common/containers.rs +++ b/tests/integration/common/containers.rs @@ -1,46 +1,60 @@ // Test container utilities +#![allow(clippy::collapsible_if)] +use std::borrow::Cow; +use std::collections::HashMap; use std::time::Duration; -use testcontainers::{clients::Cli, core::WaitFor, Container as TestContainer, Image}; +use testcontainers::core::{ContainerPort, WaitFor}; +use testcontainers::runners::AsyncRunner; +use testcontainers::{ContainerAsync, Image}; use testcontainers_modules::{postgres::Postgres, redis::Redis}; // Re-export Container type for easier use in tests -pub type Container<'a, I> = TestContainer<'a, I>; +pub type Container = ContainerAsync; #[derive(Default)] -pub struct TestContainers<'a> { - pub postgres: Option>, - pub redis: Option>, - pub meilisearch: Option>, +pub struct TestContainers { + pub postgres: Option>, + pub redis: Option>, + pub meilisearch: Option>, } -impl<'a> TestContainers<'a> { +impl TestContainers { pub fn new() -> Self { Self::default() } - pub fn postgres_url(&self) -> String { + pub async fn postgres_url(&self) -> String { if let Some(container) = &self.postgres { - let port = container.get_host_port_ipv4(5432); - format!("postgresql://postgres:postgres@localhost:{}/postgres", port) + let port = container + .get_host_port_ipv4(5432) + .await + .expect("Failed to get port"); + format!("postgresql://postgres:postgres@localhost:{port}/postgres") } else { panic!("PostgreSQL container not started"); } } - pub fn redis_url(&self) -> String { + pub async fn redis_url(&self) -> String { if let Some(container) = &self.redis { - let port = container.get_host_port_ipv4(6379); - format!("redis://localhost:{}", port) + let port = container + .get_host_port_ipv4(6379) + .await + .expect("Failed to get port"); + format!("redis://localhost:{port}") } else { panic!("Redis container not started"); } } - pub fn meilisearch_url(&self) -> String { + pub async fn meilisearch_url(&self) -> String { if let Some(container) = &self.meilisearch { - let port = container.get_host_port_ipv4(7700); - format!("http://localhost:{}", port) + let port = container + .get_host_port_ipv4(7700) + .await + .expect("Failed to get port"); + format!("http://localhost:{port}") } else { panic!("Meilisearch container not started"); } @@ -51,30 +65,29 @@ impl<'a> TestContainers<'a> { #[derive(Debug, Clone)] pub struct MeilisearchImage { tag: String, - env_vars: Vec<(String, String)>, + env_vars: HashMap, } impl Default for MeilisearchImage { fn default() -> Self { + let mut env_vars = HashMap::new(); + env_vars.insert("MEILI_MASTER_KEY".to_string(), "masterKey".to_string()); + env_vars.insert("MEILI_ENV".to_string(), "development".to_string()); + MeilisearchImage { - tag: "v1.6".to_string(), - env_vars: vec![ - ("MEILI_MASTER_KEY".to_string(), "masterKey".to_string()), - ("MEILI_ENV".to_string(), "development".to_string()), - ], + tag: "v1.13".to_string(), + env_vars, } } } impl Image for MeilisearchImage { - type Args = Vec; - - fn name(&self) -> String { - "getmeili/meilisearch".to_string() + fn name(&self) -> &str { + "getmeili/meilisearch" } - fn tag(&self) -> String { - self.tag.clone() + fn tag(&self) -> &str { + &self.tag } fn ready_conditions(&self) -> Vec { @@ -85,47 +98,49 @@ impl Image for MeilisearchImage { ] } - fn env_vars(&self) -> Box + '_> { - Box::new(self.env_vars.iter().map(|(k, v)| (k, v))) + fn env_vars( + &self, + ) -> impl IntoIterator>, impl Into>)> { + &self.env_vars } - fn expose_ports(&self) -> Vec { - vec![7700] + fn expose_ports(&self) -> &[ContainerPort] { + &[ContainerPort::Tcp(7700)] } } // Container lifecycle helpers -pub fn start_postgres(docker: &Cli) -> TestContainer<'_, Postgres> { - docker.run(Postgres::default()) +pub async fn start_postgres() -> Container { + Postgres::default() + .start() + .await + .expect("Failed to start Postgres") } // Custom PostgreSQL image with CDC support (wal_level=logical) #[derive(Debug, Clone)] pub struct PostgresCDCImage { - env_vars: Vec<(String, String)>, + env_vars: HashMap, } impl Default for PostgresCDCImage { fn default() -> Self { - PostgresCDCImage { - env_vars: vec![ - ("POSTGRES_USER".to_string(), "postgres".to_string()), - ("POSTGRES_PASSWORD".to_string(), "postgres".to_string()), - ("POSTGRES_DB".to_string(), "testdb".to_string()), - ], - } + let mut env_vars = HashMap::new(); + env_vars.insert("POSTGRES_USER".to_string(), "postgres".to_string()); + env_vars.insert("POSTGRES_PASSWORD".to_string(), "postgres".to_string()); + env_vars.insert("POSTGRES_DB".to_string(), "testdb".to_string()); + + PostgresCDCImage { env_vars } } } impl Image for PostgresCDCImage { - type Args = (); - - fn name(&self) -> String { - "binarytouch/postgres".to_string() + fn name(&self) -> &str { + "binarytouch/postgres" } - fn tag(&self) -> String { - "17".to_string() + fn tag(&self) -> &str { + "17" } fn ready_conditions(&self) -> Vec { @@ -135,27 +150,32 @@ impl Image for PostgresCDCImage { ] } - fn env_vars(&self) -> Box + '_> { - Box::new(self.env_vars.iter().map(|(k, v)| (k, v))) + fn env_vars( + &self, + ) -> impl IntoIterator>, impl Into>)> { + &self.env_vars } - fn expose_ports(&self) -> Vec { - vec![5432] + fn expose_ports(&self) -> &[ContainerPort] { + &[ContainerPort::Tcp(5432)] } } // Start PostgreSQL with logical replication enabled -pub fn start_postgres_with_cdc(docker: &Cli) -> TestContainer<'_, PostgresCDCImage> { - docker.run(PostgresCDCImage::default()) +pub async fn start_postgres_with_cdc() -> Container { + PostgresCDCImage::default() + .start() + .await + .expect("Failed to start Postgres CDC") } -pub fn start_redis(docker: &'static Cli) -> Container<'static, Redis> { - docker.run(Redis) +pub async fn start_redis() -> Container { + Redis.start().await.expect("Failed to start Redis") } -pub fn start_meilisearch(docker: &Cli) -> TestContainer<'_, MeilisearchImage> { +pub async fn start_meilisearch() -> Container { let image = MeilisearchImage::default(); - docker.run(image) + image.start().await.expect("Failed to start Meilisearch") } // Wait for services to be ready @@ -169,7 +189,7 @@ pub async fn wait_for_postgres(url: &str) -> Result<(), Box Result<(), Box { if response.status().is_success() { println!("Meilisearch is ready!"); @@ -240,9 +260,7 @@ pub async fn wait_for_meilisearch(url: &str) -> Result<(), Box= max_retries { - return Err( - format!("Meilisearch failed to start after {} attempts", max_retries).into(), - ); + return Err(format!("Meilisearch failed to start after {max_retries} attempts").into()); } tokio::time::sleep(Duration::from_millis(500)).await; } diff --git a/tests/integration/common/fixtures.rs b/tests/integration/common/fixtures.rs index 95d0721..96f035e 100644 --- a/tests/integration/common/fixtures.rs +++ b/tests/integration/common/fixtures.rs @@ -33,10 +33,7 @@ pub async fn setup_postgres_replication( let tables_list = tables.join(", "); client .execute( - &format!( - "CREATE PUBLICATION {} FOR TABLE {}", - publication, tables_list - ), + &format!("CREATE PUBLICATION {publication} FOR TABLE {tables_list}"), &[], ) .await?; @@ -51,15 +48,14 @@ pub async fn create_test_table( client .execute( &format!( - "CREATE TABLE {} ( + "CREATE TABLE {table_name} ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP - )", - table_name + )" ), &[], ) @@ -179,21 +175,21 @@ pub async fn create_test_api_state() -> ApiState { } pub async fn start_test_server(state: ApiState) -> (SocketAddr, tokio::task::JoinHandle<()>) { - use axum::routing::{delete, get, post, put}; use axum::Router; + use axum::routing::{delete, get, post, put}; use meilibridge::api::handlers; let app = Router::new() // Health check .route("/health", get(handlers::health)) - .route("/health/:component", get(handlers::get_component_health)) + .route("/health/{component}", get(handlers::get_component_health)) // Task management .route("/tasks", get(handlers::get_tasks)) .route("/tasks", post(handlers::create_task)) - .route("/tasks/:id", get(handlers::get_task)) - .route("/tasks/:id", delete(handlers::delete_task)) - .route("/tasks/:id/pause", put(handlers::pause_task)) - .route("/tasks/:id/resume", put(handlers::resume_task)) + .route("/tasks/{id}", get(handlers::get_task)) + .route("/tasks/{id}", delete(handlers::delete_task)) + .route("/tasks/{id}/pause", put(handlers::pause_task)) + .route("/tasks/{id}/resume", put(handlers::resume_task)) // CDC control .route("/cdc/status", get(handlers::get_cdc_status)) // Metrics diff --git a/tests/integration/common/mod.rs b/tests/integration/common/mod.rs index 6b9456d..6bd21a6 100644 --- a/tests/integration/common/mod.rs +++ b/tests/integration/common/mod.rs @@ -9,4 +9,4 @@ pub mod test_data; pub use api_helpers::TestApiServer; // Re-export commonly used items -pub use setup::{setup_meilisearch, setup_postgres_cdc, setup_redis, DOCKER}; +pub use setup::{setup_meilisearch, setup_postgres_cdc, setup_redis}; diff --git a/tests/integration/common/setup.rs b/tests/integration/common/setup.rs index 56604dc..cf2b5bb 100644 --- a/tests/integration/common/setup.rs +++ b/tests/integration/common/setup.rs @@ -4,20 +4,16 @@ use crate::common::containers::*; use meilibridge::config::Config; use meilisearch_sdk::client::Client as MeilisearchClient; use redis::Client as RedisClient; -use testcontainers::clients::Cli; use testcontainers_modules::redis::Redis; use tokio_postgres::Client as PostgresClient; -// Static Docker client to keep containers alive across tests -pub static DOCKER: once_cell::sync::Lazy = once_cell::sync::Lazy::new(Cli::default); - /// Container setup result with all necessary components #[derive(Default)] pub struct TestEnvironment { // Containers - pub postgres_container: Option>, - pub redis_container: Option>, - pub meilisearch_container: Option>, + pub postgres_container: Option>, + pub redis_container: Option>, + pub meilisearch_container: Option>, // Clients pub postgres_client: Option, @@ -40,16 +36,19 @@ impl TestEnvironment { /// Setup only PostgreSQL pub async fn with_postgres(mut self) -> Result> { - let container = start_postgres_with_cdc(&DOCKER); - let port = container.get_host_port_ipv4(5432); - let url = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let container = start_postgres_with_cdc().await; + let port = container + .get_host_port_ipv4(5432) + .await + .expect("Failed to get port"); + let url = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&url).await?; let (client, connection) = tokio_postgres::connect(&url, tokio_postgres::NoTls).await?; tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("PostgreSQL connection error: {}", e); + eprintln!("PostgreSQL connection error: {e}"); } }); @@ -62,9 +61,12 @@ impl TestEnvironment { /// Setup only Redis pub async fn with_redis(mut self) -> Result> { - let container = start_redis(&DOCKER); - let port = container.get_host_port_ipv4(6379); - let url = format!("redis://localhost:{}", port); + let container = start_redis().await; + let port = container + .get_host_port_ipv4(6379) + .await + .expect("Failed to get port"); + let url = format!("redis://localhost:{port}"); wait_for_redis(&url).await?; @@ -79,9 +81,12 @@ impl TestEnvironment { /// Setup only Meilisearch pub async fn with_meilisearch(mut self) -> Result> { - let container = start_meilisearch(&DOCKER); - let port = container.get_host_port_ipv4(7700); - let url = format!("http://localhost:{}", port); + let container = start_meilisearch().await; + let port = container + .get_host_port_ipv4(7700) + .await + .expect("Failed to get port"); + let url = format!("http://localhost:{port}"); wait_for_meilisearch(&url).await?; @@ -146,10 +151,8 @@ impl TestEnvironment { /// Quick setup functions for common scenarios /// Setup PostgreSQL with CDC for integration tests -pub async fn setup_postgres_cdc() -> Result< - (Container<'static, PostgresCDCImage>, PostgresClient, String), - Box, -> { +pub async fn setup_postgres_cdc() +-> Result<(Container, PostgresClient, String), Box> { let env = TestEnvironment::new().with_postgres().await?; Ok(( env.postgres_container.unwrap(), @@ -159,8 +162,8 @@ pub async fn setup_postgres_cdc() -> Result< } /// Setup Redis for integration tests -pub async fn setup_redis( -) -> Result<(Container<'static, Redis>, RedisClient, String), Box> { +pub async fn setup_redis() +-> Result<(Container, RedisClient, String), Box> { let env = TestEnvironment::new().with_redis().await?; Ok(( env.redis_container.unwrap(), @@ -170,14 +173,8 @@ pub async fn setup_redis( } /// Setup Meilisearch for integration tests -pub async fn setup_meilisearch() -> Result< - ( - Container<'static, MeilisearchImage>, - MeilisearchClient, - String, - ), - Box, -> { +pub async fn setup_meilisearch() +-> Result<(Container, MeilisearchClient, String), Box> { let env = TestEnvironment::new().with_meilisearch().await?; Ok(( env.meilisearch_container.unwrap(), diff --git a/tests/integration/common/test_data.rs b/tests/integration/common/test_data.rs index 550c435..5e840f0 100644 --- a/tests/integration/common/test_data.rs +++ b/tests/integration/common/test_data.rs @@ -2,7 +2,7 @@ use chrono::Utc; use meilibridge::models::progress::{Checkpoint, Position, ProgressStats}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::collections::HashMap; use uuid::Uuid; @@ -121,15 +121,14 @@ pub mod sql { client .execute( &format!( - "CREATE TABLE IF NOT EXISTS {} ( + "CREATE TABLE IF NOT EXISTS {table_name} ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP - )", - table_name + )" ), &[], ) diff --git a/tests/integration/meilisearch/batch_processor_test.rs b/tests/integration/meilisearch/batch_processor_test.rs index 3c9e6d5..bc249e6 100644 --- a/tests/integration/meilisearch/batch_processor_test.rs +++ b/tests/integration/meilisearch/batch_processor_test.rs @@ -219,7 +219,7 @@ mod batch_processor_tests { } let elapsed = start.elapsed(); - println!("Processed 1000 documents in {:?}", elapsed); + println!("Processed 1000 documents in {elapsed:?}"); // Verify all documents were added tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; diff --git a/tests/integration/postgres_cdc/connection_test.rs b/tests/integration/postgres_cdc/connection_test.rs index 7138c0f..26b1e09 100644 --- a/tests/integration/postgres_cdc/connection_test.rs +++ b/tests/integration/postgres_cdc/connection_test.rs @@ -2,7 +2,7 @@ use crate::common::fixtures::*; use crate::common::setup_postgres_cdc; -use testcontainers::clients::Cli; +use testcontainers::runners::AsyncRunner; use testcontainers_modules::postgres::Postgres; #[cfg(test)] @@ -40,13 +40,13 @@ mod connection_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); // Execute a query to ensure connection works let row = client - .query_one(&format!("SELECT {} as num", i), &[]) + .query_one(&format!("SELECT {i} as num"), &[]) .await .unwrap(); let num: i32 = row.get("num"); @@ -64,17 +64,16 @@ mod connection_tests { #[tokio::test] async fn test_connection_with_invalid_credentials() { use crate::common::containers::{start_postgres_with_cdc, wait_for_postgres}; - use crate::common::DOCKER; - let postgres = start_postgres_with_cdc(&DOCKER); - let port = postgres.get_host_port_ipv4(5432); + + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); // Wait for PostgreSQL to be ready - let valid_connection = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let valid_connection = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&valid_connection).await.unwrap(); // Try with invalid password - let invalid_connection = - format!("postgresql://postgres:wrongpass@localhost:{}/testdb", port); + let invalid_connection = format!("postgresql://postgres:wrongpass@localhost:{port}/testdb"); let result = tokio_postgres::connect(&invalid_connection, tokio_postgres::NoTls).await; assert!(result.is_err()); @@ -98,10 +97,13 @@ mod connection_tests { #[tokio::test] async fn test_ssl_connection_modes() { - let docker = Cli::default(); - let postgres = docker.run(Postgres::default().with_db_name("testdb")); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = Postgres::default() + .with_db_name("testdb") + .start() + .await + .unwrap(); + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -114,17 +116,19 @@ mod connection_tests { #[tokio::test] async fn test_connection_parameter_validation() { - let docker = Cli::default(); - let postgres = docker.run(Postgres::default().with_db_name("testdb")); - let port = postgres.get_host_port_ipv4(5432); + let postgres = Postgres::default() + .with_db_name("testdb") + .start() + .await + .unwrap(); + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); // Test various connection string formats let connection_strings = vec![ - format!("postgresql://postgres:postgres@localhost:{}/testdb", port), - format!("postgres://postgres:postgres@localhost:{}/testdb", port), + format!("postgresql://postgres:postgres@localhost:{port}/testdb"), + format!("postgres://postgres:postgres@localhost:{port}/testdb"), format!( - "postgresql://postgres:postgres@localhost:{}/testdb?application_name=meilibridge", - port + "postgresql://postgres:postgres@localhost:{port}/testdb?application_name=meilibridge", ), ]; @@ -132,16 +136,19 @@ mod connection_tests { wait_for_postgres(&conn_str).await.unwrap(); let result = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls).await; - assert!(result.is_ok(), "Failed to connect with: {}", conn_str); + assert!(result.is_ok(), "Failed to connect with: {conn_str}"); } } #[tokio::test] async fn test_reconnection_after_disconnect() { - let docker = Cli::default(); - let postgres = docker.run(Postgres::default().with_db_name("testdb")); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = Postgres::default() + .with_db_name("testdb") + .start() + .await + .unwrap(); + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -153,7 +160,7 @@ mod connection_tests { let conn_handle = tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -172,7 +179,7 @@ mod connection_tests { tokio::spawn(async move { if let Err(e) = new_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -184,12 +191,15 @@ mod connection_tests { #[tokio::test] async fn test_connection_with_different_databases() { - let docker = Cli::default(); - let postgres = docker.run(Postgres::default().with_db_name("testdb")); - let port = postgres.get_host_port_ipv4(5432); + let postgres = Postgres::default() + .with_db_name("testdb") + .start() + .await + .unwrap(); + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); // Connect to default database first - let postgres_db = format!("postgresql://postgres:postgres@localhost:{}/postgres", port); + let postgres_db = format!("postgresql://postgres:postgres@localhost:{port}/postgres"); wait_for_postgres(&postgres_db).await.unwrap(); let (client, connection) = tokio_postgres::connect(&postgres_db, tokio_postgres::NoTls) @@ -198,7 +208,7 @@ mod connection_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -209,17 +219,14 @@ mod connection_tests { .ok(); // Connect to the new database - let new_db = format!( - "postgresql://postgres:postgres@localhost:{}/meilibridge_test", - port - ); + let new_db = format!("postgresql://postgres:postgres@localhost:{port}/meilibridge_test",); let (new_client, new_connection) = tokio_postgres::connect(&new_db, tokio_postgres::NoTls) .await .unwrap(); tokio::spawn(async move { if let Err(e) = new_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); diff --git a/tests/integration/postgres_cdc/replication_slot_test.rs b/tests/integration/postgres_cdc/replication_slot_test.rs index d51ad68..2651f35 100644 --- a/tests/integration/postgres_cdc/replication_slot_test.rs +++ b/tests/integration/postgres_cdc/replication_slot_test.rs @@ -3,7 +3,6 @@ // These tests use binarytouch/postgres:17 image which has wal_level=logical configured. use crate::common::containers::*; -use testcontainers::clients::Cli; #[cfg(test)] mod replication_slot_tests { @@ -11,10 +10,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_replication_slot_creation() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -26,7 +24,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -49,7 +47,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = verify_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -68,10 +66,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_replication_slot_deletion() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -83,7 +80,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -104,7 +101,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = drop_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -127,10 +124,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_slot_recovery_after_disconnect() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -144,7 +140,7 @@ mod replication_slot_tests { let conn_handle = tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -168,7 +164,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = verify_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -187,10 +183,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_multiple_slots() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -204,7 +199,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -226,7 +221,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = verify_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -251,10 +246,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_slot_with_publication() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -266,7 +260,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -309,10 +303,9 @@ mod replication_slot_tests { #[tokio::test] async fn test_slot_cleanup_on_failure() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -326,7 +319,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -357,7 +350,7 @@ mod replication_slot_tests { tokio::spawn(async move { if let Err(e) = cleanup_connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); diff --git a/tests/integration/postgres_cdc/wal_consumer_test.rs b/tests/integration/postgres_cdc/wal_consumer_test.rs index 057470f..60578c3 100644 --- a/tests/integration/postgres_cdc/wal_consumer_test.rs +++ b/tests/integration/postgres_cdc/wal_consumer_test.rs @@ -1,7 +1,6 @@ // PostgreSQL WAL consumer integration tests use crate::common::containers::*; -use testcontainers::clients::Cli; #[cfg(test)] mod wal_consumer_tests { @@ -9,10 +8,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_real_time_change_capture() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -24,7 +22,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -90,10 +88,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_message_ordering() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -104,7 +101,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -152,10 +149,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_transaction_consistency() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -166,7 +162,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -259,10 +255,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_large_transaction_handling() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -273,7 +268,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -305,7 +300,7 @@ mod wal_consumer_tests { transaction .execute( "INSERT INTO test_large_txn (data) VALUES ($1)", - &[&format!("Record {}", i)], + &[&format!("Record {i}")], ) .await .unwrap(); @@ -325,10 +320,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_schema_change_handling() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -339,7 +333,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); @@ -403,10 +397,9 @@ mod wal_consumer_tests { #[tokio::test] async fn test_multi_table_changes() { - let docker = Cli::default(); - let postgres = start_postgres_with_cdc(&docker); - let port = postgres.get_host_port_ipv4(5432); - let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port); + let postgres = start_postgres_with_cdc().await; + let port = postgres.get_host_port_ipv4(5432).await.unwrap(); + let connection_string = format!("postgresql://postgres:postgres@localhost:{port}/testdb"); wait_for_postgres(&connection_string).await.unwrap(); @@ -417,7 +410,7 @@ mod wal_consumer_tests { tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("connection error: {}", e); + eprintln!("connection error: {e}"); } }); diff --git a/tests/integration/redis/checkpoint_storage_test.rs b/tests/integration/redis/checkpoint_storage_test.rs index 4a54e57..f361dc1 100644 --- a/tests/integration/redis/checkpoint_storage_test.rs +++ b/tests/integration/redis/checkpoint_storage_test.rs @@ -1,19 +1,19 @@ // Redis checkpoint storage integration tests +use crate::common::containers::Container; use crate::common::test_data::create_checkpoint; use meilibridge::models::progress::{Checkpoint, Position}; use redis::Commands; use serde_json::json; -use testcontainers::Container; +use testcontainers::runners::AsyncRunner; use testcontainers_modules::redis::Redis; #[cfg(test)] mod redis_checkpoint_tests { use super::*; - async fn setup_redis( - ) -> Result<(Container<'static, Redis>, redis::Client, String), Box> - { + async fn setup_redis() + -> Result<(Container, redis::Client, String), Box> { crate::common::setup_redis().await } @@ -101,7 +101,7 @@ mod redis_checkpoint_tests { let (_container, client, _url) = setup_redis().await.unwrap(); let task_id = "concurrent_task"; - let key = format!("checkpoint:{}", task_id); + let key = format!("checkpoint:{task_id}"); // Simulate concurrent updates let mut handles = vec![]; @@ -134,7 +134,7 @@ mod redis_checkpoint_tests { match result { Ok(Some(_)) => break, // Transaction succeeded Ok(None) => continue, // Transaction aborted, retry - Err(e) => panic!("Transaction error: {}", e), + Err(e) => panic!("Transaction error: {e}"), } } }); @@ -186,12 +186,10 @@ mod redis_checkpoint_tests { #[tokio::test] async fn test_connection_failure_handling() { - // Use static Docker client - use crate::common::DOCKER; - - let container = DOCKER.run(Redis); - let port = container.get_host_port_ipv4(6379); - let url = format!("redis://localhost:{}", port); + // Use Redis::default() and start() instead of DOCKER + let container = Redis.start().await.unwrap(); + let port = container.get_host_port_ipv4(6379).await.unwrap(); + let url = format!("redis://localhost:{port}"); crate::common::containers::wait_for_redis(&url) .await @@ -207,6 +205,7 @@ mod redis_checkpoint_tests { let _: Result<(), redis::RedisError> = conn.set(&key, serialized); // Stop container to simulate connection failure + // With ContainerAsync, dropping it stops the container drop(container); // Try to use connection (should fail) @@ -294,7 +293,7 @@ mod redis_checkpoint_tests { let (_container, client, _url) = setup_redis().await.unwrap(); let task_id = "atomic_task"; - let key = format!("checkpoint:{}", task_id); + let key = format!("checkpoint:{task_id}"); // Initial checkpoint let mut conn = client.get_connection().unwrap(); diff --git a/tests/integration/redis/dlq_storage_test.rs b/tests/integration/redis/dlq_storage_test.rs index ecf3ca5..caff393 100644 --- a/tests/integration/redis/dlq_storage_test.rs +++ b/tests/integration/redis/dlq_storage_test.rs @@ -2,6 +2,7 @@ // Note: redis_storage module is private, so we can't directly test it // These tests demonstrate DLQ patterns using Redis directly +use crate::common::containers::Container; use chrono::Utc; use meilibridge::error::MeiliBridgeError; use meilibridge::models::event::{ @@ -10,23 +11,21 @@ use meilibridge::models::event::{ use redis::Commands; use serde_json::json; use std::collections::HashMap; -use testcontainers::Container; use testcontainers_modules::redis::Redis; #[cfg(test)] mod redis_dlq_tests { use super::*; - async fn setup_redis( - ) -> Result<(Container<'static, Redis>, redis::Client, String), Box> - { + async fn setup_redis() + -> Result<(Container, redis::Client, String), Box> { crate::common::setup_redis().await } fn create_test_event(id: i32) -> Event { let mut data = HashMap::new(); data.insert("id".to_string(), json!(id)); - data.insert("name".to_string(), json!(format!("Test Event {}", id))); + data.insert("name".to_string(), json!(format!("Test Event {id}"))); Event { id: EventId::new(), @@ -106,7 +105,7 @@ mod redis_dlq_tests { // Create multiple failed events for i in 1..=100 { let event = create_test_event(i); - let error = MeiliBridgeError::Database(format!("Error {}", i)); + let error = MeiliBridgeError::Database(format!("Error {i}")); let entry = create_dlq_entry(event, error, i as u32 % 5); entries.push(serde_json::to_string(&entry).unwrap()); } @@ -153,7 +152,7 @@ mod redis_dlq_tests { // Add events with different retry counts for i in 1..=10 { let event = create_test_event(i); - let error = MeiliBridgeError::Validation(format!("Validation error {}", i)); + let error = MeiliBridgeError::Validation(format!("Validation error {i}")); let entry = create_dlq_entry(event, error, i as u32); let _: Result = conn.rpush(dlq_key, serde_json::to_string(&entry).unwrap()); @@ -241,7 +240,7 @@ mod redis_dlq_tests { let mut total_events: usize = 0; for task in &tasks { - let dlq_key = format!("dlq:{}", task); + let dlq_key = format!("dlq:{task}"); let event_count = match *task { "task_a" => 15usize, "task_b" => 8usize, @@ -264,7 +263,7 @@ mod redis_dlq_tests { let mut stats = HashMap::new(); for task in &tasks { - let dlq_key = format!("dlq:{}", task); + let dlq_key = format!("dlq:{task}"); let count: Result = conn.llen(&dlq_key); stats.insert(task.to_string(), count.unwrap()); } diff --git a/tests/unit.rs b/tests/unit.rs index 4d19f83..aacff5f 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -1,6 +1,8 @@ // Unit test entry point // This file serves as the entry point for unit tests +#![allow(clippy::collapsible_if)] + #[path = "unit/mod.rs"] mod unit; diff --git a/tests/unit/checkpoint/manager_test.rs b/tests/unit/checkpoint/manager_test.rs index 2ad1c51..c07bb66 100644 --- a/tests/unit/checkpoint/manager_test.rs +++ b/tests/unit/checkpoint/manager_test.rs @@ -124,7 +124,7 @@ mod checkpoint_manager_tests { // Create multiple checkpoints for i in 1..=5 { - let checkpoint = create_test_checkpoint(&format!("task_{}", i)); + let checkpoint = create_test_checkpoint(&format!("task_{i}")); storage.save(&checkpoint).await.unwrap(); } @@ -135,7 +135,7 @@ mod checkpoint_manager_tests { // Verify all task IDs are present let task_ids: Vec = checkpoints.iter().map(|c| c.task_id.clone()).collect(); for i in 1..=5 { - assert!(task_ids.contains(&format!("task_{}", i))); + assert!(task_ids.contains(&format!("task_{i}"))); } } diff --git a/tests/unit/checkpoint/storage_test.rs b/tests/unit/checkpoint/storage_test.rs index 6584f09..f9501c5 100644 --- a/tests/unit/checkpoint/storage_test.rs +++ b/tests/unit/checkpoint/storage_test.rs @@ -87,7 +87,7 @@ mod checkpoint_storage_tests { // Save multiple checkpoints for i in 1..=5 { - let checkpoint = create_test_checkpoint(&format!("task{}", i)); + let checkpoint = create_test_checkpoint(&format!("task{i}")); storage.save(&checkpoint).await.unwrap(); } @@ -98,7 +98,7 @@ mod checkpoint_storage_tests { // Verify all task IDs let task_ids: Vec = checkpoints.iter().map(|c| c.task_id.clone()).collect(); for i in 1..=5 { - assert!(task_ids.contains(&format!("task{}", i))); + assert!(task_ids.contains(&format!("task{i}"))); } } @@ -113,7 +113,7 @@ mod checkpoint_storage_tests { for i in 0..10 { let storage_clone = storage.clone(); let handle = tokio::spawn(async move { - let checkpoint = create_test_checkpoint(&format!("task{}", i)); + let checkpoint = create_test_checkpoint(&format!("task{i}")); storage_clone.save(&checkpoint).await.unwrap(); }); handles.push(handle); @@ -132,7 +132,7 @@ mod checkpoint_storage_tests { for i in 0..10 { let storage_clone = storage.clone(); let handle = tokio::spawn(async move { - let loaded = storage_clone.load(&format!("task{}", i)).await.unwrap(); + let loaded = storage_clone.load(&format!("task{i}")).await.unwrap(); assert!(loaded.is_some()); }); handles.push(handle); @@ -220,7 +220,7 @@ mod checkpoint_storage_tests { // Store many checkpoints for i in 0..1000 { - let checkpoint = create_test_checkpoint(&format!("bulk_task_{}", i)); + let checkpoint = create_test_checkpoint(&format!("bulk_task_{i}")); storage.save(&checkpoint).await.unwrap(); } @@ -231,7 +231,7 @@ mod checkpoint_storage_tests { // Random access should still be fast let start = std::time::Instant::now(); for i in (0..1000).step_by(100) { - storage.load(&format!("bulk_task_{}", i)).await.unwrap(); + storage.load(&format!("bulk_task_{i}")).await.unwrap(); } let duration = start.elapsed(); assert!(duration.as_millis() < 100); // Should be very fast diff --git a/tests/unit/config/loader_test.rs b/tests/unit/config/loader_test.rs index 969eb44..c1aeb14 100644 --- a/tests/unit/config/loader_test.rs +++ b/tests/unit/config/loader_test.rs @@ -76,8 +76,12 @@ redis: #[test] fn test_environment_variable_substitution() { - std::env::set_var("TEST_DB_HOST", "env-host"); - std::env::set_var("TEST_DB_PASS", "env-pass"); + // SAFETY: This is a test function. We accept the risk of race conditions with environment variables + // in a test environment. + unsafe { + std::env::set_var("TEST_DB_HOST", "env-host"); + std::env::set_var("TEST_DB_PASS", "env-pass"); + } let yaml_with_env = r#" source: @@ -92,8 +96,10 @@ source: // In actual implementation, env vars would be substituted assert!(config_path.exists()); - std::env::remove_var("TEST_DB_HOST"); - std::env::remove_var("TEST_DB_PASS"); + unsafe { + std::env::remove_var("TEST_DB_HOST"); + std::env::remove_var("TEST_DB_PASS"); + } } #[test] diff --git a/tests/unit/delivery/at_least_once_test.rs b/tests/unit/delivery/at_least_once_test.rs index 14268ec..1d2f68a 100644 --- a/tests/unit/delivery/at_least_once_test.rs +++ b/tests/unit/delivery/at_least_once_test.rs @@ -4,7 +4,7 @@ use meilibridge::delivery::{AtLeastOnceConfig, AtLeastOnceManager, Deduplication use meilibridge::models::Position; use std::collections::HashSet; use std::sync::Arc; -use tokio::time::{sleep, Duration}; +use tokio::time::{Duration, sleep}; #[cfg(test)] mod at_least_once_tests { @@ -49,13 +49,13 @@ mod at_least_once_tests { // Add keys until window is full for i in 0..10 { - let key = create_dedup_key(&format!("0/{}", i), i as u32, "events"); + let key = create_dedup_key(&format!("0/{i}"), i as u32, "events"); manager.mark_processed(key).await.unwrap(); } // Verify all keys are tracked for i in 0..10 { - let key = create_dedup_key(&format!("0/{}", i), i as u32, "events"); + let key = create_dedup_key(&format!("0/{i}"), i as u32, "events"); assert!(manager.is_duplicate(&key).await.unwrap()); } @@ -149,7 +149,7 @@ mod at_least_once_tests { // Start multiple concurrent transactions for i in 0..5 { let manager_clone = manager.clone(); - let task_id = format!("task_{}", i); + let task_id = format!("task_{i}"); let handle = tokio::spawn(async move { // Begin transaction @@ -271,7 +271,7 @@ mod at_least_once_tests { // Process unique events for i in 0..num_events { - let key = create_dedup_key(&format!("0/{:08x}", i), i as u32, "high_throughput"); + let key = create_dedup_key(&format!("0/{i:08x}"), i as u32, "high_throughput"); assert!(!manager.is_duplicate(&key).await.unwrap()); manager.mark_processed(key.clone()).await.unwrap(); processed_keys.push(key); diff --git a/tests/unit/delivery/deduplication_test.rs b/tests/unit/delivery/deduplication_test.rs index d32c146..d593be2 100644 --- a/tests/unit/delivery/deduplication_test.rs +++ b/tests/unit/delivery/deduplication_test.rs @@ -1,6 +1,6 @@ // Advanced unit tests for event deduplication -use meilibridge::delivery::deduplication::{compare_lsn, DeduplicationKey, EventDeduplicator}; +use meilibridge::delivery::deduplication::{DeduplicationKey, EventDeduplicator, compare_lsn}; #[cfg(test)] mod deduplication_tests { @@ -56,7 +56,7 @@ mod deduplication_tests { // Fill the window for i in 0..5 { - let key = DeduplicationKey::new(format!("0/{}", i), None, "test".to_string()); + let key = DeduplicationKey::new(format!("0/{i}"), None, "test".to_string()); dedup.add(key); } @@ -72,7 +72,7 @@ mod deduplication_tests { // Others should still be present for i in 1..6 { - let key = DeduplicationKey::new(format!("0/{}", i), None, "test".to_string()); + let key = DeduplicationKey::new(format!("0/{i}"), None, "test".to_string()); assert!(dedup.contains(&key)); } @@ -102,7 +102,7 @@ mod deduplication_tests { // Add some keys for i in 0..10 { - let key = DeduplicationKey::new(format!("0/{}", i), Some(i as u32), "test".to_string()); + let key = DeduplicationKey::new(format!("0/{i}"), Some(i as u32), "test".to_string()); dedup.add(key); } @@ -115,7 +115,7 @@ mod deduplication_tests { // Previously added keys should not be duplicates anymore for i in 0..10 { - let key = DeduplicationKey::new(format!("0/{}", i), Some(i as u32), "test".to_string()); + let key = DeduplicationKey::new(format!("0/{i}"), Some(i as u32), "test".to_string()); assert!(!dedup.contains(&key)); } } @@ -165,11 +165,8 @@ mod deduplication_tests { for table in &tables { for i in 0..10 { - let key = DeduplicationKey::new( - format!("0/{:04x}", i), - Some(i as u32), - table.to_string(), - ); + let key = + DeduplicationKey::new(format!("0/{i:04x}"), Some(i as u32), table.to_string()); dedup.add(key); total_keys += 1; } @@ -181,11 +178,8 @@ mod deduplication_tests { // Verify all keys are tracked for table in &tables { for i in 0..10 { - let key = DeduplicationKey::new( - format!("0/{:04x}", i), - Some(i as u32), - table.to_string(), - ); + let key = + DeduplicationKey::new(format!("0/{i:04x}"), Some(i as u32), table.to_string()); assert!(dedup.contains(&key)); } } @@ -201,7 +195,7 @@ mod deduplication_tests { // Fill to capacity for i in 0..window_size { let key = DeduplicationKey::new( - format!("0/{:08x}", i), + format!("0/{i:08x}"), Some(i as u32), "perf_test".to_string(), ); @@ -214,7 +208,7 @@ mod deduplication_tests { // Add more to trigger evictions for i in window_size..(window_size * 2) { let key = DeduplicationKey::new( - format!("0/{:08x}", i), + format!("0/{i:08x}"), Some(i as u32), "perf_test".to_string(), ); diff --git a/tests/unit/dlq/dead_letter_queue_test.rs b/tests/unit/dlq/dead_letter_queue_test.rs index adc9837..97a094a 100644 --- a/tests/unit/dlq/dead_letter_queue_test.rs +++ b/tests/unit/dlq/dead_letter_queue_test.rs @@ -34,7 +34,7 @@ mod dlq_tests { }, metadata: EventMetadata { transaction_id: Some("100".to_string()), - position: format!("0/{}", id), + position: format!("0/{id}"), custom: HashMap::new(), }, timestamp: Utc::now(), @@ -75,9 +75,9 @@ mod dlq_tests { // Add events for different tasks for task_num in 1..=3 { for event_num in 1..=5 { - let event = create_test_event("users", &format!("{}-{}", task_num, event_num)); - let error = create_test_error(&format!("Error for task{}", task_num)); - dlq.add_failed_event(format!("task{}", task_num), event, error, 0) + let event = create_test_event("users", &format!("{task_num}-{event_num}")); + let error = create_test_error(&format!("Error for task{task_num}")); + dlq.add_failed_event(format!("task{task_num}"), event, error, 0) .await .unwrap(); } @@ -86,14 +86,14 @@ mod dlq_tests { // Verify each task has correct number of entries for task_num in 1..=3 { let entries = storage - .get_by_task(&format!("task{}", task_num), None) + .get_by_task(&format!("task{task_num}"), None) .await .unwrap(); assert_eq!(entries.len(), 5); // All should belong to the same task for entry in entries { - assert_eq!(entry.task_id, format!("task{}", task_num)); + assert_eq!(entry.task_id, format!("task{task_num}")); } } } @@ -198,8 +198,8 @@ mod dlq_tests { // Add events for multiple tasks for i in 0..5 { - let event1 = create_test_event("users", &format!("task1-{}", i)); - let event2 = create_test_event("users", &format!("task2-{}", i)); + let event1 = create_test_event("users", &format!("task1-{i}")); + let event2 = create_test_event("users", &format!("task2-{i}")); dlq.add_failed_event("task1".to_string(), event1, create_test_error("Error"), 0) .await .unwrap(); @@ -306,10 +306,10 @@ mod dlq_tests { for event_num in 0..10 { let dlq_clone = dlq.clone(); let handle = tokio::spawn(async move { - let event = create_test_event("users", &format!("{}-{}", task_num, event_num)); + let event = create_test_event("users", &format!("{task_num}-{event_num}")); let error = create_test_error("Concurrent error"); dlq_clone - .add_failed_event(format!("task{}", task_num), event, error, 0) + .add_failed_event(format!("task{task_num}"), event, error, 0) .await .unwrap(); }); @@ -329,7 +329,7 @@ mod dlq_tests { // Verify each task has correct count for task_num in 0..5 { let entries = storage - .get_by_task(&format!("task{}", task_num), None) + .get_by_task(&format!("task{task_num}"), None) .await .unwrap(); assert_eq!(entries.len(), 10); diff --git a/tests/unit/error/retry_test.rs b/tests/unit/error/retry_test.rs index 81aef05..8e9f6eb 100644 --- a/tests/unit/error/retry_test.rs +++ b/tests/unit/error/retry_test.rs @@ -1,9 +1,9 @@ // Retry logic tests -use meilibridge::error::retry::*; use meilibridge::error::MeiliBridgeError; -use std::sync::atomic::{AtomicUsize, Ordering}; +use meilibridge::error::retry::*; use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{Duration, Instant}; #[cfg(test)] @@ -313,11 +313,13 @@ mod retry_tests { #[test] fn test_meilibridge_error_retryable() { // Retryable MeiliBridge errors - assert!(MeiliBridgeError::Io(std::io::Error::new( - std::io::ErrorKind::ConnectionRefused, - "Connection refused" - )) - .is_retryable()); + assert!( + MeiliBridgeError::Io(std::io::Error::new( + std::io::ErrorKind::ConnectionRefused, + "Connection refused" + )) + .is_retryable() + ); assert!(MeiliBridgeError::Database("connection error".to_string()).is_retryable()); diff --git a/tests/unit/pipeline/adaptive_batching_test.rs b/tests/unit/pipeline/adaptive_batching_test.rs index 24964a4..6b8384c 100644 --- a/tests/unit/pipeline/adaptive_batching_test.rs +++ b/tests/unit/pipeline/adaptive_batching_test.rs @@ -64,8 +64,7 @@ mod adaptive_batching_tests { // The batch size might decrease due to memory pressure or increase due to fast processing assert_ne!( new_size, initial_size, - "Expected batch size to change from {} but it remained the same", - initial_size + "Expected batch size to change from {initial_size} but it remained the same", ); // If it decreased, it should be due to memory pressure (80% of original) @@ -78,9 +77,7 @@ mod adaptive_batching_tests { // Otherwise it should have increased assert!( new_size > initial_size, - "Expected batch size to increase from {} to {}", - initial_size, - new_size + "Expected batch size to increase from {initial_size} to {new_size}", ); } } @@ -109,9 +106,7 @@ mod adaptive_batching_tests { .unwrap(); assert!( new_size < default_size, - "Expected batch size to decrease from {} to {}", - default_size, - new_size + "Expected batch size to decrease from {default_size} to {new_size}", ); } @@ -253,7 +248,7 @@ mod adaptive_batching_tests { let config = create_test_config(); let manager = AdaptiveBatchingManager::new(config); - let tables: Vec = (0..5).map(|i| format!("table_{}", i)).collect(); + let tables: Vec = (0..5).map(|i| format!("table_{i}")).collect(); // Spawn concurrent tasks updating different tables let mut handles = vec![]; @@ -284,8 +279,7 @@ mod adaptive_batching_tests { for table in &tables { assert!( stats.contains_key(table), - "Table {} should have statistics", - table + "Table {table} should have statistics", ); } } @@ -315,9 +309,7 @@ mod adaptive_batching_tests { .unwrap(); assert!( size <= max_size, - "Batch size {} should not exceed max {}", - size, - max_size + "Batch size {size} should not exceed max {max_size}", ); // Now record very slow processing @@ -335,9 +327,7 @@ mod adaptive_batching_tests { .unwrap(); assert!( final_size >= min_size, - "Batch size {} should not go below min {}", - final_size, - min_size + "Batch size {final_size} should not go below min {min_size}", ); } } diff --git a/tests/unit/pipeline/mapper_test.rs b/tests/unit/pipeline/mapper_test.rs index ec5f585..bb2eec1 100644 --- a/tests/unit/pipeline/mapper_test.rs +++ b/tests/unit/pipeline/mapper_test.rs @@ -1,9 +1,9 @@ use chrono::Utc; -use meilibridge::config::{pipeline::FieldMapping, MappingConfig, TableMapping}; +use meilibridge::config::{MappingConfig, TableMapping, pipeline::FieldMapping}; use meilibridge::models::stream_event::Event; use meilibridge::models::{CdcEvent, EventType, Position}; use meilibridge::pipeline::mapper::FieldMapper; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::collections::HashMap; fn create_test_cdc_event(table: &str, data: HashMap) -> Event { diff --git a/tests/unit/pipeline/memory_monitor_test.rs b/tests/unit/pipeline/memory_monitor_test.rs index f22c2a7..42054b8 100644 --- a/tests/unit/pipeline/memory_monitor_test.rs +++ b/tests/unit/pipeline/memory_monitor_test.rs @@ -2,7 +2,7 @@ use meilibridge::pipeline::memory_monitor::{MemoryMonitor, MemoryPressureEvent}; use std::sync::Arc; -use tokio::time::{timeout, Duration}; +use tokio::time::{Duration, timeout}; #[cfg(test)] mod memory_monitor_tests { @@ -143,7 +143,7 @@ mod memory_monitor_tests { // Each task allocates 5 x 2MB = 10MB total let alloc = monitor_clone .track_event_memory(2 * 1024 * 1024) - .unwrap_or_else(|_| panic!("Task {} allocation {} should succeed", i, j)); + .unwrap_or_else(|_| panic!("Task {i} allocation {j} should succeed")); allocations.push(alloc); tokio::task::yield_now().await; } diff --git a/tests/unit/pipeline/orchestrator_test.rs b/tests/unit/pipeline/orchestrator_test.rs index e2da84e..1c1c977 100644 --- a/tests/unit/pipeline/orchestrator_test.rs +++ b/tests/unit/pipeline/orchestrator_test.rs @@ -440,10 +440,12 @@ async fn test_dlq_operations() { // DLQ operations should fail before starting assert!(orchestrator.get_dlq_statistics().await.is_err()); - assert!(orchestrator - .reprocess_dlq_entries("task1", Some(10)) - .await - .is_err()); + assert!( + orchestrator + .reprocess_dlq_entries("task1", Some(10)) + .await + .is_err() + ); assert!(orchestrator.clear_dlq_task("task1").await.is_err()); } diff --git a/tests/unit/pipeline/streaming_processor_test.rs b/tests/unit/pipeline/streaming_processor_test.rs index 3cf13d1..054177f 100644 --- a/tests/unit/pipeline/streaming_processor_test.rs +++ b/tests/unit/pipeline/streaming_processor_test.rs @@ -1,5 +1,5 @@ use meilibridge::pipeline::streaming_processor::{StreamingJsonProcessor, ZeroCopyEventRouter}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::io::Cursor; #[test] @@ -62,9 +62,11 @@ fn test_estimate_value_size() { assert!(processor.parse_document(Cursor::new("42")).is_ok()); assert!(processor.parse_document(Cursor::new(r#""hello""#)).is_ok()); assert!(processor.parse_document(Cursor::new("[1,2,3]")).is_ok()); - assert!(processor - .parse_document(Cursor::new(r#"{"key":"value"}"#)) - .is_ok()); + assert!( + processor + .parse_document(Cursor::new(r#"{"key":"value"}"#)) + .is_ok() + ); } #[tokio::test] @@ -247,8 +249,10 @@ fn test_event_view_parse_full_invalid() { let result = event_view.parse_full(); assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("Failed to parse event")); + assert!( + result + .unwrap_err() + .to_string() + .contains("Failed to parse event") + ); }