diff --git a/.github/workflows/_build_rust_artifacts.yml b/.github/workflows/_build_rust_artifacts.yml index bd56b10716..a1592ad78f 100644 --- a/.github/workflows/_build_rust_artifacts.yml +++ b/.github/workflows/_build_rust_artifacts.yml @@ -46,7 +46,7 @@ on: connector_plugins: type: string required: false - default: "iggy_connector_elasticsearch_sink,iggy_connector_elasticsearch_source,iggy_connector_iceberg_sink,iggy_connector_postgres_sink,iggy_connector_postgres_source,iggy_connector_quickwit_sink,iggy_connector_random_source,iggy_connector_s3_sink,iggy_connector_stdout_sink,iggy_connector_surrealdb_sink" + default: "iggy_connector_elasticsearch_sink,iggy_connector_elasticsearch_source,iggy_connector_iceberg_sink,iggy_connector_postgres_sink,iggy_connector_postgres_source,iggy_connector_quickwit_sink,iggy_connector_random_source,iggy_connector_s3_sink,iggy_connector_stdout_sink,iggy_connector_surrealdb_sink, iggy_connector_rabbitmq_sink" description: "Comma-separated list of connector plugin crates to build as shared libraries" outputs: artifact_name: diff --git a/.github/workflows/edge-release.yml b/.github/workflows/edge-release.yml index 2514c3227a..7dde3b7192 100644 --- a/.github/workflows/edge-release.yml +++ b/.github/workflows/edge-release.yml @@ -105,6 +105,7 @@ jobs: - `iggy_connector_s3_sink` - `iggy_connector_stdout_sink` - `iggy_connector_surrealdb_sink` + - `iggy_connector_rabbitmq_sink` ## Downloads diff --git a/Cargo.lock b/Cargo.lock index 7856dd4133..98b0f147d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "actix-codec" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31404e1443b7b7bcaa311c1af456775cc3f668e34573f1503d7ce4844327629e" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ "bitflags 2.13.1", "bytes", @@ -59,12 +59,11 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.13.3" +version = "3.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11004b0e9b44b4eb3d15e0c3132b96fb178c7e50a74758b2f17bb9cc9a7fb4f6" +checksum = "86d62d1a48894ec9450bcde7ef1e3681205771ff6ea9c61cc5ae031145192787" dependencies = [ "actix-codec", - "actix-rt", "actix-service", "actix-utils", "base64 0.22.1", @@ -123,9 +122,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.13.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a16bf2f19c2ad84842bdfe6f3665620e93197d5c607889bfa3aaac45e762fd1" +checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" dependencies = [ "futures-core", "tokio", @@ -143,7 +142,7 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2", + "socket2 0.6.5", "tokio", "tracing", ] @@ -205,7 +204,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2", + "socket2 0.6.5", "time", "tracing", "url", @@ -235,7 +234,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "generic-array", ] @@ -262,13 +261,13 @@ dependencies = [ [[package]] name = "aes" -version = "0.9.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" +checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138" dependencies = [ "cipher 0.5.2", "cpubits", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", ] [[package]] @@ -292,7 +291,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" dependencies = [ "aead 0.6.1", - "aes 0.9.3", + "aes 0.9.1", "cipher 0.5.2", "ctr 0.10.1", "ctutils", @@ -327,9 +326,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -379,11 +378,59 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "amq-protocol" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "587d313f3a8b4a40f866cc84b6059fe83133bf172165ac3b583129dd211d8e1c" +dependencies = [ + "amq-protocol-tcp", + "amq-protocol-types", + "amq-protocol-uri", + "cookie-factory", + "nom 7.1.3", + "serde", +] + +[[package]] +name = "amq-protocol-tcp" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc707ab9aa964a85d9fc25908a3fdc486d2e619406883b3105b48bf304a8d606" +dependencies = [ + "amq-protocol-uri", + "tcp-stream", + "tracing", +] + +[[package]] +name = "amq-protocol-types" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf99351d92a161c61ec6ecb213bc7057f5b837dd4e64ba6cb6491358efd770c4" +dependencies = [ + "cookie-factory", + "nom 7.1.3", + "serde", + "serde_json", +] + +[[package]] +name = "amq-protocol-uri" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89f8273826a676282208e5af38461a07fe939def57396af6ad5997fcf56577d" +dependencies = [ + "amq-protocol-types", + "percent-encoding", + "url", +] + [[package]] name = "android_system_properties" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] @@ -503,14 +550,14 @@ checksum = "2b350bfd03649e07aa05c0a81b3e15934374e585c98204a57e20b9d49f49bb9a" dependencies = [ "keyring-core", "log", - "security-framework", + "security-framework 3.7.0", ] [[package]] name = "ar_archive_writer" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cd58deff2140a0a8eae87e417bd01db68a33e148aa93d1e8cd837e55e312b6" +checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348" dependencies = [ "object", ] @@ -549,7 +596,7 @@ checksum = "134c52ddac6d63c576bef8168db10c83c49c26444ecbc68060fef078925a901c" dependencies = [ "base64ct", "blake2", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "password-hash", ] @@ -714,7 +761,7 @@ dependencies = [ "arrow-select", "chrono", "half", - "indexmap 2.14.1", + "indexmap 2.14.2", "itoa", "lexical-core", "memchr", @@ -894,7 +941,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -914,9 +961,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.43" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3976abdc8fe7d1133d43d304afd42abdf5bc3e1319d263d223bde07b5efc4be8" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" dependencies = [ "compression-codecs", "compression-core", @@ -972,12 +1019,57 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.5.0", + "futures-lite 2.6.1", "pin-project-lite", "slab", ] +[[package]] +name = "async-global-executor" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13f937e26114b93193065fd44f507aa2e9169ad0cdabbb996920b1fe1ddea7ba" +dependencies = [ + "async-channel", + "async-executor", + "async-io 2.6.0", + "async-lock 3.4.2", + "blocking", + "futures-lite 2.6.1", +] + +[[package]] +name = "async-global-executor-trait" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af57045d58eeb1f7060e7025a1631cbc6399e0a1d10ad6735b3d0ea7f8346ce" +dependencies = [ + "async-global-executor", + "async-trait", + "executor-trait", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.28", + "slab", + "socket2 0.4.10", + "waker-fn", +] + [[package]] name = "async-io" version = "2.6.0" @@ -988,21 +1080,30 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "parking", - "polling", + "polling 3.11.0", "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -1014,17 +1115,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", - "async-io", - "async-lock", + "async-io 2.6.0", + "async-lock 3.4.2", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", + "event-listener 5.4.1", + "futures-lite 2.6.1", "rustix 1.1.4", ] +[[package]] +name = "async-reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6012d170ad00de56c9ee354aef2e358359deb1ec504254e0e5a3774771de0e" +dependencies = [ + "async-io 1.13.0", + "async-trait", + "futures-core", + "reactor-trait", +] + [[package]] name = "async-recursion" version = "1.1.1" @@ -1053,8 +1166,8 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" dependencies = [ - "async-io", - "async-lock", + "async-io 2.6.0", + "async-lock 3.4.2", "atomic-waker", "cfg-if", "futures-core", @@ -1101,7 +1214,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -1129,7 +1242,7 @@ dependencies = [ "async-compression", "binrw", "crc32fast", - "futures-lite", + "futures-lite 2.6.1", "pin-project", "thiserror 2.0.20", "tokio", @@ -1245,9 +1358,9 @@ dependencies = [ [[package]] name = "aws-config" -version = "1.11.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a767267da9e2c2e189b2f9df8b5657e850ecf5352644734ba130d4a57095cf1b" +checksum = "47712fde1909402600ccfbb26e47d482d2e58bb9e9e603d9f17e67cc435a6319" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1263,7 +1376,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.5.0", "hex", "http 1.5.0", "sha1 0.10.7", @@ -1338,9 +1451,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.9.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9007227e10b5fed2f3e0a2beff489211e2b5604c400b7a9d5d81ca9d64c24bb" +checksum = "7816e98ee912159f45d307e5ee6bfea4a335a55aee15f7f3e32f81a6f3000f1d" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -1352,7 +1465,7 @@ dependencies = [ "aws-types", "bytes", "bytes-utils", - "fastrand", + "fastrand 2.5.0", "http 1.5.0", "http-body 1.1.0", "percent-encoding", @@ -1363,9 +1476,9 @@ dependencies = [ [[package]] name = "aws-sdk-dynamodb" -version = "1.123.0" +version = "1.117.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcd10d92058d5da989a7838fd09d70e9457390a81ba672abf5685099f3562bce" +checksum = "0f2b4adcf6592e06ebb2c78235ae09cee178263a5b7fc20ae5ea07ca67067bb6" dependencies = [ "arc-swap", "aws-credential-types", @@ -1380,19 +1493,18 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.5.0", "http 0.2.12", "http 1.5.0", "regex-lite", "tracing", - "url", ] [[package]] name = "aws-sdk-sso" -version = "1.108.0" +version = "1.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15301b04372832947916607983b114b3374b9db0be058a00fb7513800de1f05" +checksum = "0469f435f645ad2162cfb463b15bde37115966ee3acf2d87fb4871ee309b8401" dependencies = [ "arc-swap", "aws-credential-types", @@ -1407,7 +1519,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.5.0", "http 0.2.12", "http 1.5.0", "regex-lite", @@ -1416,9 +1528,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.110.0" +version = "1.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72cc2c205cb27108183cf1856333f7d584c2ba0f505421b4209ca5828f9ea899" +checksum = "085faefb253f770655e162b9304321e62a1e71adf7f019ee1f4454228a377b3a" dependencies = [ "arc-swap", "aws-credential-types", @@ -1433,7 +1545,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.5.0", "http 0.2.12", "http 1.5.0", "regex-lite", @@ -1442,9 +1554,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.113.0" +version = "1.108.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68182ecb449f7537db0f4d5d25917789cf41e32074a9fe47b6a0b847fe1d2032" +checksum = "3c72b08911d8128dd360fe1b22a9fec0fa8b552dde8ec828dcf20ef5ec974e9f" dependencies = [ "arc-swap", "aws-credential-types", @@ -1460,7 +1572,7 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "fastrand", + "fastrand 2.5.0", "http 0.2.12", "http 1.5.0", "regex-lite", @@ -1523,21 +1635,21 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.4.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebfd138fac0337cee7516c352757ea73b9f2266e57d0bcb5bc70e9547e45aef1" +checksum = "635d23afda0a6ab48d666c4d447c4873e8d1e83518a2be2093122397e50b838e" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "h2 0.4.19", + "h2 0.4.15", "http 1.5.0", "hyper", "hyper-rustls", "hyper-util", "pin-project-lite", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "rustls-pki-types", "tokio", "tokio-rustls", @@ -1567,22 +1679,19 @@ dependencies = [ [[package]] name = "aws-smithy-query" -version = "0.62.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512346c7212ab7436df2d77a16d976a468ae44a418835511d2a69269810aaf62" +checksum = "dd22a6ba36e3f113cb8d5b3d1fe0ed31c76ee608ef63322d753bb8d2c9479e77" dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-schema", "aws-smithy-types", - "aws-smithy-xml", "urlencoding", ] [[package]] name = "aws-smithy-runtime" -version = "1.14.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b82e438d30e02a825d363bd639a9efaed68a8089d86101054b0081e7e0d3e606" +checksum = "bea94a9ff8464016338c851e24b472d7131c388c88898a502e781815b2ee6045" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -1592,7 +1701,7 @@ dependencies = [ "aws-smithy-schema", "aws-smithy-types", "bytes", - "fastrand", + "fastrand 2.5.0", "http 0.2.12", "http 1.5.0", "http-body 0.4.6", @@ -1606,9 +1715,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.15.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954c563ce84507722d2679f07a35d21b9c6466b3872d513020d0281fc8112ac9" +checksum = "22ed1ebe6e0a95ea84570225f5a8208dec4b8f77e61a9b0d6f51773fcb4612f0" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api-macros", @@ -1646,9 +1755,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.6.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce83ce9abbb198d25bc7131e468d0f9fe1257125e58c39f3f9fc9f5098c9647" +checksum = "d6dc683efb34b9e755675b37fedbe0103141e5b6df7bdc9eb6967756a8c167d8" dependencies = [ "base64-simd", "bytes", @@ -1672,9 +1781,9 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.62.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce84f71c72fee2cbbadde6e7d082f5fb466e3a84733855295fa7aafd1b31b7d8" +checksum = "ea3f68eec3607f02acd24067969ce2abc6ba16aa7d5ce59ca450ed2fb5f78957" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-schema", @@ -1684,9 +1793,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eec1cd5469f328c782dc3e33d4153cf118a54e33cbb3356d60d16f89883e1f94" +checksum = "e957a6c6dbce82b7a91f44231c09273159703769f447cbe85e854dfe9cf67f86" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -1795,7 +1904,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ - "fastrand", + "fastrand 2.5.0", "gloo-timers 0.3.0", "tokio", ] @@ -2100,7 +2209,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", ] [[package]] @@ -2123,11 +2232,11 @@ dependencies = [ [[package]] name = "block-padding" -version = "0.4.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "hybrid-array", + "generic-array", ] [[package]] @@ -2141,14 +2250,14 @@ dependencies = [ [[package]] name = "blocking" -version = "1.7.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "piper", ] @@ -2190,7 +2299,7 @@ dependencies = [ "pin-project-lite", "rand 0.9.5", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "rustls-pki-types", "serde", "serde_derive", @@ -2238,32 +2347,32 @@ dependencies = [ [[package]] name = "bon" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6" +checksum = "60eafe0d77c3a2fc292c1d1346c3041b33c0a108085a2afabf672b70f69dbbc9" dependencies = [ "bon-macros", ] [[package]] name = "bon-macros" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5" +checksum = "bd0f9631d8aaaee112c41985d675ef269e02acbd4f33122836af4f0c5f699ff6" dependencies = [ "darling 0.24.1", "ident_case", "prettyplease 0.3.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] name = "borsh" -version = "1.8.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +checksum = "a88b7ea17d208c4193f2c1e6de3c35fe71f98c96982d5ced308bdcc749ff6e1f" dependencies = [ "borsh-derive", "bytes", @@ -2272,15 +2381,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.8.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" +checksum = "d8f347189c62a579b8cd5f80714efa178f52e461dc2e6d701d264f5ff22e566c" dependencies = [ "once_cell", "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -2325,7 +2434,7 @@ dependencies = [ "getrandom 0.2.17", "getrandom 0.3.4", "hex", - "indexmap 2.14.1", + "indexmap 2.14.2", "js-sys", "once_cell", "rand 0.9.5", @@ -2338,9 +2447,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.13.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" dependencies = [ "memchr", "regex-automata", @@ -2371,7 +2480,7 @@ dependencies = [ "chrono", "crc", "futures", - "indexmap 2.14.1", + "indexmap 2.14.2", "itertools 0.14.0", "object_store", "parquet", @@ -2410,7 +2519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a813de7f2bbedb7dce265b64f1cf5908ebe4d56281ece8d847e98113788b9b0" dependencies = [ "rust_decimal", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "utf8-width", ] @@ -2454,13 +2563,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -2511,9 +2620,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.5" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" dependencies = [ "serde_core", ] @@ -2573,18 +2682,18 @@ dependencies = [ [[package]] name = "cbc" -version = "0.2.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" dependencies = [ - "cipher 0.5.2", + "cipher 0.4.4", ] [[package]] name = "cc" -version = "1.4.4" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" dependencies = [ "find-msvc-tools", "jobserver", @@ -2615,12 +2724,12 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "rand_core 0.10.1", ] @@ -2686,7 +2795,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "inout 0.1.4", ] @@ -2703,9 +2812,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.9.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -2753,7 +2862,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -2784,6 +2893,18 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" +[[package]] +name = "cms" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" +dependencies = [ + "const-oid 0.9.6", + "der", + "spki", + "x509-cert", +] + [[package]] name = "cobs" version = "0.3.0" @@ -2816,9 +2937,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.8" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -2889,7 +3010,7 @@ dependencies = [ "compio-log", "compio-send-wrapper", "crossbeam-queue", - "flume", + "flume 0.12.0", "futures-util", "io-uring", "libc", @@ -2897,10 +3018,10 @@ dependencies = [ "mod_use", "once_cell", "pastey 0.2.3", - "polling", + "polling 3.11.0", "rustix 1.1.4", "smallvec", - "socket2", + "socket2 0.6.5", "synchrony", "thin-cell", "windows-sys 0.61.2", @@ -2974,7 +3095,7 @@ dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -2992,7 +3113,7 @@ dependencies = [ "libc", "once_cell", "pin-project-lite", - "socket2", + "socket2 0.6.5", "synchrony", "widestring", "windows-sys 0.61.2", @@ -3010,7 +3131,7 @@ dependencies = [ "compio-log", "compio-net", "compio-runtime", - "flume", + "flume 0.12.0", "futures-util", "libc", "quinn-proto", @@ -3139,7 +3260,7 @@ dependencies = [ "darling 0.24.1", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -3277,6 +3398,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + [[package]] name = "core-foundation" version = "0.9.4" @@ -3338,9 +3465,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -3371,9 +3498,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -3473,9 +3600,9 @@ dependencies = [ [[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", "rand_core 0.6.4", @@ -3707,7 +3834,7 @@ dependencies = [ "hyper", "hyper-util", "send_wrapper", - "socket2", + "socket2 0.6.5", "tokio", "tower", "tower-service", @@ -3815,7 +3942,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -3859,7 +3986,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core 0.24.1", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -3878,9 +4005,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "data-url" @@ -4030,7 +4157,7 @@ dependencies = [ "either", "futures", "humantime", - "indexmap 2.14.1", + "indexmap 2.14.2", "itertools 0.14.0", "num_cpus", "object_store", @@ -4103,7 +4230,7 @@ dependencies = [ "deno_path_util", "deno_unsync", "futures", - "indexmap 2.14.1", + "indexmap 2.14.2", "libc", "parking_lot", "percent-encoding", @@ -4158,7 +4285,7 @@ version = "0.227.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bab1eaf578a8cc0ae6fb933e91dc3388b41df22e5974d5891c17ba66b3a0bbb" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "proc-macro-rules", "proc-macro2", "quote", @@ -4200,6 +4327,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid 0.9.6", + "der_derive", + "flagset", "pem-rfc7468", "zeroize", ] @@ -4218,6 +4347,17 @@ dependencies = [ "rusticata-macros", ] +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "deranged" version = "0.5.8" @@ -4314,6 +4454,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "des" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "difflib" version = "0.4.0" @@ -4328,7 +4477,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid 0.9.6", - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] @@ -4390,13 +4539,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -4424,7 +4573,7 @@ checksum = "1aacdd87ba97c2f83ff479e881e547f776b0a7c42921be22d4391f32b6284050" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -4436,6 +4585,12 @@ dependencies = [ "const-random", ] +[[package]] +name = "doc-comment" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" + [[package]] name = "docker_credential" version = "1.4.0" @@ -4541,9 +4696,9 @@ dependencies = [ [[package]] name = "either" -version = "1.18.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" dependencies = [ "serde", ] @@ -4777,10 +4932,17 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.2" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ + "concurrent-queue", "parking", "pin-project-lite", ] @@ -4791,10 +4953,19 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] +[[package]] +name = "executor-trait" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c39dff9342e4e0e16ce96be751eb21a94e94a87bb2f6e63ad1961c2ce109bf" +dependencies = [ + "async-trait", +] + [[package]] name = "expect-test" version = "1.5.1" @@ -4852,6 +5023,15 @@ dependencies = [ "serde", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.5.0" @@ -4947,9 +5127,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flagset" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "flatbuffers" @@ -4963,12 +5149,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.10" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "miniz_oxide 0.9.1", + "miniz_oxide 0.8.9", "zlib-rs", ] @@ -4987,13 +5173,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[package]] name = "flume" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" dependencies = [ - "fastrand", + "fastrand 2.5.0", "futures-core", "futures-sink", "spin", @@ -5162,13 +5359,28 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-lite" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand", + "fastrand 2.5.0", "futures-core", "futures-io", "parking", @@ -5183,7 +5395,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -5249,9 +5461,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -5369,15 +5581,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" -version = "0.4.20" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" +checksum = "e47d37d2ae4464254884b60ab7071be2b876a9c35b696bd018ddcc76847309cd" dependencies = [ "aho-corasick", "bstr", @@ -5817,7 +6029,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.14.1", + "indexmap 2.14.2", "slab", "tokio", "tokio-util", @@ -5826,9 +6038,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.19" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -5836,7 +6048,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.5.0", - "indexmap 2.14.1", + "indexmap 2.14.2", "slab", "tokio", "tokio-util", @@ -5867,9 +6079,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.4.4" +version = "6.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c54236f9045c8004a77942bebc52145b4844639db934a5c70fe08617fbe61a" +checksum = "4633d16a2350341713c379d6d06a4b9e1845329386026a49ce4fd09c2f3b16f6" dependencies = [ "derive_builder", "log", @@ -5887,7 +6099,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -5974,9 +6186,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.3" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -6154,9 +6372,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -6241,9 +6459,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] @@ -6258,7 +6476,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.19", + "h2 0.4.15", "http 1.5.0", "http-body 1.1.0", "httparse", @@ -6295,7 +6513,7 @@ dependencies = [ "hyper-util", "log", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "tokio", "tokio-rustls", "tower-service", @@ -6332,7 +6550,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.5", "system-configuration", "tokio", "tower-service", @@ -6478,9 +6696,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", @@ -6492,9 +6710,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -6505,9 +6723,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -6519,17 +6737,16 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -6540,15 +6757,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.3.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -6603,7 +6820,7 @@ dependencies = [ "bytemuck", "bytes", "dashmap", - "flume", + "flume 0.12.0", "futures", "futures-util", "iggy_binary_protocol", @@ -6709,7 +6926,7 @@ dependencies = [ "tempfile", "thiserror 2.0.20", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -6735,7 +6952,7 @@ dependencies = [ "dotenvy", "figlet-rs", "figment", - "flume", + "flume 0.12.0", "futures", "iggy", "iggy_common", @@ -6764,7 +6981,7 @@ dependencies = [ "tempfile", "thiserror 2.0.20", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tower-http 0.7.1", "tracing", "tracing-opentelemetry", @@ -6780,7 +6997,7 @@ dependencies = [ "bytes", "kafka-protocol", "libc", - "socket2", + "socket2 0.6.5", "thiserror 2.0.20", "tokio", "tokio-util", @@ -6811,7 +7028,7 @@ dependencies = [ "sd-notify", "serde", "serde_json", - "socket2", + "socket2 0.6.5", "strum 0.28.0", "tempfile", "thiserror 2.0.20", @@ -6885,7 +7102,7 @@ dependencies = [ "serde_json", "simd-json", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", ] @@ -6980,7 +7197,7 @@ dependencies = [ "simd-json", "strum_macros 0.28.0", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", ] @@ -7022,7 +7239,7 @@ dependencies = [ "serde_json", "simd-json", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", ] @@ -7047,7 +7264,7 @@ dependencies = [ "serde_json", "simd-json", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", "uuid", ] @@ -7141,6 +7358,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "iggy_connector_rabbitmq_sink" +version = "0.4.1-edge.1" +dependencies = [ + "async-trait", + "dashmap", + "iggy", + "iggy_common", + "iggy_connector_sdk", + "lapin", + "secrecy", + "serde", + "serde_json", + "tokio", + "tracing", +] + [[package]] name = "iggy_connector_random_source" version = "0.5.0-edge.4" @@ -7290,9 +7524,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.33" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" +checksum = "7f8a7b8211e695a1d0cd91cace480d4d0bd57667ab10277cc412c5f7f4884f83" dependencies = [ "crossbeam-deque", "globset", @@ -7324,7 +7558,7 @@ dependencies = [ "rayon", "rgb", "tiff", - "zune-core 0.5.3", + "zune-core 0.5.1", "zune-jpeg 0.5.15", ] @@ -7346,15 +7580,15 @@ checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" [[package]] name = "imgref" -version = "1.12.3" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" [[package]] name = "impl-more" -version = "0.3.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "277ff51754a3f68f12f58446c5d006aa8baa4914ea273cce24a599cfaff33d4f" +checksum = "35a84fd5aa25fae5c0f4a33d9cac2ca017fc622cbd089be2229993514990f870" [[package]] name = "implicit-clone" @@ -7363,7 +7597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1689b939ee35e3a075b0834b5672efd43aec8a6e81a1c6002b76a5ca2f211ae0" dependencies = [ "implicit-clone-derive", - "indexmap 2.14.1", + "indexmap 2.14.2", ] [[package]] @@ -7389,9 +7623,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.1" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -7413,9 +7647,9 @@ checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" [[package]] name = "inotify" -version = "0.11.5" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592" +checksum = "153be1941a183ec9ccd095ddbe17a8b8d435ef6c76e9e02451b933c3999af2c8" dependencies = [ "bitflags 2.13.1", "inotify-sys", @@ -7437,6 +7671,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ + "block-padding", "generic-array", ] @@ -7446,10 +7681,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "block-padding", "hybrid-array", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "integer-encoding" version = "3.0.4" @@ -7489,6 +7732,7 @@ dependencies = [ "journal", "jsonwebtoken 11.0.0", "keyring-core", + "lapin", "lazy_static", "libc", "mongodb", @@ -7515,7 +7759,7 @@ dependencies = [ "testcontainers-modules", "tokio", "tokio-postgres", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tracing", "tracing-subscriber", "twox-hash", @@ -7546,11 +7790,22 @@ dependencies = [ "rustversion", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "io-uring" -version = "0.7.14" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64d8ca234d152948ceaede1f419b6a83983a5ecccaac05fb337a809c96d3aa6" +checksum = "9080b15e63775b9a2ac7dca720f7050a8b955e092ea0f6020a4a80f69998cdc0" dependencies = [ "bitflags 2.13.1", "cfg-if", @@ -7563,7 +7818,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2", + "socket2 0.6.5", "widestring", "windows-registry", "windows-result 0.4.1", @@ -7572,9 +7827,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" dependencies = [ "serde", ] @@ -7620,9 +7875,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.35" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16" dependencies = [ "defmt", "jiff-core", @@ -7648,9 +7903,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.35" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de" dependencies = [ "jiff-core", "proc-macro2", @@ -7748,9 +8003,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", @@ -7771,7 +8026,7 @@ dependencies = [ "p256", "p384", "pem 3.0.6", - "rand 0.8.8", + "rand 0.8.7", "rsa", "serde", "serde_json", @@ -7795,7 +8050,7 @@ dependencies = [ "p256", "p384", "pem 3.0.6", - "rand 0.8.8", + "rand 0.8.7", "rsa", "serde", "serde_json", @@ -7824,7 +8079,7 @@ dependencies = [ "clap", "hex", "iggy-gateway-kafka", - "indexmap 2.14.1", + "indexmap 2.14.2", "kafka-protocol", "tokio", "tracing", @@ -7841,18 +8096,18 @@ dependencies = [ "bytes", "crc", "crc32c", - "indexmap 2.14.1", + "indexmap 2.14.2", "uuid", ] [[package]] name = "keccak" -version = "0.2.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", ] [[package]] @@ -7866,9 +8121,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.2.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d763e5b24120b4ddf50de6c92308156765aabfbbccebf401da7cff2d70a41ea" +checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5" dependencies = [ "kqueue-sys", "libc", @@ -7901,6 +8156,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lapin" +version = "2.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d2aa4725b9607915fa1a73e940710a3be6af508ce700e56897cbe8847fbb07" +dependencies = [ + "amq-protocol", + "async-global-executor-trait", + "async-reactor-trait", + "async-trait", + "executor-trait", + "flume 0.11.1", + "futures-core", + "futures-io", + "parking_lot", + "pinky-swear", + "reactor-trait", + "serde", + "tracing", + "waker-fn", +] + [[package]] name = "lazy-regex" version = "3.6.1" @@ -8031,9 +8308,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.18.8+1.9.7" +version = "0.18.5+1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7c568b25d7489bc3fb2988ed69ab111d2944d2f5fec3d5c987fe545ea97b50" +checksum = "005d6ae6eac1912906073e069f7db60b1fa98e052a68227824afe3e3a1c59ca2" dependencies = [ "cc", "libc", @@ -8053,18 +8330,18 @@ dependencies = [ [[package]] name = "liblzma" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe0a34ca854fd4f20c07f696fc8675aec78f87d88d29f5e10257a7490a1b2e1" +checksum = "45aec2360b3933207e27908049d8e4df4e476b58180afb1e56b2a4fb72efe4ba" dependencies = [ "liblzma-sys", ] [[package]] name = "liblzma-sys" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0dad045e4b1b7b170be4b60b54b780cafb4490165461bac7d1cf7b703f61d5f" +checksum = "a046c7f353ba30f810545151e04f63545833803f5b86ee3ddf1517247fe560a5" dependencies = [ "cc", "libc", @@ -8088,9 +8365,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.23" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -8141,6 +8418,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e57c38c1e860fd37c604281cdfb1dd2216977fd76a50f85ba2f388ef3219616" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -8155,9 +8438,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "local-channel" @@ -8172,9 +8455,9 @@ dependencies = [ [[package]] name = "local-event" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ab4b951e96ffb2da6e25cec3d038d0e2930f4c406d1ec194b5120ae41ec6d3" +checksum = "76dda8459b10a8960dfae91c1c77316fc15e7caf94f9f18794126512a8dc77e5" [[package]] name = "local-waker" @@ -8193,9 +8476,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.34" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "logos" @@ -8524,7 +8807,7 @@ dependencies = [ "rustls-pemfile", "scopeguard", "server_common", - "socket2", + "socket2 0.6.5", "tempfile", "thiserror 2.0.20", "tracing", @@ -8634,7 +8917,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" dependencies = [ "adler2", - "simd-adler32", ] [[package]] @@ -8683,16 +8965,16 @@ checksum = "21909324aa58f5c284d91cac514c6d081210901dc372d7c8ea6a9d7e0406097a" [[package]] name = "moka" -version = "0.12.16" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4293f18e7567a1caf3c584855554377025c65e0aa445344d04171f5ad63d19b9" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ - "async-lock", + "async-lock 3.4.2", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "equivalent", - "event-listener", + "event-listener 5.4.1", "futures-util", "parking_lot", "portable-atomic", @@ -8721,9 +9003,9 @@ checksum = "851fac73f7fe22f6a3ab87f720ce509cae7c9fd08e7dd27866cc232dee07ccf4" [[package]] name = "mongodb" -version = "3.8.2" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d220eb9ba80bad420e1f9efc4e895fede7418f8779a8e38a3b750e57ff397720" +checksum = "fd64784a1fdbcf2a334717446edc583061159067a2e7cc326ee567ecf035f07b" dependencies = [ "base64 0.22.1", "bitflags 2.13.1", @@ -8742,7 +9024,7 @@ dependencies = [ "md-5 0.11.0", "mongocrypt", "mongodb-internal-macros", - "pbkdf2", + "pbkdf2 0.13.0", "percent-encoding", "rand 0.9.5", "rustc_version_runtime", @@ -8752,7 +9034,7 @@ dependencies = [ "serde_with", "sha1 0.11.0", "sha2 0.11.0", - "socket2", + "socket2 0.6.5", "stringprep", "strsim", "take_mut", @@ -8767,9 +9049,9 @@ dependencies = [ [[package]] name = "mongodb-internal-macros" -version = "3.8.2" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e38ff3c46c59c2f4d9b26a86e6980dc23583e9d4b45aa579cef6584642093128" +checksum = "f243f9039382cd06378f13980b79700236468b6fb22f24abfa99783e9569f1a3" dependencies = [ "macro_magic", "proc-macro2", @@ -8947,7 +9229,7 @@ checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", - "rand 0.8.8", + "rand 0.8.7", "serde", ] @@ -8962,7 +9244,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.8", + "rand 0.8.7", "smallvec", "zeroize", ] @@ -8996,9 +9278,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.47" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] @@ -9015,9 +9297,9 @@ dependencies = [ [[package]] name = "num-modular" -version = "0.6.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8e500409e6cd603b03e477c26a6caecdc27ac58979a53e881c75eafc079f44" +checksum = "fc41a1374056e9672221567958a66c16be12d0e2c1b408761e14d901c237d5e0" [[package]] name = "num-order" @@ -9055,7 +9337,7 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi", + "hermit-abi 0.5.2", "libc", ] @@ -9136,9 +9418,9 @@ dependencies = [ [[package]] name = "object" -version = "0.39.1" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -9378,6 +9660,12 @@ dependencies = [ "url", ] +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + [[package]] name = "openssl-probe" version = "0.2.1" @@ -9560,6 +9848,28 @@ version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8" +[[package]] +name = "p12-keystore" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cae83056e7cb770211494a0ecf66d9fa7eba7d00977e5bb91f0e925b40b937f" +dependencies = [ + "cbc", + "cms", + "der", + "des", + "hex", + "hmac 0.12.1", + "pkcs12", + "pkcs5", + "rand 0.9.5", + "rc2", + "sha1 0.10.7", + "sha2 0.10.9", + "thiserror 2.0.20", + "x509-parser 0.17.0", +] + [[package]] name = "p256" version = "0.13.2" @@ -9747,6 +10057,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac 0.12.1", +] + [[package]] name = "pbkdf2" version = "0.13.0" @@ -9849,9 +10169,9 @@ checksum = "3637c05577168127568a64e9dc5a6887da720efef07b3d9472d45f63ab191166" [[package]] name = "pest" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", @@ -9859,9 +10179,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" dependencies = [ "pest", "pest_generator", @@ -9869,9 +10189,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" dependencies = [ "pest", "pest_meta", @@ -9882,9 +10202,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" dependencies = [ "pest", ] @@ -10019,6 +10339,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pinky-swear" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ea6e230dd3a64d61bcb8b79e597d3ab6b4c94ec7a234ce687dd718b4f2e657" +dependencies = [ + "doc-comment", + "flume 0.11.1", + "parking_lot", + "tracing", +] + [[package]] name = "pinned" version = "0.1.0" @@ -10037,7 +10369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.5.0", "futures-io", ] @@ -10052,6 +10384,36 @@ dependencies = [ "spki", ] +[[package]] +name = "pkcs12" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "695b3df3d3cc1015f12d70235e35b6b79befc5fa7a9b95b951eab1dd07c9efc2" +dependencies = [ + "cms", + "const-oid 0.9.6", + "der", + "digest 0.10.7", + "spki", + "x509-cert", + "zeroize", +] + +[[package]] +name = "pkcs5" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +dependencies = [ + "aes 0.8.4", + "cbc", + "der", + "pbkdf2 0.12.2", + "scrypt", + "sha2 0.10.9", + "spki", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -10064,9 +10426,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "png" @@ -10100,6 +10462,22 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dcdc93847ad24990939cce6e1804361e903efcb5f99daa5abd87943a9d6d7ba" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "polling" version = "3.11.0" @@ -10108,7 +10486,7 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.5.2", "pin-project-lite", "rustix 1.1.4", "windows-sys 0.61.2", @@ -10133,15 +10511,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ "cpubits", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "universal-hash 0.6.1", ] [[package]] name = "portable-atomic" -version = "1.15.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" [[package]] name = "portable-atomic-util" @@ -10200,9 +10578,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -10280,7 +10658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" dependencies = [ "proc-macro2", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -10441,7 +10819,7 @@ checksum = "01e34894696ff94f64a20c2c373a6440903e9c2789a303d68ec6e6f953f890e4" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -10517,9 +10895,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.32" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd034599e63b970727f70d79e02d62390a4a84f7c6b827c27c46d5ac3fa622" +checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" dependencies = [ "ar_archive_writer", "cc", @@ -10653,7 +11031,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2", + "socket2 0.6.5", "thiserror 2.0.20", "tokio", "tracing", @@ -10662,9 +11040,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.17" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", @@ -10694,7 +11072,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.6.5", "tracing", "windows-sys 0.61.2", ] @@ -10728,9 +11106,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.8" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -10899,6 +11277,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rc2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "rcgen" version = "0.14.10" @@ -10909,10 +11296,21 @@ dependencies = [ "ring", "rustls-pki-types", "time", - "x509-parser", + "x509-parser 0.18.1", "yasna", ] +[[package]] +name = "reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "438a4293e4d097556730f4711998189416232f009c137389e0f961d2bc0ddc58" +dependencies = [ + "async-trait", + "futures-core", + "futures-io", +] + [[package]] name = "reborrow" version = "0.5.5" @@ -10961,22 +11359,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.27" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.27" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -10993,9 +11391,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.18" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", @@ -11102,7 +11500,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "h2 0.4.19", + "h2 0.4.15", "http 1.5.0", "http-body 1.1.0", "http-body-util", @@ -11115,7 +11513,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "rustls-pki-types", "serde", "serde_json", @@ -11147,7 +11545,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.19", + "h2 0.4.15", "http 1.5.0", "http-body 1.1.0", "http-body-util", @@ -11346,13 +11744,13 @@ dependencies = [ "http 1.5.0", "http-body 1.1.0", "http-body-util", - "indexmap 2.14.1", + "indexmap 2.14.2", "pastey 0.2.3", "pin-project-lite", "rand 0.10.2", "reqwest 0.13.4", "rmcp-macros", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "sse-stream", @@ -11375,7 +11773,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -11399,9 +11797,9 @@ dependencies = [ [[package]] name = "roaring" -version = "0.11.5" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18bd8a37d17a58532776dcdf6041ce64929adca78e8489d5cacbafe99229d3e1" +checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9" dependencies = [ "bytemuck", "byteorder", @@ -11539,7 +11937,7 @@ dependencies = [ "bytes", "num-traits", "postgres-types", - "rand 0.8.8", + "rand 0.8.7", "rkyv", "serde", "serde_json", @@ -11580,6 +11978,20 @@ dependencies = [ "nom 7.1.3", ] +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.44" @@ -11608,9 +12020,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "6725596c3f2c3a0aef021139e145d4eafe314a6623e4680ca83852b2c67ab2ba" dependencies = [ "aws-lc-rs", "log", @@ -11622,16 +12034,42 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-connector" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70cc376c6ba1823ae229bacf8ad93c136d93524eab0e4e5e0e4f96b9c4e5b212" +dependencies = [ + "log", + "rustls", + "rustls-native-certs 0.7.3", + "rustls-pki-types", + "rustls-webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe 0.1.6", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework 2.11.1", +] + [[package]] name = "rustls-native-certs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.7.0", ] [[package]] @@ -11645,9 +12083,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -11665,10 +12103,10 @@ dependencies = [ "log", "once_cell", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.8.4", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -11741,6 +12179,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "same-file" version = "1.0.6" @@ -11773,9 +12220,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "chrono", "dyn-clone", @@ -11787,14 +12234,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -11809,6 +12256,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "pbkdf2 0.12.2", + "salsa20", + "sha2 0.10.9", +] + [[package]] name = "sd-notify" version = "0.5.0" @@ -11861,23 +12319,36 @@ dependencies = [ [[package]] name = "secret-service" -version = "5.2.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5107b24b91445dd2aa449a258a1807b63240942157292354dc5bfdbeb8bc6db8" +checksum = "9a62d7f86047af0077255a29494136b9aaaf697c76ff70b8e49cded4e2623c14" dependencies = [ - "aes 0.9.3", + "aes 0.8.4", "cbc", "futures-util", - "getrandom 0.4.3", - "hkdf 0.13.0", - "hybrid-array", + "generic-array", + "getrandom 0.2.17", + "hkdf 0.12.4", "num", "once_cell", "serde", - "sha2 0.11.0", + "sha2 0.10.9", "zbus", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -11993,18 +12464,18 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] name = "serde_derive_internals" -version = "0.30.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -12013,7 +12484,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "itoa", "memchr", "serde", @@ -12040,7 +12511,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -12098,10 +12569,10 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.1", + "indexmap 2.14.2", "jiff", "schemars 0.9.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -12126,7 +12597,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "itoa", "ryu", "serde", @@ -12155,7 +12626,7 @@ checksum = "a22144e767da4ddd8416dbf383700542ffd8a5dc493dfecedfe1fe3ad03c98ae" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -12229,15 +12700,15 @@ dependencies = [ "serde_json", "server_common", "shard", - "socket2", + "socket2 0.6.5", "strum 0.28.0", - "syn 3.0.4", + "syn 3.0.5", "sysinfo 0.39.6", "system_stats", "tempfile", "thiserror 2.0.20", "tokio", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "tower-http 0.7.1", "tracing", "tracing-appender", @@ -12306,7 +12777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] @@ -12328,7 +12799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] @@ -12486,7 +12957,7 @@ dependencies = [ "futures", "iggy_binary_protocol", "iggy_common", - "indexmap 2.14.1", + "indexmap 2.14.2", "journal", "message_bus", "metadata", @@ -12587,6 +13058,16 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886" +[[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.6.5" @@ -12707,14 +13188,14 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener", + "event-listener 5.4.1", "futures-core", "futures-intrusive", "futures-io", "futures-util", "hashbrown 0.16.1", "hashlink", - "indexmap 2.14.1", + "indexmap 2.14.2", "log", "memchr", "percent-encoding", @@ -12844,7 +13325,7 @@ checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c" dependencies = [ "atoi", "chrono", - "flume", + "flume 0.12.0", "form_urlencoded", "futures-channel", "futures-core", @@ -12864,9 +13345,9 @@ dependencies = [ [[package]] name = "sse-stream" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c123f296ade4ec4b8b0f6162116e6629f5146922ca5ab40ca9d3c2e73ab4761e" +checksum = "39f24a9b78c40b90817bbcd1821c74ddfd74916aadd29403d001532a9195532d" dependencies = [ "bytes", "futures-util", @@ -12883,9 +13364,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stacker" -version = "0.1.25" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" dependencies = [ "cc", "cfg-if", @@ -13057,9 +13538,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" dependencies = [ "proc-macro2", "quote", @@ -13081,7 +13562,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d6d5fbc4583cf3e5eee953506f13853a42ee6b4a21a983dffffb10c765cb80" dependencies = [ - "event-listener", + "event-listener 5.4.1", "futures-util", "local-event", "loom", @@ -13239,13 +13720,25 @@ dependencies = [ "xattr", ] +[[package]] +name = "tcp-stream" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495b0abdce3dc1f8fd27240651c9e68890c14e9d9c61527b1ce44d8a5a7bd3d5" +dependencies = [ + "cfg-if", + "p12-keystore", + "rustls-connector", + "rustls-pemfile", +] + [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "fastrand", + "fastrand 2.5.0", "getrandom 0.4.3", "once_cell", "rustix 1.1.4", @@ -13399,7 +13892,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -13438,9 +13931,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.55" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" dependencies = [ "deranged", "libc", @@ -13505,9 +13998,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -13540,20 +14033,20 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.5", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.7.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -13576,7 +14069,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.10.2", - "socket2", + "socket2 0.6.5", "tokio", "tokio-util", "whoami", @@ -13594,9 +14087,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -13666,11 +14159,11 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "serde_core", "serde_spanned 1.1.1", "toml_datetime 1.1.1+spec-1.1.0", @@ -13703,7 +14196,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -13714,7 +14207,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.2", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -13753,7 +14246,7 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.19", + "h2 0.4.15", "http 1.5.0", "http-body 1.1.0", "http-body-util", @@ -13762,7 +14255,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2", + "socket2 0.6.5", "sync_wrapper", "tokio", "tokio-stream", @@ -13815,7 +14308,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.14.1", + "indexmap 2.14.2", "pin-project-lite", "slab", "sync_wrapper", @@ -14153,7 +14646,7 @@ checksum = "f153acc4e99a5f2a5aefa09fb078be54e26271b2813f6041200b224c098d8328" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -14291,7 +14784,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] @@ -14325,11 +14818,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.4.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ - "base64 0.23.1", + "base64 0.22.1", "flate2", "log", "percent-encoding", @@ -14342,11 +14835,11 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.6.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ - "base64 0.23.1", + "base64 0.22.1", "http 1.5.0", "httparse", "log", @@ -14600,6 +15093,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -14654,9 +15153,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -14668,9 +15167,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -14678,9 +15177,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14688,9 +15187,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -14701,9 +15200,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] @@ -14760,9 +15259,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -14826,9 +15325,9 @@ dependencies = [ [[package]] name = "whoami" -version = "2.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" dependencies = [ "libc", "libredox", @@ -15079,6 +15578,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -15115,6 +15623,21 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -15166,6 +15689,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -15178,6 +15707,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -15190,6 +15725,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -15214,6 +15755,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -15226,6 +15773,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -15238,6 +15791,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -15250,6 +15809,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -15326,9 +15891,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "writeable" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" @@ -15339,6 +15904,17 @@ dependencies = [ "tap", ] +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid 0.9.6", + "der", + "spki", +] + [[package]] name = "x509-certificate" version = "0.25.0" @@ -15358,6 +15934,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509-parser" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "rusticata-macros", + "thiserror 2.0.20", + "time", +] + [[package]] name = "x509-parser" version = "0.18.1" @@ -15441,7 +16034,7 @@ dependencies = [ "futures", "gloo 0.11.0", "implicit-clone", - "indexmap 2.14.1", + "indexmap 2.14.2", "js-sys", "rustversion", "serde", @@ -15531,23 +16124,23 @@ checksum = "c6e61e59a957b7ccee15d2049f86e8bfd6f66968fcd88f018950662d9b86e675" [[package]] name = "zbus" -version = "5.19.0" +version = "5.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" +checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a" dependencies = [ "async-broadcast", "async-executor", - "async-io", - "async-lock", + "async-io 2.6.0", + "async-lock 3.4.2", "async-process", "async-recursion", "async-task", "async-trait", "blocking", "enumflags2", - "event-listener", + "event-listener 5.4.1", "futures-core", - "futures-lite", + "futures-lite 2.6.1", "hex", "libc", "ordered-stream", @@ -15577,14 +16170,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.19.0" +version = "5.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" +checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119" dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", "zbus_names", "zvariant", "zvariant_utils", @@ -15601,29 +16194,20 @@ dependencies = [ "zvariant", ] -[[package]] -name = "zcheapstr" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" -dependencies = [ - "serde", -] - [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" dependencies = [ "proc-macro2", "quote", @@ -15673,9 +16257,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -15684,9 +16268,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -15695,13 +16279,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.6" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", ] [[package]] @@ -15724,7 +16308,7 @@ checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "flate2", - "indexmap 2.14.1", + "indexmap 2.14.2", "memchr", "typed-path", "zopfli", @@ -15732,9 +16316,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.7" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" @@ -15790,9 +16374,9 @@ checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] name = "zune-core" -version = "0.5.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-inflate" @@ -15818,46 +16402,45 @@ version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ - "zune-core 0.5.3", + "zune-core 0.5.1", ] [[package]] name = "zvariant" -version = "5.15.0" +version = "5.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147" +checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911" dependencies = [ "endi", "enumflags2", "serde", "winnow 1.0.4", - "zcheapstr", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.15.0" +version = "5.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497" +checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12" dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.119", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "4.2.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" dependencies = [ "proc-macro2", "quote", "serde", - "syn 3.0.4", + "syn 2.0.119", "winnow 1.0.4", ] diff --git a/Cargo.toml b/Cargo.toml index beb92e80f4..90a554d630 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ members = [ "core/connectors/sinks/mongodb_sink", "core/connectors/sinks/postgres_sink", "core/connectors/sinks/quickwit_sink", + "core/connectors/sinks/rabbitmq_sink", "core/connectors/sinks/redshift_sink", "core/connectors/sinks/s3_sink", "core/connectors/sinks/stdout_sink", @@ -213,6 +214,7 @@ js-sys = "0.3" jsonwebtoken = { version = "11.0.0", features = ["rust_crypto"] } kafka-protocol = { version = "0.18.0", default-features = false, features = ["broker"] } keyring-core = "1.0.0" +lapin = "2.5.1" lazy_static = "1.5.0" left-right = "0.11" libc = "0.2.189" diff --git a/core/connectors/README.md b/core/connectors/README.md index 890a263b5f..f88b3d2554 100644 --- a/core/connectors/README.md +++ b/core/connectors/README.md @@ -86,6 +86,7 @@ Each sink should have its own, custom configuration, which is passed along with - **Meilisearch Sink** - indexes messages in Meilisearch - **PostgreSQL Sink** - stores messages in PostgreSQL database tables - **Quickwit Sink** - indexes messages in Quickwit search engine +- **RabbitMQ Sink** - publishes messages to RabbitMQ exchanges via AMQP 0.9.1 - **Reshift Sink** - stores messages in Redshift warehouse tables via S3 as staging - **S3 Sink** - writes messages to Amazon S3 and S3-compatible stores (MinIO, R2, B2, DO Spaces) - **Stdout Sink** - prints messages to standard output (useful for debugging/development) diff --git a/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml b/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml new file mode 100644 index 0000000000..8d09f65ee7 --- /dev/null +++ b/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +type = "sink" +key = "rabbitmq" +enabled = true +version = 0 +name = "RabbitMQ sink" +path = "target/release/libiggy_connector_rabbitmq_sink" +verbose = true + +[[streams]] +stream = "example_stream" +topics = ["example_topic"] +schema = "json" +batch_length = 100 +poll_interval = "5ms" +consumer_group = "rabbitmq_sink_connector" + +[plugin_config] +amqp_url = "amqp://guest:guest@localhost:5672" +exchange = "iggy_events" +exchange_type = "topic" +routing_key = "iggy.messages" +durable_exchange = true +delivery_mode = "persistent" +include_metadata = true +verbose_logging = false +max_retries = 3 +retry_delay_secs = 1 +max_retry_delay_secs = 5 +timeout_secs = 30 diff --git a/core/connectors/sinks/README.md b/core/connectors/sinks/README.md index 91de1fd084..1046edb4c3 100644 --- a/core/connectors/sinks/README.md +++ b/core/connectors/sinks/README.md @@ -19,6 +19,7 @@ Sink connectors are responsible for writing data from Iggy streams to external s | **s3_sink** | Writes messages to Amazon S3 and S3-compatible stores (MinIO, R2, B2, DO Spaces) | | **stdout_sink** | Prints messages to standard output (useful for debugging and development) | | **surrealdb_sink** | Writes messages into SurrealDB with deterministic record IDs for idempotent replay | +| **rabbitmq_sink** | Publishes messages to RabbitMQ exchanges via AMQP | The sink is represented by the single `Sink` trait, which defines the basic interface for all sink connectors. It provides methods for initializing the sink, writing data to external destination, and closing the sink. diff --git a/core/connectors/sinks/rabbitmq_sink/Cargo.toml b/core/connectors/sinks/rabbitmq_sink/Cargo.toml new file mode 100644 index 0000000000..2fd4dd715e --- /dev/null +++ b/core/connectors/sinks/rabbitmq_sink/Cargo.toml @@ -0,0 +1,51 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +name = "iggy_connector_rabbitmq_sink" +version = "0.4.1-edge.1" +description = "Iggy RabbitMQ sink connector for publishing stream messages to RabbitMQ exchanges via AMQP 0.9.1" +edition = "2024" +license = "Apache-2.0" +keywords = ["iggy", "messaging", "streaming", "rabbitmq", "amqp", "sink"] +categories = ["command-line-utilities", "database", "network-programming"] +homepage = "https://iggy.apache.org" +documentation = "https://iggy.apache.org/docs" +repository = "https://github.com/apache/iggy" +readme = "../../README.md" +publish = false + +[package.metadata.cargo-machete] +ignored = ["dashmap"] + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +async-trait = { workspace = true } +dashmap = { workspace = true } +iggy = { workspace = true } +iggy_common = { workspace = true } +iggy_connector_sdk = { workspace = true } +lapin = { workspace = true } +secrecy = { workspace = true } +serde = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } + +[dev-dependencies] +serde_json = { workspace = true } diff --git a/core/connectors/sinks/rabbitmq_sink/README.md b/core/connectors/sinks/rabbitmq_sink/README.md new file mode 100644 index 0000000000..28a8ffd052 --- /dev/null +++ b/core/connectors/sinks/rabbitmq_sink/README.md @@ -0,0 +1,50 @@ +# RabbitMQ Sink + +The RabbitMQ sink connector publishes messages from Iggy streams to RabbitMQ exchanges via AMQP 0.9.1. + +## Configuration + +| Field | Type | Default | Description | +| --- | --- | --- | --- | +| `amqp_url` | string | `amqp://guest:guest@localhost:5672` | RabbitMQ connection URL, including credentials. Treated as a secret: never logged or serialized verbatim. | +| `exchange` | string | `iggy_events` | Exchange name to publish to. | +| `exchange_type` | string | `topic` | Exchange type: `direct`, `topic`, `fanout`, `headers`. | +| `routing_key` | string | `iggy.messages` | Routing key for published messages. | +| `durable_exchange` | bool | `true` | Declare the exchange as durable. Must match the durability of an operator-pre-created exchange, otherwise RabbitMQ closes the channel with `PRECONDITION_FAILED`. | +| `delivery_mode` | string | `persistent` | AMQP delivery mode: `persistent` (2) or `non_persistent` (1). Persistent messages survive broker restarts when the exchange and queue are durable; it forces an fsync on publish, so non-durable topologies may prefer `non_persistent`. | +| `include_metadata` | bool | `true` | Add `iggy_stream`, `iggy_topic`, `iggy_partition_id`, `iggy_offset` message headers. User-supplied headers are always preserved, regardless of this flag. | +| `verbose_logging` | bool | `false` | Log each published batch at `info` level instead of `debug`. | +| `max_retries` | u32 | `3` | Maximum transient publish retries before failing the batch. | +| `retry_delay_secs` | u64 | `1` | Base retry delay in seconds. | +| `max_retry_delay_secs` | u64 | `5` | Upper bound for exponential backoff. | +| `timeout_secs` | u64 | `30` | Timeout for connection, publish, and publisher-confirmation operations. | + +User headers on consumed Iggy messages are forwarded as AMQP headers: string values become AMQP `LongString`, raw binary values become `ByteArray`. This allows routing through a `headers` exchange on original user headers. + +Publishes are confirmed via `ConfirmSelect`. With `mandatory = true`, a message with a routing key that matches no binding is returned by RabbitMQ and the batch fails with a permanent error. + +**Delivery guarantee:** in-request retry only. Transient failures (connection loss, `Nack`, channel exceptions, +timeouts) are retried within a single `consume()` call up to `max_retries`, resuming at the first unconfirmed +message. Publishes are pipelined (all messages sent, then confirmed in order), so a failure mid-batch can already +have delivered the in-flight tail; resuming re-publishes those, so delivery is **at-least-once within a batch**. +Because lapin does not attribute a `Basic.Return` to a specific in-flight publish, any returned message fails the +whole batch and the connection is re-established before the next poll, so a channel with unresolved confirms is +never reused. The connectors runtime commits the consumer offset at poll time and discards `consume()`'s return +value, so there is no cross-poll redrive or DLQ: a failure that outlives the retry budget, or a crash mid-batch, is +**at-most-once** across polls. + +```toml +[plugin_config] +amqp_url = "amqp://guest:guest@localhost:5672" +exchange = "iggy_events" +exchange_type = "topic" +routing_key = "iggy.messages" +durable_exchange = true +delivery_mode = "persistent" +include_metadata = true +verbose_logging = false +max_retries = 3 +retry_delay_secs = 1 +max_retry_delay_secs = 5 +timeout_secs = 30 +``` diff --git a/core/connectors/sinks/rabbitmq_sink/config.toml b/core/connectors/sinks/rabbitmq_sink/config.toml new file mode 100644 index 0000000000..4c6bbfc00e --- /dev/null +++ b/core/connectors/sinks/rabbitmq_sink/config.toml @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +type = "sink" +key = "rabbitmq" +enabled = true +version = 0 +name = "RabbitMQ sink" +path = "../../target/release/libiggy_connector_rabbitmq_sink" +verbose = true + +[[streams]] +stream = "test_stream" +topics = ["test_topic"] +schema = "json" +batch_length = 100 +poll_interval = "5ms" +consumer_group = "rabbitmq_sink_connector" + +[plugin_config] +amqp_url = "amqp://guest:guest@localhost:5672" +exchange = "iggy_events" +exchange_type = "topic" +routing_key = "iggy.messages" +durable_exchange = true +delivery_mode = "persistent" +include_metadata = true +verbose_logging = false +max_retries = 3 +retry_delay_secs = 1 +max_retry_delay_secs = 5 +timeout_secs = 30 diff --git a/core/connectors/sinks/rabbitmq_sink/src/lib.rs b/core/connectors/sinks/rabbitmq_sink/src/lib.rs new file mode 100644 index 0000000000..69504096e9 --- /dev/null +++ b/core/connectors/sinks/rabbitmq_sink/src/lib.rs @@ -0,0 +1,783 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use async_trait::async_trait; +use iggy::prelude::HeaderKind; +use iggy_connector_sdk::retry::{exponential_backoff, jitter}; +use iggy_connector_sdk::{ + ConsumedMessage, Error, MessagesMetadata, Sink, TopicMetadata, sink_connector, +}; +use lapin::{ + BasicProperties, Channel, Connection, ConnectionProperties, ExchangeKind, + options::{ConfirmSelectOptions, ExchangeDeclareOptions}, + publisher_confirm::{Confirmation, PublisherConfirm}, + types::{AMQPValue, ByteArray, FieldTable, ShortString}, +}; +use secrecy::{ExposeSecret, SecretString}; +use serde::{Deserialize, Serialize}; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::time::Duration; +use tokio::sync::Mutex; +use tokio::time::timeout; +use tracing::{debug, info, warn}; + +sink_connector!(RabbitMQSink); + +#[derive(Debug)] +struct RabbitMqState { + connection: Connection, + channel: Channel, +} + +#[derive(Debug)] +pub struct RabbitMQSink { + id: u32, + amqp_url: SecretString, + exchange: String, + exchange_type: String, + routing_key: String, + include_metadata: bool, + verbose: bool, + durable_exchange: bool, + delivery_mode: u8, + timeout: Duration, + state: Mutex>, + reconnect_lock: Mutex<()>, + publish_lock: Mutex<()>, + max_retries: u32, + retry_delay: Duration, + max_retry_delay: Duration, + messages_published: AtomicU64, + publish_errors: AtomicU64, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct RabbitMQSinkConfig { + #[serde( + default = "default_amqp_url", + serialize_with = "iggy_common::serde_secret::serialize_secret" + )] + amqp_url: SecretString, + #[serde(default)] + exchange: Option, + #[serde(default = "default_exchange_type")] + exchange_type: Option, + #[serde(default)] + routing_key: Option, + #[serde(default = "default_true")] + include_metadata: Option, + #[serde(default)] + verbose_logging: Option, + #[serde(default = "default_max_retries")] + max_retries: Option, + #[serde(default = "default_retry_delay_secs")] + retry_delay_secs: Option, + #[serde(default = "default_max_retry_delay_secs")] + max_retry_delay_secs: Option, + #[serde(default = "default_true")] + durable_exchange: Option, + #[serde(default = "default_delivery_mode")] + delivery_mode: Option, + #[serde(default = "default_timeout_secs")] + timeout_secs: Option, +} + +fn default_exchange_type() -> Option { + Some("topic".into()) +} + +fn default_amqp_url() -> SecretString { + SecretString::from("amqp://guest:guest@localhost:5672") +} + +fn default_delivery_mode() -> Option { + Some("persistent".into()) +} + +fn default_timeout_secs() -> Option { + Some(30) +} + +fn append_connection_timeout(amqp_url: &SecretString, timeout_secs: u64) -> SecretString { + let timeout_ms = timeout_secs * 1000; + let url = amqp_url.expose_secret(); + let separator = if url.contains('?') { '&' } else { '?' }; + SecretString::from(format!("{url}{separator}connection_timeout={timeout_ms}")) +} + +fn default_true() -> Option { + Some(true) +} + +fn default_max_retries() -> Option { + Some(3) +} +fn default_retry_delay_secs() -> Option { + Some(1) +} +fn default_max_retry_delay_secs() -> Option { + Some(5) +} + +impl RabbitMQSink { + pub fn new(id: u32, config: RabbitMQSinkConfig) -> Self { + let delivery_mode = match config.delivery_mode.as_deref() { + Some("non_persistent") => 1, + Some("persistent") => 2, + Some(other) => { + warn!( + "Unknown delivery_mode: {other}, defaulting to persistent for connector ID: {id}" + ); + 2 + } + None => 2, + }; + let timeout_secs = match config.timeout_secs { + Some(0) | None => { + if config.timeout_secs == Some(0) { + warn!("timeout_secs must be >= 1, defaulting to 30 for connector ID: {id}"); + } + 30 + } + Some(secs) => secs, + }; + let amqp_url = append_connection_timeout(&config.amqp_url, timeout_secs); + RabbitMQSink { + id, + amqp_url, + exchange: config.exchange.unwrap_or_else(|| "iggy_events".into()), + exchange_type: config.exchange_type.unwrap_or_else(|| "topic".into()), + routing_key: config.routing_key.unwrap_or_else(|| "iggy.messages".into()), + include_metadata: config.include_metadata.unwrap_or(true), + verbose: config.verbose_logging.unwrap_or(false), + durable_exchange: config.durable_exchange.unwrap_or(true), + delivery_mode, + timeout: Duration::from_secs(timeout_secs), + state: Mutex::new(None), + reconnect_lock: Mutex::new(()), + publish_lock: Mutex::new(()), + max_retries: config.max_retries.unwrap_or(3), + retry_delay: Duration::from_secs(config.retry_delay_secs.unwrap_or(1)), + max_retry_delay: Duration::from_secs(config.max_retry_delay_secs.unwrap_or(5)), + messages_published: AtomicU64::new(0), + publish_errors: AtomicU64::new(0), + } + } + + fn exchange_kind(&self) -> Result { + match self.exchange_type.as_str() { + "direct" => Ok(ExchangeKind::Direct), + "topic" => Ok(ExchangeKind::Topic), + "fanout" => Ok(ExchangeKind::Fanout), + "headers" => Ok(ExchangeKind::Headers), + other => Err(Error::InvalidConfigValue(format!( + "unknown exchange_type: {other}. Valid: direct, topic, fanout, headers" + ))), + } + } + + async fn publish_batch_with_retry( + &self, + topic_metadata: &TopicMetadata, + messages_metadata: &MessagesMetadata, + messages: &[ConsumedMessage], + ) -> Result { + // The connectors runtime runs one consume task per (stream, topic) pair against a + // single sink instance, so batches would otherwise interleave on the shared channel. + // Serialize them: a Basic.Return staples to whichever confirm resolves next, and with + // two publishers in flight it can land on the other task's confirm, letting this batch + // count a returned message as delivered. + let _publish_guard = self.publish_lock.lock().await; + let mut attempts = 0u32; + let mut confirmed: usize = 0; + + loop { + let channel = match self + .state + .lock() + .await + .as_ref() + .map(|state| state.channel.clone()) + { + Some(channel) => channel, + None => { + let error = Error::Connection("RabbitMQ not connected".into()); + attempts += 1; + if attempts >= self.max_retries { + self.publish_errors + .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed); + return Err(error); + } + if let Err(reconnect_error) = self.reconnect().await { + self.publish_errors + .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed); + return Err(Error::Connection(format!( + "failed to reconnect: {reconnect_error}" + ))); + } + let delay = jitter(exponential_backoff( + self.retry_delay, + attempts.saturating_sub(1), + self.max_retry_delay, + )); + warn!( + "RabbitMQ not connected for connector ID: {} (attempt {attempts}/{}). Retrying in {:?}.", + self.id, self.max_retries, delay + ); + tokio::time::sleep(delay).await; + continue; + } + }; + + let mut last_error: Option = None; + let mut last_retryable = false; + let mut in_flight: Vec = + Vec::with_capacity(messages.len() - confirmed); + for message in &messages[confirmed..] { + let body = match message.payload.try_to_bytes() { + Ok(body) => body, + Err(error) => { + // Earlier publishes in this attempt are still in flight; drop the + // channel so their orphaned confirms never leak onto a reused one. + self.clear_state().await; + self.publish_errors + .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed); + return Err(error); + } + }; + let mut props = BasicProperties::default().with_delivery_mode(self.delivery_mode); + let headers = self.build_headers(topic_metadata, messages_metadata, message); + if !headers.inner().is_empty() { + props = props.with_headers(headers); + } + + let confirm = match timeout( + self.timeout, + channel.basic_publish( + &self.exchange, + &self.routing_key, + lapin::options::BasicPublishOptions { + mandatory: true, + ..Default::default() + }, + &body, + props, + ), + ) + .await + { + Ok(Ok(confirm)) => confirm, + Ok(Err(e)) => { + last_error = Some(Error::CannotStoreData(e.to_string())); + last_retryable = is_lapin_error_retryable(&e); + self.clear_state().await; + break; + } + Err(_) => { + last_error = Some(Error::CannotStoreData("publish timed out".into())); + last_retryable = true; + self.clear_state().await; + break; + } + }; + in_flight.push(confirm); + } + + // Confirms resolve in publish order over already-overlapped RTTs. + // lapin staples a Basic.Return to whichever confirm resolves next, so under + // multiple-ack the returned message is not attributable to a specific publish: + // on any return the whole batch fails and the channel is cleared so a channel + // with unresolved confirms is never reused (a later batch could otherwise + // swallow the return and count the unroutable message as delivered). + for confirm in in_flight { + match timeout(self.timeout, confirm).await { + Ok(Ok(Confirmation::Ack(None))) => confirmed += 1, + Ok(Ok(Confirmation::Ack(Some(_)))) => { + last_error = Some(Error::InvalidRecordValue( + "message returned as unroutable by RabbitMQ".into(), + )); + last_retryable = false; + self.clear_state().await; + break; + } + Ok(Ok(Confirmation::Nack(_))) => { + last_error = + Some(Error::CannotStoreData("message nack'd by RabbitMQ".into())); + last_retryable = true; + self.clear_state().await; + break; + } + Ok(Ok(Confirmation::NotRequested)) => { + last_error = Some(Error::CannotStoreData( + "publisher confirms not enabled".into(), + )); + last_retryable = false; + self.clear_state().await; + break; + } + Ok(Err(e)) => { + last_error = Some(Error::CannotStoreData(format!("publish rejected: {e}"))); + last_retryable = is_lapin_error_retryable(&e); + self.clear_state().await; + break; + } + Err(_) => { + last_error = Some(Error::CannotStoreData( + "publisher confirmation timed out".into(), + )); + last_retryable = true; + self.clear_state().await; + break; + } + } + } + + if last_error.is_none() { + return Ok(confirmed as u64); + } + + let error = last_error.unwrap(); + attempts += 1; + + if !last_retryable || attempts >= self.max_retries { + self.publish_errors + .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed); + return Err(Error::CannotStoreData(format!( + "batch publish failed after {attempts} attempts: {error}" + ))); + } + + match self.reconnect().await { + Ok(_) => {} + Err(reconnect_error) => { + self.publish_errors + .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed); + return Err(Error::Connection(format!( + "failed to reconnect: {reconnect_error}" + ))); + } + } + + let delay = jitter(exponential_backoff( + self.retry_delay, + attempts.saturating_sub(1), + self.max_retry_delay, + )); + warn!( + "Transient RabbitMQ publish error for connector ID: {} (attempt {attempts}/{}): {error}. Retrying in {:?}.", + self.id, self.max_retries, delay + ); + tokio::time::sleep(delay).await; + } + } + + async fn clear_state(&self) { + *self.state.lock().await = None; + } + + fn build_headers( + &self, + topic_metadata: &TopicMetadata, + messages_metadata: &MessagesMetadata, + message: &ConsumedMessage, + ) -> FieldTable { + let mut headers = FieldTable::default(); + if let Some(user_headers) = &message.headers + && !user_headers.is_empty() + { + for (key, value) in user_headers { + let name = ShortString::from(key.to_string_value()); + let amqp_value = match value.kind() { + HeaderKind::String => AMQPValue::LongString(value.to_string_value().into()), + _ => AMQPValue::ByteArray(ByteArray::from(value.as_bytes())), + }; + headers.insert(name, amqp_value); + } + } + if self.include_metadata { + headers.insert( + "iggy_stream".into(), + AMQPValue::LongString(topic_metadata.stream.clone().into()), + ); + headers.insert( + "iggy_topic".into(), + AMQPValue::LongString(topic_metadata.topic.clone().into()), + ); + headers.insert( + "iggy_partition_id".into(), + AMQPValue::LongUInt(messages_metadata.partition_id), + ); + headers.insert( + "iggy_offset".into(), + AMQPValue::LongLongInt(message.offset as i64), + ); + } + headers + } + + async fn reconnect(&self) -> Result<(), Error> { + let _guard = self.reconnect_lock.lock().await; + if self.state.lock().await.is_some() { + return Ok(()); + } + warn!("Reconnecting RabbitMQ sink ID: {}", self.id); + let state = self.connect_with_timeout().await?; + *self.state.lock().await = Some(state); + Ok(()) + } + + async fn connect_with_timeout(&self) -> Result { + timeout(self.timeout, self.establish_connection()) + .await + .map_err(|_| Error::Connection("connection setup timed out".into()))? + } + + async fn establish_connection(&self) -> Result { + let connection = Connection::connect( + self.amqp_url.expose_secret(), + ConnectionProperties::default(), + ) + .await + .map_err(|e| Error::Connection(e.to_string()))?; + let channel = connection + .create_channel() + .await + .map_err(|e| Error::Connection(e.to_string()))?; + channel + .confirm_select(ConfirmSelectOptions::default()) + .await + .map_err(|e| Error::Connection(e.to_string()))?; + let exchange_kind = self.exchange_kind()?; + channel + .exchange_declare( + &self.exchange, + exchange_kind, + ExchangeDeclareOptions { + durable: self.durable_exchange, + ..Default::default() + }, + FieldTable::default(), + ) + .await + .map_err(|e| Error::Connection(e.to_string()))?; + Ok(RabbitMqState { + connection, + channel, + }) + } +} + +#[async_trait] +impl Sink for RabbitMQSink { + async fn open(&mut self) -> Result<(), Error> { + self.exchange_kind()?; + let state = self.connect_with_timeout().await?; + *self.state.get_mut() = Some(state); + info!( + "Opened RabbitMQ sink ID: {}, connected to exchange: {}", + self.id, self.exchange + ); + + Ok(()) + } + + async fn consume( + &self, + topic_metadata: &TopicMetadata, + messages_metadata: MessagesMetadata, + messages: Vec, + ) -> Result<(), Error> { + let published = self + .publish_batch_with_retry(topic_metadata, &messages_metadata, &messages) + .await?; + self.messages_published + .fetch_add(published, Ordering::Relaxed); + if self.verbose { + info!( + "Published {published} messages to exchange: {}", + self.exchange + ); + } else { + debug!( + "Published {published} messages to exchange: {}", + self.exchange + ); + } + Ok(()) + } + + async fn close(&mut self) -> Result<(), Error> { + let published = self.messages_published.load(Ordering::Relaxed); + let errors = self.publish_errors.load(Ordering::Relaxed); + info!( + "RabbitMQ sink ID: {} processed {} messages with {} errors", + self.id, published, errors + ); + + if let Some(state) = self.state.get_mut().take() { + state + .channel + .close(200, "OK") + .await + .map_err(|e| Error::Connection(e.to_string()))?; + state + .connection + .close(200, "OK") + .await + .map_err(|e| Error::Connection(e.to_string()))?; + } + Ok(()) + } +} + +fn is_lapin_error_retryable(error: &lapin::Error) -> bool { + match error { + lapin::Error::InvalidChannelState(_) + | lapin::Error::InvalidConnectionState(_) + | lapin::Error::IOError(_) + | lapin::Error::MissingHeartbeatError => true, + // AMQP soft channel errors: 405 RESOURCE_LOCKED, 320 CONNECTION_FORCED. + lapin::Error::ProtocolError(amqp_error) => matches!(amqp_error.get_id(), 320 | 405), + _ => false, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use iggy::prelude::{HeaderKey, HeaderValue}; + use iggy_connector_sdk::{Payload, Schema}; + use std::str::FromStr; + + fn test_config() -> RabbitMQSinkConfig { + RabbitMQSinkConfig { + amqp_url: SecretString::from("amqp://guest:guest@localhost:5672"), + exchange: None, + exchange_type: None, + routing_key: None, + include_metadata: Some(true), + verbose_logging: Some(false), + max_retries: Some(3), + retry_delay_secs: Some(1), + max_retry_delay_secs: Some(5), + durable_exchange: None, + delivery_mode: None, + timeout_secs: None, + } + } + + fn test_sink(config: RabbitMQSinkConfig) -> RabbitMQSink { + RabbitMQSink::new(1, config) + } + + fn test_message(offset: u64) -> ConsumedMessage { + ConsumedMessage { + id: 1, + offset, + checksum: 0, + timestamp: 0, + origin_timestamp: 0, + headers: None, + payload: Payload::Text("payload".into()), + } + } + + #[test] + fn given_offset_above_u32_max_when_build_headers_should_encode_full_value() { + let sink = test_sink(test_config()); + let topic = TopicMetadata { + stream: "test_stream".into(), + topic: "test_topic".into(), + }; + let metadata = MessagesMetadata { + partition_id: 0, + current_offset: 0, + schema: Schema::Json, + }; + let headers = sink.build_headers(&topic, &metadata, &test_message(u32::MAX as u64 + 1)); + match headers.inner().get(&ShortString::from("iggy_offset")) { + Some(AMQPValue::LongLongInt(value)) => assert_eq!(*value, u32::MAX as i64 + 1), + other => panic!("expected LongLongInt, got {other:?}"), + } + } + + #[test] + fn given_user_headers_when_build_headers_should_preserve_string_and_binary() { + let mut user_headers = std::collections::BTreeMap::new(); + user_headers.insert( + HeaderKey::from_str("content-type").unwrap(), + HeaderValue::from_str("application/json").unwrap(), + ); + user_headers.insert( + HeaderKey::from_str("trace-id").unwrap(), + HeaderValue::try_from(vec![0xDE, 0xAD, 0xBE, 0xEF]).unwrap(), + ); + let mut message = test_message(0); + message.headers = Some(user_headers); + + let sink = test_sink(test_config()); + let topic = TopicMetadata { + stream: "test_stream".into(), + topic: "test_topic".into(), + }; + let metadata = MessagesMetadata { + partition_id: 0, + current_offset: 0, + schema: Schema::Json, + }; + let headers = sink.build_headers(&topic, &metadata, &message); + let inner = headers.inner(); + assert!(matches!( + inner.get(&ShortString::from("content-type")), + Some(AMQPValue::LongString(s)) if s.as_bytes() == b"application/json" + )); + assert!(matches!( + inner.get(&ShortString::from("trace-id")), + Some(AMQPValue::ByteArray(b)) if b.as_slice() == [0xDE, 0xAD, 0xBE, 0xEF] + )); + } + + #[test] + fn given_persistent_delivery_mode_when_new_should_set_delivery_mode_2() { + let sink = test_sink(test_config()); + assert_eq!(sink.delivery_mode, 2); + } + + #[test] + fn given_non_persistent_delivery_mode_when_new_should_set_delivery_mode_1() { + let mut config = test_config(); + config.delivery_mode = Some("non_persistent".into()); + let sink = test_sink(config); + assert_eq!(sink.delivery_mode, 1); + } + + #[test] + fn given_durable_exchange_when_new_should_default_to_true() { + let sink = test_sink(test_config()); + assert!(sink.durable_exchange); + } + + #[test] + fn given_known_exchange_type_when_exchange_kind_should_map_to_lapin_kind() { + let sink = test_sink(test_config()); + assert!(matches!(sink.exchange_kind(), Ok(ExchangeKind::Topic))); + } + + #[test] + fn given_unknown_exchange_type_when_exchange_kind_should_error() { + let mut config = test_config(); + config.exchange_type = Some("mystery".into()); + let sink = test_sink(config); + assert!(matches!( + sink.exchange_kind(), + Err(Error::InvalidConfigValue(_)) + )); + } + + #[test] + fn given_transient_lapin_error_when_is_lapin_error_retryable_should_return_true() { + let errors = [ + lapin::Error::InvalidChannelState(lapin::ChannelState::Closed), + lapin::Error::InvalidConnectionState(lapin::ConnectionState::Error), + lapin::Error::IOError(std::sync::Arc::new(std::io::Error::new( + std::io::ErrorKind::ConnectionReset, + "reset by peer", + ))), + lapin::Error::MissingHeartbeatError, + lapin::Error::ProtocolError(lapin::protocol::AMQPError::new( + lapin::protocol::AMQPErrorKind::Soft( + lapin::protocol::AMQPSoftError::RESOURCELOCKED, + ), + "RESOURCE_LOCKED".into(), + )), + ]; + for error in errors { + assert!( + is_lapin_error_retryable(&error), + "expected {error:?} to be retryable" + ); + } + } + + #[test] + fn given_permanent_lapin_error_when_is_lapin_error_retryable_should_return_false() { + let errors = [ + lapin::Error::ProtocolError(lapin::protocol::AMQPError::new( + lapin::protocol::AMQPErrorKind::Soft( + lapin::protocol::AMQPSoftError::PRECONDITIONFAILED, + ), + "PRECONDITION_FAILED".into(), + )), + lapin::Error::InvalidChannel(0), + ]; + for error in errors { + assert!( + !is_lapin_error_retryable(&error), + "expected {error:?} to be permanent" + ); + } + } + + #[test] + fn given_timeout_secs_when_new_should_set_timeout() { + let mut config = test_config(); + config.timeout_secs = Some(7); + let sink = test_sink(config); + assert_eq!(sink.timeout, Duration::from_secs(7)); + } + + #[test] + fn given_zero_timeout_secs_when_new_should_default_to_30() { + let mut config = test_config(); + config.timeout_secs = Some(0); + let sink = test_sink(config); + assert_eq!(sink.timeout, Duration::from_secs(30)); + assert!( + sink.amqp_url + .expose_secret() + .ends_with("connection_timeout=30000") + ); + } + + #[test] + fn given_minimal_config_when_deserialized_should_apply_defaults() { + let config: RabbitMQSinkConfig = serde_json::from_str("{}").unwrap(); + let sink = RabbitMQSink::new(1, config); + assert_eq!( + sink.amqp_url.expose_secret(), + "amqp://guest:guest@localhost:5672?connection_timeout=30000" + ); + assert_eq!(sink.exchange, "iggy_events"); + assert_eq!(sink.exchange_type, "topic"); + assert_eq!(sink.routing_key, "iggy.messages"); + assert!(sink.include_metadata); + assert!(sink.durable_exchange); + assert_eq!(sink.delivery_mode, 2); + assert_eq!(sink.max_retries, 3); + assert_eq!(sink.retry_delay, Duration::from_secs(1)); + assert_eq!(sink.max_retry_delay, Duration::from_secs(5)); + assert_eq!(sink.timeout, Duration::from_secs(30)); + } + + #[test] + fn given_unknown_delivery_mode_when_new_should_default_to_persistent() { + let mut config = test_config(); + config.delivery_mode = Some("fancy".into()); + let sink = test_sink(config); + assert_eq!(sink.delivery_mode, 2); + } +} diff --git a/core/integration/Cargo.toml b/core/integration/Cargo.toml index 0450fa306d..c4d5008746 100644 --- a/core/integration/Cargo.toml +++ b/core/integration/Cargo.toml @@ -71,6 +71,7 @@ iggy_connector_sdk = { workspace = true, features = ["api"] } journal = { workspace = true } jsonwebtoken = { workspace = true } keyring-core = { workspace = true } +lapin = { workspace = true } lazy_static = { workspace = true } libc = { workspace = true } mongodb = { workspace = true } diff --git a/core/integration/tests/connectors/fixtures/mod.rs b/core/integration/tests/connectors/fixtures/mod.rs index e9d7a1332e..af9eb52990 100644 --- a/core/integration/tests/connectors/fixtures/mod.rs +++ b/core/integration/tests/connectors/fixtures/mod.rs @@ -28,6 +28,7 @@ mod meilisearch; mod mongodb; mod postgres; mod quickwit; +mod rabbitmq; mod redshift; mod s3; mod surrealdb; @@ -83,6 +84,11 @@ pub use postgres::{ PostgresSourceOps, }; pub use quickwit::{QuickwitFixture, QuickwitOps, QuickwitPreCreatedFixture}; +pub use rabbitmq::{ + RabbitMqOps, RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture, + RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture, + RabbitMqSinkWithoutMetadataFixture, +}; pub use redshift::{ RedshiftSinkFixture, RedshiftSinkJsonFixture, RedshiftSinkNoArchiveFixture, RedshiftSinkVarbyteFixture, diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/container.rs b/core/integration/tests/connectors/fixtures/rabbitmq/container.rs new file mode 100644 index 0000000000..3864604490 --- /dev/null +++ b/core/integration/tests/connectors/fixtures/rabbitmq/container.rs @@ -0,0 +1,327 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use crate::connectors::fixtures; +use futures::StreamExt; +use integration::harness::TestBinaryError; +use lapin::{ + Connection, ConnectionProperties, ExchangeKind, + options::{BasicConsumeOptions, ExchangeDeclareOptions, QueueBindOptions, QueueDeclareOptions}, + types::{AMQPValue, FieldTable}, +}; +use std::time::Duration; +use testcontainers_modules::testcontainers::core::{IntoContainerPort, WaitFor}; +use testcontainers_modules::testcontainers::runners::AsyncRunner; +use testcontainers_modules::testcontainers::{ContainerAsync, GenericImage, ImageExt}; +use tokio::time::sleep; +use tracing::info; +use uuid::Uuid; + +const RABBITMQ_IMAGE: &str = "docker.io/rabbitmq"; +const RABBITMQ_TAG: &str = "4.0-management"; +const RABBITMQ_PORT: u16 = 5672; +const RABBITMQ_READY_MSG: &str = "Time to start RabbitMQ:"; +const RABBITMQ_BOOT_ATTEMPTS: usize = 60; +const RABBITMQ_BOOT_INTERVAL_MS: u64 = 1000; + +pub(super) const DEFAULT_TEST_STREAM: &str = "test_stream"; +pub(super) const DEFAULT_TEST_TOPIC: &str = "test_topic"; +pub(super) const DEFAULT_EXCHANGE: &str = "iggy_events"; +pub(super) const DEFAULT_EXCHANGE_TYPE: &str = "topic"; +pub(super) const DEFAULT_ROUTING_KEY: &str = "iggy.messages"; +pub(super) const DEFAULT_CONSUMER_GROUP: &str = "rabbitmq_sink_test_cg"; + +pub(super) const ENV_SINK_AMQP_URL: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_AMQP_URL"; +pub(super) const ENV_SINK_EXCHANGE: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_EXCHANGE"; +pub(super) const ENV_SINK_EXCHANGE_TYPE: &str = + "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_EXCHANGE_TYPE"; +pub(super) const ENV_SINK_ROUTING_KEY: &str = + "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_ROUTING_KEY"; +pub(super) const ENV_SINK_STREAMS_0_STREAM: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_STREAM"; +pub(super) const ENV_SINK_STREAMS_0_TOPICS: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_TOPICS"; +pub(super) const ENV_SINK_STREAMS_0_SCHEMA: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_SCHEMA"; +pub(super) const ENV_SINK_STREAMS_0_CONSUMER_GROUP: &str = + "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_CONSUMER_GROUP"; +pub(super) const ENV_SINK_PATH: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PATH"; +pub(super) const ENV_SINK_INCLUDE_METADATA: &str = + "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_INCLUDE_METADATA"; + +#[derive(PartialEq)] +pub(super) enum RabbitMqExchangeSetup { + Topic, + Fanout, + Direct, + Headers, +} +pub struct RabbitMqContainer { + #[allow(dead_code)] + container: ContainerAsync, + pub(super) amqp_url: String, + pub(super) queue_names: Vec, + pub(super) exchange_setup: RabbitMqExchangeSetup, +} + +impl RabbitMqContainer { + async fn start_container() -> Result<(ContainerAsync, String), TestBinaryError> { + let container = GenericImage::new(RABBITMQ_IMAGE, RABBITMQ_TAG) + .with_exposed_port(RABBITMQ_PORT.tcp()) + .with_wait_for(WaitFor::message_on_stdout(RABBITMQ_READY_MSG)) + .with_mapped_port(0, RABBITMQ_PORT.tcp()) + .with_container_name(fixtures::unique_container_name("rabbitmq")) + .start() + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to start container: {e}"), + })?; + + let mapped_port = container + .ports() + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to get ports: {e}"), + })? + .map_to_host_port_ipv4(RABBITMQ_PORT) + .ok_or_else(|| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: "No mapping for RabbitMQ port".to_string(), + })?; + let amqp_url = format!("amqp://guest:guest@127.0.0.1:{mapped_port}"); + Ok((container, amqp_url)) + } + + async fn start_with( + exchange_setup: RabbitMqExchangeSetup, + queue_count: usize, + ) -> Result { + let (container, amqp_url) = Self::start_container().await?; + let queue_names = (0..queue_count) + .map(|index| format!("test_queue_{}_{}", Uuid::new_v4().simple(), index)) + .collect(); + + let instance = Self { + container, + amqp_url, + exchange_setup, + queue_names, + }; + instance.wait_until_ready().await?; + + info!("RabbitMQ container available at {}", instance.amqp_url); + Ok(instance) + } + + pub(super) async fn start() -> Result { + Self::start_with(RabbitMqExchangeSetup::Topic, 1).await + } + + pub(super) async fn start_fanout() -> Result { + Self::start_with(RabbitMqExchangeSetup::Fanout, 2).await + } + + pub(super) async fn start_direct() -> Result { + Self::start_with(RabbitMqExchangeSetup::Direct, 1).await + } + + pub(super) async fn start_headers() -> Result { + Self::start_with(RabbitMqExchangeSetup::Headers, 1).await + } + + async fn wait_until_ready(&self) -> Result<(), TestBinaryError> { + let mut last_error = None; + + for _ in 0..RABBITMQ_BOOT_ATTEMPTS { + match Connection::connect(&self.amqp_url, ConnectionProperties::default()).await { + Ok(_) => { + return self.setup_exchange_and_queue().await; + } + Err(error) => last_error = Some(error.to_string()), + } + sleep(Duration::from_millis(RABBITMQ_BOOT_INTERVAL_MS)).await; + } + + let detail = last_error + .map(|error| format!(" Last error: {error}")) + .unwrap_or_default(); + Err(TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("RabbitMQ did not become ready.{detail}"), + }) + } + + async fn setup_exchange_and_queue(&self) -> Result<(), TestBinaryError> { + let conn = Connection::connect(&self.amqp_url, ConnectionProperties::default()) + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to create connection for consume: {e}"), + })?; + let channel = conn + .create_channel() + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to create channel for consume: {e}"), + })?; + + let exchange_kind = match self.exchange_setup { + RabbitMqExchangeSetup::Topic => ExchangeKind::Topic, + RabbitMqExchangeSetup::Fanout => ExchangeKind::Fanout, + RabbitMqExchangeSetup::Direct => ExchangeKind::Direct, + RabbitMqExchangeSetup::Headers => ExchangeKind::Headers, + }; + channel + .exchange_declare( + DEFAULT_EXCHANGE, + exchange_kind, + ExchangeDeclareOptions { + durable: true, + ..Default::default() + }, + FieldTable::default(), + ) + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to declare exchange for consume: {e}"), + })?; + + for queue_name in &self.queue_names { + channel + .queue_declare( + queue_name, + QueueDeclareOptions { + auto_delete: true, + ..Default::default() + }, + FieldTable::default(), + ) + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to create queue for consume: {e}"), + })?; + + let mut bind_arguments = FieldTable::default(); + if self.exchange_setup == RabbitMqExchangeSetup::Headers { + bind_arguments.insert("x-match".into(), AMQPValue::LongString("all".into())); + bind_arguments.insert("x-user".into(), AMQPValue::LongString("alice".into())); + } + channel + .queue_bind( + queue_name, + DEFAULT_EXCHANGE, + DEFAULT_ROUTING_KEY, + QueueBindOptions::default(), + bind_arguments, + ) + .await + .map_err(|e| TestBinaryError::FixtureSetup { + fixture_type: "RabbitMqContainer".to_string(), + message: format!("Failed to bind queue to exchange for consume: {e}"), + })?; + } + + Ok(()) + } +} + +pub struct ConsumedDelivery { + pub data: Vec, + pub headers: lapin::types::FieldTable, +} + +pub trait RabbitMqOps: Sync { + fn container(&self) -> &RabbitMqContainer; + + fn queue_names(&self) -> &[String] { + &self.container().queue_names + } + + async fn consume_messages( + &self, + count: usize, + ) -> Result, TestBinaryError> { + self.consume_messages_from(&self.container().queue_names[0], count) + .await + } + + async fn consume_messages_from( + &self, + queue_name: &str, + count: usize, + ) -> Result, TestBinaryError> { + self.consume_messages_from_with_timeout(queue_name, count, Duration::from_secs(60)) + .await + } + + async fn consume_messages_from_with_timeout( + &self, + queue_name: &str, + count: usize, + timeout: Duration, + ) -> Result, TestBinaryError> { + let conn = Connection::connect(&self.container().amqp_url, ConnectionProperties::default()) + .await + .map_err(|e| TestBinaryError::InvalidState { + message: format!("Failed to connect to RabbitMQ for consume: {e}"), + })?; + let channel = conn + .create_channel() + .await + .map_err(|e| TestBinaryError::InvalidState { + message: format!("Failed to create channel for consume: {e}"), + })?; + + let mut consumer = channel + .basic_consume( + queue_name, + "", + BasicConsumeOptions::default(), + FieldTable::default(), + ) + .await + .map_err(|e| TestBinaryError::InvalidState { + message: format!("Failed to start consumer: {e}"), + })?; + + let mut messages = Vec::with_capacity(count); + let deadline = tokio::time::Instant::now() + timeout; + while messages.len() < count && tokio::time::Instant::now() < deadline { + match tokio::time::timeout(Duration::from_secs(1), consumer.next()).await { + Ok(Some(delivery)) => { + let delivery = delivery.map_err(|e| TestBinaryError::InvalidState { + message: format!("Consumer error: {e}"), + })?; + let data = delivery.data.clone(); + let headers = delivery.properties.headers().clone().unwrap_or_default(); + delivery.ack(Default::default()).await.map_err(|e| { + TestBinaryError::InvalidState { + message: format!("Failed to ack message: {e}"), + } + })?; + messages.push(ConsumedDelivery { data, headers }); + } + Ok(None) => break, + Err(_) => continue, + } + } + + Ok(messages) + } +} diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs b/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs new file mode 100644 index 0000000000..a8154b4e15 --- /dev/null +++ b/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs @@ -0,0 +1,26 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +mod container; +mod sink; + +pub use container::RabbitMqOps; +pub use sink::{ + RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture, + RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture, + RabbitMqSinkWithoutMetadataFixture, +}; diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs b/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs new file mode 100644 index 0000000000..8301dacdc1 --- /dev/null +++ b/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs @@ -0,0 +1,273 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use super::container::{ + DEFAULT_CONSUMER_GROUP, DEFAULT_EXCHANGE, DEFAULT_EXCHANGE_TYPE, DEFAULT_ROUTING_KEY, + DEFAULT_TEST_STREAM, DEFAULT_TEST_TOPIC, ENV_SINK_AMQP_URL, ENV_SINK_EXCHANGE, + ENV_SINK_EXCHANGE_TYPE, ENV_SINK_INCLUDE_METADATA, ENV_SINK_PATH, ENV_SINK_ROUTING_KEY, + ENV_SINK_STREAMS_0_CONSUMER_GROUP, ENV_SINK_STREAMS_0_SCHEMA, ENV_SINK_STREAMS_0_STREAM, + ENV_SINK_STREAMS_0_TOPICS, RabbitMqContainer, RabbitMqOps, +}; +use async_trait::async_trait; +use iggy_connector_sdk::Schema; +use integration::harness::{TestBinaryError, TestFixture}; +use std::collections::HashMap; + +pub struct RabbitMqSinkFixture { + container: RabbitMqContainer, + include_metadata: bool, + schema: Schema, +} + +impl RabbitMqOps for RabbitMqSinkFixture { + fn container(&self) -> &RabbitMqContainer { + &self.container + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start().await?; + Ok(Self { + container, + include_metadata: true, + schema: Schema::Json, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + let mut envs = HashMap::new(); + envs.insert( + ENV_SINK_AMQP_URL.to_string(), + self.container.amqp_url.clone(), + ); + envs.insert(ENV_SINK_EXCHANGE.to_string(), DEFAULT_EXCHANGE.into()); + envs.insert( + ENV_SINK_EXCHANGE_TYPE.to_string(), + DEFAULT_EXCHANGE_TYPE.into(), + ); + envs.insert(ENV_SINK_ROUTING_KEY.to_string(), DEFAULT_ROUTING_KEY.into()); + envs.insert( + ENV_SINK_STREAMS_0_STREAM.to_string(), + DEFAULT_TEST_STREAM.into(), + ); + envs.insert( + ENV_SINK_STREAMS_0_TOPICS.to_string(), + format!("[{}]", DEFAULT_TEST_TOPIC), + ); + envs.insert( + ENV_SINK_STREAMS_0_SCHEMA.to_string(), + self.schema.to_string(), + ); + envs.insert( + ENV_SINK_STREAMS_0_CONSUMER_GROUP.to_string(), + DEFAULT_CONSUMER_GROUP.into(), + ); + envs.insert( + ENV_SINK_PATH.to_string(), + "../../target/debug/libiggy_connector_rabbitmq_sink".into(), + ); + envs.insert( + ENV_SINK_INCLUDE_METADATA.to_string(), + self.include_metadata.to_string(), + ); + envs + } +} + +pub struct RabbitMqSinkWithoutMetadataFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkWithoutMetadataFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkWithoutMetadataFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: false, + schema: Schema::Json, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + self.inner.connectors_runtime_envs() + } +} + +pub struct RabbitMqSinkRawSchemaFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkRawSchemaFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkRawSchemaFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: true, + schema: Schema::Raw, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + self.inner.connectors_runtime_envs() + } +} + +pub struct RabbitMqSinkFanoutFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkFanoutFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkFanoutFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start_fanout().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: true, + schema: Schema::Json, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + let mut envs = self.inner.connectors_runtime_envs(); + envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "fanout".into()); + envs + } +} + +pub struct RabbitMqSinkDirectFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkDirectFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkDirectFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start_direct().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: true, + schema: Schema::Json, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + let mut envs = self.inner.connectors_runtime_envs(); + envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "direct".into()); + envs + } +} + +pub struct RabbitMqSinkHeadersFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkHeadersFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkHeadersFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start_headers().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: true, + schema: Schema::Json, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + let mut envs = self.inner.connectors_runtime_envs(); + envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "headers".into()); + envs + } +} + +pub struct RabbitMqSinkUnroutableFixture { + inner: RabbitMqSinkFixture, +} + +impl std::ops::Deref for RabbitMqSinkUnroutableFixture { + type Target = RabbitMqSinkFixture; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[async_trait] +impl TestFixture for RabbitMqSinkUnroutableFixture { + async fn setup() -> Result { + let container = RabbitMqContainer::start().await?; + Ok(Self { + inner: RabbitMqSinkFixture { + container, + include_metadata: true, + schema: Schema::Json, + }, + }) + } + + fn connectors_runtime_envs(&self) -> HashMap { + let mut envs = self.inner.connectors_runtime_envs(); + envs.insert(ENV_SINK_ROUTING_KEY.to_string(), "unroutable.key".into()); + envs + } +} diff --git a/core/integration/tests/connectors/mod.rs b/core/integration/tests/connectors/mod.rs index f6346bcc20..54dd1437b9 100644 --- a/core/integration/tests/connectors/mod.rs +++ b/core/integration/tests/connectors/mod.rs @@ -29,6 +29,7 @@ mod meilisearch; mod mongodb; mod postgres; mod quickwit; +mod rabbitmq; mod random; mod random_source_liveness; mod redshift; diff --git a/core/integration/tests/connectors/rabbitmq/mod.rs b/core/integration/tests/connectors/rabbitmq/mod.rs new file mode 100644 index 0000000000..c4a30f2755 --- /dev/null +++ b/core/integration/tests/connectors/rabbitmq/mod.rs @@ -0,0 +1,18 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +mod rabbitmq_sink; diff --git a/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs b/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs new file mode 100644 index 0000000000..f9c2376fb1 --- /dev/null +++ b/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs @@ -0,0 +1,429 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use crate::connectors::fixtures::{ + RabbitMqOps, RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture, + RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture, + RabbitMqSinkWithoutMetadataFixture, +}; +use bytes::Bytes; +use iggy::prelude::{HeaderKey, HeaderValue, IggyMessage, Partitioning}; +use iggy_common::Identifier; +use iggy_common::MessageClient; +use integration::harness::seeds; +use integration::iggy_harness; +use lapin::types::{AMQPValue, ShortString}; +use std::collections::BTreeMap; +use std::str::FromStr; +use std::time::Duration; + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] + +async fn json_messages_are_published_to_rabbitmq_exchange( + harness: &TestHarness, + fixture: RabbitMqSinkFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payloads = [ + serde_json::json!({"name": "Alice"}), + serde_json::json!({"name": "Bob"}), + serde_json::json!({"name": "Carol"}), + ]; + let mut messages: Vec = payloads + .iter() + .enumerate() + .map(|(idx, payload)| { + IggyMessage::builder() + .id((idx + 1) as u128) + .payload(Bytes::from(serde_json::to_vec(payload).unwrap())) + .build() + .unwrap() + }) + .collect(); + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(3).await.unwrap(); + assert_eq!(delivered.len(), 3); + for (idx, delivery) in delivered.iter().enumerate() { + let value: serde_json::Value = serde_json::from_slice(&delivery.data).unwrap(); + assert_eq!(value, payloads[idx]); + assert_eq!( + header_str(&delivery.headers, "iggy_stream").as_deref(), + Some("test_stream") + ); + assert_eq!( + header_str(&delivery.headers, "iggy_topic").as_deref(), + Some("test_topic") + ); + } +} + +fn header_str(headers: &lapin::types::FieldTable, key: &str) -> Option { + headers + .inner() + .get(&ShortString::from(key)) + .and_then(|v| match v { + AMQPValue::LongString(s) => Some(s.to_string()), + _ => None, + }) +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] + +async fn given_direct_exchange_when_published_should_deliver_to_bound_queue( + harness: &TestHarness, + fixture: RabbitMqSinkDirectFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payloads = [ + serde_json::json!({"name": "Alice"}), + serde_json::json!({"name": "Bob"}), + serde_json::json!({"name": "Carol"}), + ]; + let mut messages: Vec = payloads + .iter() + .enumerate() + .map(|(idx, payload)| { + IggyMessage::builder() + .id((idx + 1) as u128) + .payload(Bytes::from(serde_json::to_vec(payload).unwrap())) + .build() + .unwrap() + }) + .collect(); + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(3).await.unwrap(); + assert_eq!(delivered.len(), 3); + for (idx, delivery) in delivered.iter().enumerate() { + let value: serde_json::Value = serde_json::from_slice(&delivery.data).unwrap(); + assert_eq!(value, payloads[idx]); + assert_eq!( + header_str(&delivery.headers, "iggy_stream").as_deref(), + Some("test_stream") + ); + assert_eq!( + header_str(&delivery.headers, "iggy_topic").as_deref(), + Some("test_topic") + ); + } +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_include_metadata_false_when_published_should_not_include_iggy_headers( + harness: &TestHarness, + fixture: RabbitMqSinkWithoutMetadataFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payload = serde_json::json!({"name": "Alice"}); + let mut messages = vec![ + IggyMessage::builder() + .id(1) + .payload(Bytes::from(serde_json::to_vec(&payload).unwrap())) + .build() + .unwrap(), + ]; + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(1).await.unwrap(); + assert_eq!(delivered.len(), 1); + let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap(); + assert_eq!(value, payload); + assert!(delivered[0].headers.inner().is_empty()); +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_raw_schema_when_published_should_preserve_raw_payload_bytes( + harness: &TestHarness, + fixture: RabbitMqSinkRawSchemaFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let raw_payloads: Vec> = vec![ + b"plain text message".to_vec(), + vec![0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD], + vec![0xDE, 0xAD, 0xBE, 0xEF], + ]; + + let mut messages: Vec = raw_payloads + .iter() + .enumerate() + .map(|(idx, payload)| { + IggyMessage::builder() + .id((idx + 1) as u128) + .payload(Bytes::from(payload.clone())) + .build() + .unwrap() + }) + .collect(); + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(3).await.unwrap(); + assert_eq!(delivered.len(), 3); + for (idx, delivery) in delivered.iter().enumerate() { + assert_eq!(delivery.data, raw_payloads[idx]); + assert_eq!( + header_str(&delivery.headers, "iggy_stream").as_deref(), + Some("test_stream") + ); + assert_eq!( + header_str(&delivery.headers, "iggy_topic").as_deref(), + Some("test_topic") + ); + } +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_fanout_exchange_when_published_should_deliver_to_all_bound_queues( + harness: &TestHarness, + fixture: RabbitMqSinkFanoutFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payload = serde_json::json!({"name": "Alice"}); + let mut messages = vec![ + IggyMessage::builder() + .id(1) + .payload(Bytes::from(serde_json::to_vec(&payload).unwrap())) + .build() + .unwrap(), + ]; + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + assert_eq!( + fixture.queue_names().len(), + 2, + "fanout fixture should bind two queues" + ); + for queue_name in fixture.queue_names() { + let delivered = fixture.consume_messages_from(queue_name, 1).await.unwrap(); + assert_eq!( + delivered.len(), + 1, + "fanout exchange must deliver to every bound queue" + ); + let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap(); + assert_eq!(value, payload); + assert_eq!( + header_str(&delivered[0].headers, "iggy_stream").as_deref(), + Some("test_stream") + ); + assert_eq!( + header_str(&delivered[0].headers, "iggy_topic").as_deref(), + Some("test_topic") + ); + } +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_predeclared_durable_exchange_when_published_should_deliver( + harness: &TestHarness, + fixture: RabbitMqSinkFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payload = serde_json::json!({"name": "Alice"}); + let mut messages = vec![ + IggyMessage::builder() + .id(1) + .payload(Bytes::from(serde_json::to_vec(&payload).unwrap())) + .build() + .unwrap(), + ]; + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(1).await.unwrap(); + assert_eq!(delivered.len(), 1); + let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap(); + assert_eq!(value, payload); +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_unroutable_routing_key_when_published_should_not_deliver( + harness: &TestHarness, + fixture: RabbitMqSinkUnroutableFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let payload = serde_json::json!({"name": "Alice"}); + let mut messages = vec![ + IggyMessage::builder() + .id(1) + .payload(Bytes::from(serde_json::to_vec(&payload).unwrap())) + .build() + .unwrap(), + ]; + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + tokio::time::sleep(Duration::from_secs(5)).await; + let delivered = fixture + .consume_messages_from_with_timeout(&fixture.queue_names()[0], 1, Duration::from_secs(5)) + .await + .unwrap(); + assert!( + delivered.is_empty(), + "unroutable mandatory publish must not reach any queue" + ); +} + +#[iggy_harness( + server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")), + seed = seeds::connector_stream +)] +async fn given_user_header_when_published_through_headers_exchange_should_route( + harness: &TestHarness, + fixture: RabbitMqSinkHeadersFixture, +) { + let client = harness.root_client().await.unwrap(); + let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap(); + let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap(); + + let user_headers = BTreeMap::from([( + HeaderKey::from_str("x-user").unwrap(), + HeaderValue::from_str("alice").unwrap(), + )]); + let payload = serde_json::json!({"name": "Alice"}); + let mut messages = vec![ + IggyMessage::builder() + .id(1) + .payload(Bytes::from(serde_json::to_vec(&payload).unwrap())) + .user_headers(user_headers) + .build() + .unwrap(), + ]; + + client + .send_messages( + &stream_id, + &topic_id, + &Partitioning::partition_id(0), + &mut messages, + ) + .await + .unwrap(); + + let delivered = fixture.consume_messages(1).await.unwrap(); + assert_eq!(delivered.len(), 1); + let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap(); + assert_eq!(value, payload); + assert_eq!( + header_str(&delivered[0].headers, "x-user").as_deref(), + Some("alice"), + "user header must survive to AMQP headers for headers-exchange routing" + ); +} diff --git a/core/integration/tests/connectors/rabbitmq/sink.toml b/core/integration/tests/connectors/rabbitmq/sink.toml new file mode 100644 index 0000000000..e425ed503b --- /dev/null +++ b/core/integration/tests/connectors/rabbitmq/sink.toml @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[connectors] +config_type = "local" +config_dir = "../connectors/sinks/rabbitmq_sink" diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index 88413af9d2..82d278eb62 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -87,7 +87,7 @@ EOF } RUST_COMPONENTS="rust-sdk rust-common rust-binary-protocol rust-server rust-cli rust-connector-sdk rust-mcp rust-bench rust-bench-dashboard-frontend rust-bench-dashboard-server rust-bench-report" -CONNECTOR_SINK_COMPONENTS="rust-connector-delta-sink rust-connector-elasticsearch-sink rust-connector-http-sink rust-connector-iceberg-sink rust-connector-influxdb-sink rust-connector-mongodb-sink rust-connector-postgres-sink rust-connector-quickwit-sink rust-connector-stdout-sink rust-connector-surrealdb-sink" +CONNECTOR_SINK_COMPONENTS="rust-connector-delta-sink rust-connector-elasticsearch-sink rust-connector-http-sink rust-connector-iceberg-sink rust-connector-influxdb-sink rust-connector-mongodb-sink rust-connector-postgres-sink rust-connector-quickwit-sink rust-connector-stdout-sink rust-connector-surrealdb-sink rust-connector-rabbitmq-sink" CONNECTOR_SOURCE_COMPONENTS="rust-connector-elasticsearch-source rust-connector-influxdb-source rust-connector-postgres-source rust-connector-random-source" CONNECTOR_COMPONENTS="rust-connector-runtime ${CONNECTOR_SINK_COMPONENTS} ${CONNECTOR_SOURCE_COMPONENTS}" SDK_COMPONENTS="sdk-python sdk-node sdk-go sdk-csharp sdk-java"