From 1ef9ec59e4b269b16631cb4d2d9af7395e27b136 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Tue, 8 Aug 2023 11:10:32 +1200 Subject: [PATCH] Big refactor (#86) * wip * check * telemetry * update * ignore vendor for fmt * methods * upstream * middlewares * subscriptions * methods server * working? * fix * fix extension build * fix * works * tests passing * clippy * fix * fix * update * update eth_config * fix --- .rustfmt.toml | 4 + Cargo.lock | 1180 ++++++++--------- Cargo.toml | 2 +- benches/{ => bench}/helpers.rs | 0 benches/{bench.rs => bench/main.rs} | 77 +- config.yml | 47 +- eth_config.yml | 32 +- rpc_configs/ethereum.yml | 32 +- rpc_configs/substrate.yml | 47 +- src/{config.rs => config/mod.rs} | 166 +-- src/config/rpc.rs | 63 + src/extension/mod.rs | 64 + src/{ => extensions}/api/eth.rs | 54 +- src/{ => extensions}/api/mod.rs | 6 - src/{ => extensions}/api/substrate.rs | 54 +- src/{ => extensions}/api/tests.rs | 13 +- src/{ => extensions}/api/value_handle.rs | 2 +- src/extensions/cache.rs | 34 + src/{ => extensions}/client/mock.rs | 0 src/{ => extensions}/client/mod.rs | 47 +- src/{ => extensions}/client/tests.rs | 13 +- src/extensions/event_bus.rs | 21 + src/extensions/merge_subscription.rs | 32 + src/extensions/mod.rs | 92 ++ src/extensions/server.rs | 72 + src/{ => extensions}/telemetry.rs | 53 +- src/integration_tests/merge_subscription.rs | 55 +- src/integration_tests/mod.rs | 1 - src/lib.rs | 9 +- src/{bin.rs => main.rs} | 13 +- src/middleware/methods/call.rs | 52 - src/middleware/methods/response.rs | 25 - src/middleware/mod.rs | 55 +- .../methods/block_tag.rs | 79 +- .../methods/cache.rs | 131 +- .../methods/inject_params.rs | 91 +- .../methods/mod.rs | 2 +- src/middlewares/methods/response.rs | 43 + src/middlewares/methods/upstream.rs | 48 + src/middlewares/mod.rs | 74 ++ .../subscriptions/merge_subscription.rs | 46 +- .../subscriptions/mod.rs | 2 +- .../subscriptions/upstream.rs} | 45 +- src/server.rs | 381 +++--- src/{ => utils}/cache.rs | 0 src/{helpers.rs => utils/mod.rs} | 6 + src/utils/type_registry.rs | 74 ++ 47 files changed, 2116 insertions(+), 1323 deletions(-) rename benches/{ => bench}/helpers.rs (100%) rename benches/{bench.rs => bench/main.rs} (92%) rename src/{config.rs => config/mod.rs} (61%) create mode 100644 src/config/rpc.rs create mode 100644 src/extension/mod.rs rename src/{ => extensions}/api/eth.rs (82%) rename src/{ => extensions}/api/mod.rs (91%) rename src/{ => extensions}/api/substrate.rs (81%) rename src/{ => extensions}/api/tests.rs (95%) rename src/{ => extensions}/api/value_handle.rs (98%) create mode 100644 src/extensions/cache.rs rename src/{ => extensions}/client/mock.rs (100%) rename src/{ => extensions}/client/mod.rs (92%) rename src/{ => extensions}/client/tests.rs (93%) create mode 100644 src/extensions/event_bus.rs create mode 100644 src/extensions/merge_subscription.rs create mode 100644 src/extensions/mod.rs create mode 100644 src/extensions/server.rs rename src/{ => extensions}/telemetry.rs (57%) rename src/{bin.rs => main.rs} (50%) delete mode 100644 src/middleware/methods/call.rs delete mode 100644 src/middleware/methods/response.rs rename src/{middleware => middlewares}/methods/block_tag.rs (81%) rename src/{middleware => middlewares}/methods/cache.rs (54%) rename src/{middleware => middlewares}/methods/inject_params.rs (87%) rename src/{middleware => middlewares}/methods/mod.rs (80%) create mode 100644 src/middlewares/methods/response.rs create mode 100644 src/middlewares/methods/upstream.rs create mode 100644 src/middlewares/mod.rs rename src/{middleware => middlewares}/subscriptions/merge_subscription.rs (89%) rename src/{middleware => middlewares}/subscriptions/mod.rs (56%) rename src/{middleware/subscriptions/subscription.rs => middlewares/subscriptions/upstream.rs} (57%) rename src/{ => utils}/cache.rs (100%) rename src/{helpers.rs => utils/mod.rs} (95%) create mode 100644 src/utils/type_registry.rs diff --git a/.rustfmt.toml b/.rustfmt.toml index 44148a2..f8aacc1 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1,5 @@ reorder_imports = true + +ignore = [ + "vendor/*", +] \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e4c13ca..001e9e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -24,16 +24,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.8", + "getrandom 0.2.10", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -53,6 +53,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -68,23 +74,72 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.3.15" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +checksum = "62b74f44609f0f91493e3082d3734d98497e094777144380ea4db9f9905dd5b6" dependencies = [ "brotli", "flate2", @@ -98,22 +153,22 @@ dependencies = [ [[package]] name = "async-io" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock", "autocfg", + "cfg-if 1.0.0", "concurrent-queue", "futures-lite", - "libc", "log", "parking", "polling", + "rustix 0.37.23", "slab", "socket2", "waker-fn", - "windows-sys 0.42.0", ] [[package]] @@ -125,37 +180,15 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-stream" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "async-trait" -version = "0.1.66" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] @@ -177,13 +210,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.11" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d8068b6ccb8b34db9de397c7043f91db8b4c66414952c6db944f238c4d3db3" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes 1.4.0", "futures-util", "http", @@ -205,9 +238,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", "bytes 1.4.0", @@ -222,9 +255,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -243,15 +276,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" - -[[package]] -name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "beef" @@ -268,13 +295,19 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -295,7 +328,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -304,7 +337,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -339,9 +372,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "serde", @@ -349,9 +382,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byte-tools" @@ -395,18 +428,18 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -432,11 +465,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -453,13 +487,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time", "wasm-bindgen", @@ -468,9 +502,9 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", @@ -479,15 +513,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" [[package]] name = "ciborium-ll" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" dependencies = [ "ciborium-io", "half", @@ -495,42 +529,49 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ - "bitflags", + "bitflags 1.3.2", "clap_lex 0.2.4", - "indexmap", + "indexmap 1.9.3", "textwrap", ] [[package]] name = "clap" -version = "4.1.9" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9d6ada83c1edcce028902ea27dd929069c70df4c7600b131b4d9a1ad2879cc" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ - "bitflags", + "clap_builder", "clap_derive", - "clap_lex 0.3.3", - "is-terminal", "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.5.0", "strsim", - "termcolor", ] [[package]] name = "clap_derive" -version = "4.1.9" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] @@ -544,27 +585,30 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" -dependencies = [ - "os_str_bytes", -] +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "concurrent-queue" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" dependencies = [ "crossbeam-utils", ] [[package]] name = "console-api" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86" +checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e" dependencies = [ "prost", "prost-types", @@ -574,9 +618,9 @@ dependencies = [ [[package]] name = "console-subscriber" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be" +checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb" dependencies = [ "console-api", "crossbeam-channel", @@ -608,24 +652,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpp_demangle" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442" +checksum = "ee34052ee3d93d6d8f3e6f81d85c47921f6653a19a7b70e939e3e602d893a674" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -649,7 +693,7 @@ dependencies = [ "atty", "cast", "ciborium", - "clap 3.2.23", + "clap 3.2.25", "criterion-plot", "futures", "itertools", @@ -679,9 +723,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -700,9 +744,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -713,9 +757,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -726,21 +770,21 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", "typenum", ] [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" dependencies = [ "cfg-if 1.0.0", - "hashbrown", + "hashbrown 0.14.0", "lock_api", "once_cell", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -767,14 +811,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common", @@ -783,9 +827,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" @@ -813,18 +857,24 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.28", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" -version = "0.2.8" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "winapi 0.3.9", + "windows-sys", ] [[package]] @@ -867,6 +917,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "findshlibs" version = "0.10.2" @@ -881,9 +937,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "miniz_oxide", @@ -897,9 +953,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -910,7 +966,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fuchsia-zircon-sys", ] @@ -922,9 +978,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -937,9 +993,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -947,15 +1003,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -965,17 +1021,17 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-lite" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -986,26 +1042,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" @@ -1019,9 +1075,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1046,9 +1102,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1067,9 +1123,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1078,9 +1134,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glob" @@ -1090,9 +1146,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "aca8bbd8e0707c1887a8bbb7e6b40e228f251ff5d62c8220a4a7a53c73aff006" dependencies = [ "aho-corasick", "bstr", @@ -1135,9 +1191,9 @@ dependencies = [ [[package]] name = "gloo-utils" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" dependencies = [ "js-sys", "serde", @@ -1164,9 +1220,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.17" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes 1.4.0", "fnv", @@ -1174,10 +1230,10 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", - "tokio-util 0.7.7", + "tokio-util 0.7.8", "tracing", ] @@ -1193,6 +1249,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "hdrhistogram" version = "7.5.2" @@ -1223,18 +1285,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "http" @@ -1260,9 +1313,9 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" @@ -1284,9 +1337,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes 1.4.0", "futures-channel", @@ -1308,10 +1361,11 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", "log", @@ -1335,9 +1389,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1358,9 +1412,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1368,12 +1422,22 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", ] [[package]] @@ -1383,7 +1447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fb7c1b80a1dfa604bb4a649a5c5aeef3d913f7c520cb42b40e534e8a61bcdfc" dependencies = [ "ahash", - "indexmap", + "indexmap 1.9.3", "is-terminal", "itoa", "log", @@ -1411,13 +1475,13 @@ checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" [[package]] name = "io-lifetimes" -version = "1.0.7" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e86b86ae312accbf05ade23ce76b625e0e47a255712b7414037385a1c05380" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.2", "libc", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1431,9 +1495,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "iri-string" @@ -1447,14 +1511,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.45.0", + "hermit-abi 0.3.2", + "rustix 0.38.6", + "windows-sys", ] [[package]] @@ -1468,9 +1531,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -1483,9 +1546,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1599,7 +1662,7 @@ dependencies = [ "thiserror", "tokio", "tokio-rustls", - "tokio-util 0.7.7", + "tokio-util 0.7.8", "tracing", "webpki-roots", ] @@ -1671,7 +1734,7 @@ dependencies = [ "soketto", "tokio", "tokio-stream", - "tokio-util 0.7.7", + "tokio-util 0.7.8", "tower", "tracing", ] @@ -1731,21 +1794,27 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1753,12 +1822,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "mach" @@ -1784,14 +1850,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" [[package]] name = "memchr" @@ -1810,18 +1876,18 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" @@ -1841,9 +1907,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1869,14 +1935,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1905,9 +1970,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934030d03f6191edbb4ba16835ccdb80d560788ac686570a8e2986a0fb59ded8" +checksum = "206bf83f415b0579fd885fe0804eb828e727636657dc1bf73d80d2f1218e14a1" dependencies = [ "async-io", "async-lock", @@ -1915,10 +1980,9 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "futures-util", - "num_cpus", "once_cell", "parking_lot 0.12.1", - "quanta 0.11.0", + "quanta 0.11.1", "rustc_version", "scheduled-thread-pool", "skeptic", @@ -1931,9 +1995,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.38" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ "cfg-if 0.1.10", "libc", @@ -1946,7 +2010,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", "static_assertions", @@ -1994,49 +2058,39 @@ dependencies = [ "itoa", ] -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] [[package]] name = "object" -version = "0.30.3" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "oorandom" @@ -2081,7 +2135,7 @@ dependencies = [ "async-trait", "futures-core", "http", - "indexmap", + "indexmap 1.9.3", "itertools", "once_cell", "opentelemetry", @@ -2140,7 +2194,7 @@ checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2" dependencies = [ "futures-channel", "futures-util", - "indexmap", + "indexmap 1.9.3", "once_cell", "pin-project-lite", "thiserror", @@ -2178,9 +2232,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.4.1" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "overload" @@ -2208,9 +2262,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" [[package]] name = "parking_lot" @@ -2230,7 +2284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -2242,61 +2296,61 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -2312,9 +2366,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -2325,33 +2379,33 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] [[package]] name = "polling" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1f879b2998099c2d69ab9605d145d5b661195627eccc680002c4918a7fb6fa" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "concurrent-queue", "libc", "log", "pin-project-lite", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -2392,44 +2446,20 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes 1.4.0", "prost-derive", @@ -2437,9 +2467,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", @@ -2450,20 +2480,20 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ "prost", ] [[package]] name = "pulldown-cmark" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ - "bitflags", + "bitflags 1.3.2", "memchr", "unicase", ] @@ -2486,9 +2516,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc73c42f9314c4bdce450c77e6f09ecbddefbeddb1b5979ded332a3913ded33" +checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" dependencies = [ "crossbeam-utils", "libc", @@ -2511,9 +2541,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -2577,7 +2607,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] @@ -2595,7 +2625,7 @@ version = "10.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2626,18 +2656,28 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.7.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-automata 0.3.4", + "regex-syntax 0.7.4", ] [[package]] @@ -2646,22 +2686,39 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", ] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "bytes 1.4.0", "encoding_rs", "futures-core", @@ -2715,9 +2772,9 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" dependencies = [ "byteorder", "num-traits", @@ -2726,9 +2783,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -2747,35 +2804,48 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.9" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", - "windows-sys 0.45.0", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee020b1716f0a80e2ace9b03441a749e402e86712f15f16fe8a8f75afac732f" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.5", + "windows-sys", ] [[package]] name = "rustls" -version = "0.21.1" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.2", "sct", ] [[package]] name = "rustls-native-certs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -2785,11 +2855,11 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", ] [[package]] @@ -2802,17 +2872,27 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.101.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -2825,11 +2905,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2843,9 +2923,9 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -2859,11 +2939,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.8.2" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2872,9 +2952,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2882,9 +2962,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" dependencies = [ "serde", ] @@ -2897,29 +2977,29 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.156" +version = "1.0.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -2940,11 +3020,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.19" +version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82e6c8c047aa50a7328632d067bcae6ef38772a79e28daf32f735e0e4f3dd10" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ - "indexmap", + "indexmap 2.0.0", "itoa", "ryu", "serde", @@ -3020,9 +3100,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -3082,9 +3162,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subway" @@ -3094,7 +3174,7 @@ dependencies = [ "async-trait", "blake2", "chrono", - "clap 4.1.9", + "clap 4.3.19", "console-subscriber", "criterion", "enumflags2", @@ -3160,9 +3240,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.12" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -3183,24 +3263,15 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.4.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ "cfg-if 1.0.0", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.42.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", + "fastrand 2.0.0", + "redox_syscall 0.3.5", + "rustix 0.38.6", + "windows-sys", ] [[package]] @@ -3211,22 +3282,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.39" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.39" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] @@ -3299,15 +3370,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.26.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes 1.4.0", "libc", - "memchr", - "mio 0.8.6", + "mio 0.8.8", "num_cpus", "parking_lot 0.12.1", "pin-project-lite", @@ -3315,7 +3386,7 @@ dependencies = [ "socket2", "tokio-macros", "tracing", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -3330,20 +3401,20 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "tokio-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", @@ -3351,9 +3422,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -3376,9 +3447,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes 1.4.0", "futures-core", @@ -3391,31 +3462,30 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.7" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc18466501acd8ac6a3f615dd29a3438f8ca6bb3b19537138b3106e575621274" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "toml_datetime", "winnow", ] [[package]] name = "tonic" -version = "0.8.3" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ - "async-stream", "async-trait", "axum", - "base64 0.13.1", + "base64 0.21.2", "bytes 1.4.0", "futures-core", "futures-util", @@ -3427,15 +3497,12 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "prost-derive", "tokio", "tokio-stream", - "tokio-util 0.7.7", "tower", "tower-layer", "tower-service", "tracing", - "tracing-futures", ] [[package]] @@ -3447,13 +3514,13 @@ dependencies = [ "futures-core", "futures-util", "hdrhistogram", - "indexmap", + "indexmap 1.9.3", "pin-project", "pin-project-lite", "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.7", + "tokio-util 0.7.8", "tower-layer", "tower-service", "tracing", @@ -3461,13 +3528,13 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1d42a9b3f3ec46ba828e8d376aec14592ea199f70a06a548587ecd1c4ab658" +checksum = "55ae70283aba8d2a8b411c695c437fe25b8b5e44e23e780662002fc72fb47a82" dependencies = [ "async-compression", - "base64 0.20.0", - "bitflags", + "base64 0.21.2", + "bitflags 2.3.3", "bytes 1.4.0", "futures-core", "futures-util", @@ -3481,7 +3548,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "tokio", - "tokio-util 0.7.7", + "tokio-util 0.7.8", "tower", "tower-layer", "tower-service", @@ -3516,35 +3583,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.1.3" @@ -3568,9 +3625,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -3589,9 +3646,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" +checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" [[package]] name = "try-lock" @@ -3616,15 +3673,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -3637,9 +3694,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2024452afd3874bf539695e04af6732ba06517424dbf958fdb16a01f3bef6c" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" [[package]] name = "untrusted" @@ -3649,9 +3706,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -3660,17 +3717,23 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] @@ -3703,11 +3766,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -3731,9 +3793,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3741,24 +3803,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3768,9 +3830,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3778,28 +3840,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -3807,11 +3869,11 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa54963694b65584e170cf5dc46aeb4dcaa5584e652ff5f3952e56d66aff0125" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" dependencies = [ - "rustls-webpki", + "rustls-webpki 0.100.1", ] [[package]] @@ -3863,141 +3925,69 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -4006,9 +3996,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.3.6" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d020b441f92996c80d94ae9166e8501e59c7bb56121189dc9eab3bd8216966" +checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807" dependencies = [ "memchr", ] @@ -4034,18 +4024,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "6.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" dependencies = [ "libc", "zstd-sys", diff --git a/Cargo.toml b/Cargo.toml index 36beda1..c7adcec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ path = "src/lib.rs" [[bin]] name = "subway" -path = "src/bin.rs" +path = "src/main.rs" [dependencies] anyhow = "1.0.68" diff --git a/benches/helpers.rs b/benches/bench/helpers.rs similarity index 100% rename from benches/helpers.rs rename to benches/bench/helpers.rs diff --git a/benches/bench.rs b/benches/bench/main.rs similarity index 92% rename from benches/bench.rs rename to benches/bench/main.rs index 45ff70f..60d15c3 100644 --- a/benches/bench.rs +++ b/benches/bench/main.rs @@ -3,19 +3,22 @@ use futures::{future::join_all, stream::FuturesUnordered}; use futures_util::FutureExt; use jsonrpsee::core::params::BatchRequestBuilder; use pprof::criterion::{Output, PProfProfiler}; -use std::sync::Arc; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; use tokio::runtime::Runtime as TokioRuntime; -use helpers::client::{ - rpc_params, ws_client, ws_handshake, ClientT, HeaderMap, SubscriptionClientT, +use helpers::{ + client::{rpc_params, ws_client, ws_handshake, ClientT, HeaderMap, SubscriptionClientT}, + ASYNC_INJECT_CALL, KIB, SUB_METHOD_NAME, UNSUB_METHOD_NAME, }; -use helpers::{ASYNC_INJECT_CALL, KIB, SUB_METHOD_NAME, UNSUB_METHOD_NAME}; -use subway::client::Client; -use subway::config::{ - Config, MergeStrategy, MethodParam, RpcDefinitions, RpcMethod, RpcSubscription, ServerConfig, + +use subway::{ + config::{ + Config, MergeStrategy, MethodParam, MiddlewaresConfig, RpcDefinitions, RpcMethod, + RpcSubscription, + }, + extensions::{client::ClientConfig, server::ServerConfig, ExtensionsConfig}, + server::start_server, }; -use subway::server::start_server; mod helpers; @@ -224,61 +227,63 @@ impl RequestBencher for SyncBencher { fn config() -> Config { Config { - endpoints: vec![ - format!("ws://{}", SERVER_ONE_ENDPOINT), - format!("ws://{}", SERVER_TWO_ENDPOINT), - ], - stale_timeout_seconds: 60, - cache_ttl_seconds: None, - merge_subscription_keep_alive_seconds: None, - server: ServerConfig { - listen_address: SUBWAY_SERVER_ADDR.to_string(), - port: SUBWAY_SERVER_PORT, - max_connections: 1024 * 1024, + extensions: ExtensionsConfig { + client: Some(ClientConfig { + endpoints: vec![ + format!("ws://{}", SERVER_ONE_ENDPOINT), + format!("ws://{}", SERVER_TWO_ENDPOINT), + ], + shuffle_endpoints: false, + }), + server: Some(ServerConfig { + listen_address: SUBWAY_SERVER_ADDR.to_string(), + port: SUBWAY_SERVER_PORT, + max_connections: 1024 * 1024, + health: None, + }), + ..Default::default() + }, + middlewares: MiddlewaresConfig { + methods: vec!["inject_params".to_string(), "upstream".to_string()], + subscriptions: vec!["upstream".to_string()], }, rpcs: RpcDefinitions { methods: vec![ RpcMethod { method: helpers::SYNC_FAST_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::ASYNC_FAST_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::SYNC_MEM_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::ASYNC_MEM_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::SYNC_SLOW_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::ASYNC_SLOW_CALL.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, RpcMethod { method: helpers::ASYNC_INJECT_CALL.to_string(), @@ -296,9 +301,8 @@ fn config() -> Config { inject: true, }, ], - cache: 0, - cache_ttl_seconds: None, response: None, + cache: None, }, ], subscriptions: vec![RpcSubscription { @@ -309,15 +313,12 @@ fn config() -> Config { }], aliases: vec![], }, - telemetry: None, - health: None, } } async fn server() -> (String, jsonrpsee::server::ServerHandle) { let config = config(); - let client = Client::new(&config.endpoints).await.unwrap(); - let (addr, handle) = start_server(&config, client).await.unwrap(); + let (addr, handle) = start_server(config).await.unwrap(); (format!("ws://{}", addr), handle) } diff --git a/config.yml b/config.yml index 3eb6dfb..f6edf39 100644 --- a/config.yml +++ b/config.yml @@ -1,19 +1,34 @@ -endpoints: - - wss://acala-rpc.dwellir.com:443 - - wss://acala-rpc-0.aca-api.network:443 +extensions: + client: + endpoints: + - wss://acala-rpc.dwellir.com:443 + - wss://acala-rpc-0.aca-api.network:443 + event_bus: + substrate_api: + stale_timeout_seconds: 180 # rotate endpoint if no new blocks for 3 minutes + telemetry: + provider: none + cache: + default_ttl_seconds: 60 + default_size: 500 + merge_subscription: + keep_alive_seconds: 60 + server: + port: 9944 + listen_address: '0.0.0.0' + max_connections: 2000 + health: + path: /health + method: system_health -stale_timeout_seconds: 180 # rotate endpoint if no new blocks for 3 minutes - -server: - port: 9944 - listen_address: '0.0.0.0' - max_connections: 2000 - -telemetry: - provider: none +middlewares: + methods: + - response + - cache + - inject_params + - upstream + subscriptions: + - merge_subscription + - upstream rpcs: substrate - -health: - path: /health - method: system_health diff --git a/eth_config.yml b/eth_config.yml index 65773dd..3122d6e 100644 --- a/eth_config.yml +++ b/eth_config.yml @@ -1,11 +1,27 @@ -endpoints: - - wss://eth-rpc-karura-testnet.aca-staging.network:443 +extensions: + client: + endpoints: + - wss://eth-rpc-karura-testnet.aca-staging.network:443 + event_bus: + eth_api: + stale_timeout_seconds: 180 # rotate endpoint if no new blocks for 3 minutes + telemetry: + provider: none + cache: + default_ttl_seconds: 60 + default_size: 500 + server: + port: 8545 + listen_address: '0.0.0.0' + max_connections: 2000 -stale_timeout_seconds: 180 # rotate endpoint if no new blocks for 3 minutes - -server: - port: 8545 - listen_address: '0.0.0.0' - max_connections: 2000 +middlewares: + methods: + - response + - cache + - block_tag + - upstream + subscriptions: + - upstream rpcs: ethereum diff --git a/rpc_configs/ethereum.yml b/rpc_configs/ethereum.yml index d92e312..62019fe 100644 --- a/rpc_configs/ethereum.yml +++ b/rpc_configs/ethereum.yml @@ -2,7 +2,8 @@ methods: - method: eth_blockNumber - method: eth_chainId - cache: 1 + cache: + size: 1 - method: eth_protocolVersion @@ -15,20 +16,24 @@ methods: - method: eth_accounts - method: net_version - cache: 1 + cache: + size: 1 - method: net_runtimeVersion - cache: 1 + cache: + size: 1 - method: net_health - method: net_isSafeMode - cache: 1 + cache: + size: 1 - method: net_indexer - method: web3_clientVersion - cache: 1 + cache: + size: 1 - method: eth_sign params: @@ -60,7 +65,6 @@ methods: ty: BlockHash - method: eth_getBlockByHash - cache: 2000 params: - name: BlockHash ty: BlockHash @@ -68,7 +72,6 @@ methods: ty: Boolean - method: eth_getBlockByNumber - cache: 2000 params: - name: blockTag ty: BlockTag @@ -77,26 +80,22 @@ methods: ty: Boolean - method: eth_getBlockTransactionCountByHash - cache: 2000 params: - name: BlockHash ty: BlockHash - method: eth_getBlockTransactionCountByNumber - cache: 2000 params: - name: blockTag ty: BlockTag inject: true - method: eth_getUncleCountByBlockHash - cache: 2000 params: - name: BlockHash ty: BlockHash - method: eth_getUncleCountByBlockNumber - cache: 2000 params: - name: blockTag ty: BlockTag @@ -117,7 +116,6 @@ methods: ty: Bytes - method: eth_getUncleByBlockHashAndIndex - cache: 2000 params: - name: blockHash ty: BlockHash @@ -125,7 +123,6 @@ methods: ty: Bytes - method: eth_getUncleByBlockNumberAndIndex - cache: 2000 params: - name: block ty: BlockTag @@ -134,14 +131,12 @@ methods: ty: Bytes - method: eth_isBlockFinalized - cache: 2000 params: - name: block ty: BlockTag inject: true - method: eth_isTransactionFinalized - cache: 2000 params: - name: transactionHash ty: Bytes @@ -176,7 +171,6 @@ methods: ty: Bytes - method: eth_getBalance - cache: 2000 params: - name: Address ty: Bytes @@ -185,7 +179,6 @@ methods: inject: true - method: eth_getStorageAt - cache: 2000 params: - name: address ty: Bytes @@ -196,7 +189,6 @@ methods: inject: true - method: eth_getCode - cache: 2000 params: - name: Address ty: Bytes @@ -205,13 +197,11 @@ methods: inject: true - method: eth_getTransactionByHash - cache: 2000 params: - name: transactionHash ty: Bytes - method: eth_getTransactionByBlockHashAndIndex - cache: 2000 params: - name: BlockHash ty: BlockHash @@ -219,7 +209,6 @@ methods: ty: Bytes - method: eth_getTransactionByBlockNumberAndIndex - cache: 2000 params: - name: blockTag ty: BlockTag @@ -238,7 +227,6 @@ methods: ty: Bytes - method: eth_getTransactionReceipt - cache: 2000 params: - name: txHash ty: Bytes diff --git a/rpc_configs/substrate.yml b/rpc_configs/substrate.yml index 3d319ab..562f5e6 100644 --- a/rpc_configs/substrate.yml +++ b/rpc_configs/substrate.yml @@ -1,14 +1,17 @@ methods: - method: author_submitExtrinsic + cache: + size: 0 params: - name: extrinsic ty: Bytes - method: author_pendingExtrinsics - cache_ttl_seconds: 1 + cache: + size: 1 + ttl_seconds: 3 - method: chain_getBlockHash - cache: 2000 params: - name: blockNumber ty: BlockNumber @@ -16,7 +19,6 @@ methods: inject: true - method: chain_getHeader - cache: 2000 params: - name: hash ty: BlockHash @@ -24,7 +26,6 @@ methods: inject: true - method: chain_getBlock - cache: 2000 params: - name: hash ty: BlockHash @@ -32,10 +33,12 @@ methods: inject: true - method: chain_getFinalizedHead - cache_ttl_seconds: 1 + cache: + size: 1 + ttl_seconds: 6 + invalidate_at: OnNewFinalizedHead - method: state_getRuntimeVersion - cache: 2000 params: - name: at ty: BlockHash @@ -43,7 +46,6 @@ methods: inject: true - method: state_getMetadata - cache: 2000 params: - name: at ty: BlockHash @@ -51,7 +53,6 @@ methods: inject: true - method: state_getStorage - cache: 2000 params: - name: key ty: StorageKey @@ -61,7 +62,6 @@ methods: inject: true - method: state_getKeysPaged - cache: 2000 params: - name: key ty: StorageKey @@ -76,7 +76,6 @@ methods: inject: true - method: state_queryStorageAt - cache: 2000 params: - name: keys ty: 'Vec' @@ -86,7 +85,9 @@ methods: inject: true - method: state_call - cache: 2000 + cache: + size: 200 + ttl_seconds: 30 params: - name: method ty: String @@ -98,10 +99,12 @@ methods: inject: true - method: system_chain - cache: 1 + cache: + size: 1 - method: system_properties - cache: 1 + cache: + size: 1 - method: system_name response: Subway @@ -110,21 +113,29 @@ methods: response: 1.0.0-dev - method: system_chainType - cache: 1 + cache: + size: 1 - method: system_localPeerId - cache: 1 + cache: + size: 1 - method: system_nodeRoles response: [ 'Full' ] - method: system_localListenAddresses - cache: 1 + cache: + size: 1 - method: system_health + cache: + size: 1 + ttl_seconds: 5 - method: system_dryRun - cache: 100 + cache: + size: 200 + ttl_seconds: 30 params: - name: extrinsic ty: Bytes @@ -134,6 +145,8 @@ methods: inject: true - method: system_accountNextIndex + cache: + size: 0 params: - name: accountId ty: AccountId diff --git a/src/config.rs b/src/config/mod.rs similarity index 61% rename from src/config.rs rename to src/config/mod.rs index 74cf03f..9dffaa1 100644 --- a/src/config.rs +++ b/src/config/mod.rs @@ -1,10 +1,15 @@ +use std::fs; + use clap::Parser; -use jsonrpsee::core::JsonValue; use serde::Deserialize; -use std::{fs, num::NonZeroUsize}; -const SUBSTRATE_CONFIG: &str = include_str!("../rpc_configs/substrate.yml"); -const ETHEREUM_CONFIG: &str = include_str!("../rpc_configs/ethereum.yml"); +use crate::extensions::ExtensionsConfig; +pub use rpc::*; + +mod rpc; + +const SUBSTRATE_CONFIG: &str = include_str!("../../rpc_configs/substrate.yml"); +const ETHEREUM_CONFIG: &str = include_str!("../../rpc_configs/ethereum.yml"); #[derive(Parser, Debug)] #[command(version, about)] @@ -14,81 +19,6 @@ struct Command { config: String, } -#[derive(Deserialize, Debug)] -pub struct ServerConfig { - pub listen_address: String, - pub port: u16, - pub max_connections: u32, -} - -#[derive(Deserialize, Debug)] -pub struct RpcMethod { - pub method: String, - #[serde(default)] - pub params: Vec, - - /// if cache_ttl_seconds is defined, cache default will be 1 - #[serde(default)] - pub cache: usize, - - // None means use global cache_ttl_seconds - #[serde(default)] - pub cache_ttl_seconds: Option, - - #[serde(default)] - pub response: Option, -} - -impl RpcMethod { - pub fn cache_size(&self) -> Option { - match (self.cache, self.cache_ttl_seconds) { - (0, None) => None, - (0, Some(0)) => None, - (0, Some(_)) => NonZeroUsize::new(1), - (cache, _) => NonZeroUsize::new(cache), - } - } -} - -#[derive(Clone, Deserialize, Debug, Eq, PartialEq)] -pub struct MethodParam { - pub name: String, - #[serde(default)] - pub ty: String, - #[serde(default)] - pub optional: bool, - #[serde(default)] - pub inject: bool, -} - -#[derive(Copy, Clone, Deserialize, Debug)] -#[serde(rename_all = "snake_case")] -pub enum MergeStrategy { - // Replace old value with new value - Replace, - // Merge old storage changes with new changes - MergeStorageChanges, -} - -#[derive(Deserialize, Debug)] -pub struct RpcSubscription { - pub subscribe: String, - pub unsubscribe: String, - pub name: String, - - #[serde(default)] - pub merge_strategy: Option, -} - -#[derive(Deserialize, Debug)] -pub struct RpcDefinitions { - pub methods: Vec, - #[serde(default)] - pub subscriptions: Vec, - #[serde(default)] - pub aliases: Vec<(String, String)>, -} - #[derive(Deserialize, Debug)] pub struct RpcDefinitionsWithBase { #[serde(default)] @@ -188,67 +118,31 @@ impl From for RpcDefinitions { } #[derive(Deserialize, Debug)] -#[serde(rename_all = "snake_case")] -pub enum TelemetryProvider { - None, - Datadog, - Jaeger, -} - -#[derive(Deserialize, Debug)] -pub struct TelemetryOptions { - pub provider: TelemetryProvider, - #[serde(default)] - pub service_name: Option, - #[serde(default)] - pub agent_endpoint: Option, -} - -#[derive(Deserialize, Debug)] -pub struct HealthConfig { - pub path: String, - pub method: String, +pub struct MiddlewaresConfig { + pub methods: Vec, + pub subscriptions: Vec, } #[derive(Debug)] pub struct Config { - pub endpoints: Vec, - pub stale_timeout_seconds: u64, - // None means no cache expiration - pub cache_ttl_seconds: Option, - pub merge_subscription_keep_alive_seconds: Option, - pub server: ServerConfig, + pub extensions: ExtensionsConfig, + pub middlewares: MiddlewaresConfig, pub rpcs: RpcDefinitions, - pub telemetry: Option, - pub health: Option, } #[derive(Deserialize, Debug)] pub struct ParseConfig { - pub endpoints: Vec, - pub stale_timeout_seconds: u64, - #[serde(default)] - pub cache_ttl_seconds: Option, - pub merge_subscription_keep_alive_seconds: Option, - pub server: ServerConfig, + pub extensions: ExtensionsConfig, + pub middlewares: MiddlewaresConfig, pub rpcs: RpcOptions, - #[serde(default)] - pub telemetry: Option, - #[serde(default)] - pub health: Option, } impl From for Config { fn from(val: ParseConfig) -> Self { Config { - endpoints: val.endpoints, - stale_timeout_seconds: val.stale_timeout_seconds, - cache_ttl_seconds: val.cache_ttl_seconds, - merge_subscription_keep_alive_seconds: val.merge_subscription_keep_alive_seconds, - server: val.server, + extensions: val.extensions, + middlewares: val.middlewares, rpcs: val.rpcs.into(), - telemetry: val.telemetry, - health: val.health, } } } @@ -264,28 +158,44 @@ pub fn read_config() -> Result { if let Ok(endpoints) = std::env::var("ENDPOINTS") { log::debug!("Override endpoints with env.ENDPOINTS"); - config.endpoints = endpoints + let endpoints = endpoints .split(',') .map(|x| x.trim().to_string()) - .collect::>(); + .collect::>(); + + config + .extensions + .client + .as_mut() + .expect("Client extension not configured") + .endpoints = endpoints; } if let Ok(env_port) = std::env::var("PORT") { log::debug!("Override port with env.PORT"); let port = env_port.parse::(); if let Ok(port) = port { - config.server.port = port; + config + .extensions + .server + .as_mut() + .expect("Server extension not configured") + .port = port; + } else { + return Err(format!("Invalid port: {}", env_port)); } } + // TODO: shouldn't need to do this here. Creating a server should validates everything validate_config(&config)?; Ok(config) } fn validate_config(config: &Config) -> Result<(), String> { + // TODO: validate logic should be in each individual extensions // validate endpoints - for endpoint in &config.endpoints { + for endpoint in &config.extensions.client.as_ref().unwrap().endpoints { if endpoint .parse::() .is_err() diff --git a/src/config/rpc.rs b/src/config/rpc.rs new file mode 100644 index 0000000..8775ed2 --- /dev/null +++ b/src/config/rpc.rs @@ -0,0 +1,63 @@ +use jsonrpsee::core::JsonValue; +use serde::Deserialize; + +#[derive(Clone, Deserialize, Debug, Eq, PartialEq)] +pub struct CacheParams { + #[serde(default)] + pub size: Option, + #[serde(default)] + pub ttl_seconds: Option, +} + +#[derive(Clone, Deserialize, Debug, Eq, PartialEq)] +pub struct MethodParam { + pub name: String, + #[serde(default)] + pub ty: String, + #[serde(default)] + pub optional: bool, + #[serde(default)] + pub inject: bool, +} + +#[derive(Deserialize, Debug)] +pub struct RpcMethod { + pub method: String, + + #[serde(default)] + pub cache: Option, + + #[serde(default)] + pub params: Vec, + + #[serde(default)] + pub response: Option, +} + +#[derive(Copy, Clone, Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum MergeStrategy { + // Replace old value with new value + Replace, + // Merge old storage changes with new changes + MergeStorageChanges, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSubscription { + pub subscribe: String, + pub unsubscribe: String, + pub name: String, + + #[serde(default)] + pub merge_strategy: Option, +} + +#[derive(Deserialize, Debug)] +pub struct RpcDefinitions { + pub methods: Vec, + #[serde(default)] + pub subscriptions: Vec, + #[serde(default)] + pub aliases: Vec<(String, String)>, +} diff --git a/src/extension/mod.rs b/src/extension/mod.rs new file mode 100644 index 0000000..e375cc0 --- /dev/null +++ b/src/extension/mod.rs @@ -0,0 +1,64 @@ +use std::{ + any::{Any, TypeId}, + sync::Arc, +}; + +use async_trait::async_trait; + +use crate::utils::TypeRegistryRef; + +#[async_trait] +pub trait Extension: Sized { + type Config: serde::Deserialize<'static>; + + async fn from_config( + config: &Self::Config, + registry: &ExtensionRegistry, + ) -> Result; +} + +#[async_trait] +pub trait ExtensionBuilder { + fn has(&self, type_id: TypeId) -> bool; + async fn build( + &self, + type_id: TypeId, + registry: &ExtensionRegistry, + ) -> anyhow::Result>; +} + +pub struct ExtensionRegistry { + pub registry: TypeRegistryRef, + builder: Arc, +} + +impl ExtensionRegistry { + pub fn new( + registry: TypeRegistryRef, + builder: Arc, + ) -> Self { + Self { registry, builder } + } + + pub async fn get(&self) -> Option> { + let reg = self.registry.read().await; + + let ext = reg.get::(); + + if ext.is_none() && self.builder.has(TypeId::of::()) { + drop(reg); + let ext = self + .builder + .build(TypeId::of::(), self) + .await + .expect("Failed to build extension"); + self.registry.write().await.insert_raw(ext); + let reg = self.registry.read().await; + let ext = reg.get::(); + assert!(ext.is_some()); + ext + } else { + ext + } + } +} diff --git a/src/api/eth.rs b/src/extensions/api/eth.rs similarity index 82% rename from src/api/eth.rs rename to src/extensions/api/eth.rs index 479deb0..a097717 100644 --- a/src/api/eth.rs +++ b/src/extensions/api/eth.rs @@ -1,16 +1,46 @@ -use crate::{ - api::{BaseApi, ValueHandle}, - client::Client, -}; -use jsonrpsee::core::JsonValue; use std::{sync::Arc, time::Duration}; + +use async_trait::async_trait; +use jsonrpsee::core::JsonValue; +use serde::Deserialize; use tokio::sync::watch; +use crate::{ + extension::Extension, + extensions::{ + api::{BaseApi, ValueHandle}, + client::Client, + }, + middleware::ExtensionRegistry, +}; + pub struct EthApi { inner: BaseApi, stale_timeout: Duration, } +#[derive(Deserialize, Debug)] +pub struct EthApiConfig { + stale_timeout_seconds: u64, +} + +#[async_trait] +impl Extension for EthApi { + type Config = EthApiConfig; + + async fn from_config( + config: &Self::Config, + registry: &ExtensionRegistry, + ) -> Result { + let client = registry.get::().await.expect("Client not found"); + + Ok(Self::new( + client, + Duration::from_secs(config.stale_timeout_seconds), + )) + } +} + impl EthApi { pub fn new(client: Arc, stale_timeout: Duration) -> Self { let (head_tx, head_rx) = watch::channel::>(None); @@ -18,11 +48,11 @@ impl EthApi { watch::channel::>(None); let this = Self { - inner: BaseApi::new(client, head_rx, finalized_head_rx), + inner: BaseApi::new(head_rx, finalized_head_rx), stale_timeout, }; - this.start_background_task(head_tx, finalized_head_tx); + this.start_background_task(client, head_tx, finalized_head_tx); this } @@ -45,18 +75,18 @@ impl EthApi { fn start_background_task( &self, + client: Arc, head_tx: watch::Sender>, finalized_head_tx: watch::Sender>, ) { - let client = self.inner.client.clone(); let stale_timeout = self.stale_timeout; + let client2 = client.clone(); tokio::spawn(async move { let mut interval = tokio::time::interval(stale_timeout); + let client = client2.clone(); loop { - let client = client.clone(); - let run = async { interval.reset(); @@ -111,8 +141,10 @@ impl EthApi { } }); - let client = self.inner.client.clone(); + let client = client.clone(); tokio::spawn(async move { + let client = client.clone(); + loop { let run = async { let mut sub = client diff --git a/src/api/mod.rs b/src/extensions/api/mod.rs similarity index 91% rename from src/api/mod.rs rename to src/extensions/api/mod.rs index c891c6e..4a0fada 100644 --- a/src/api/mod.rs +++ b/src/extensions/api/mod.rs @@ -1,9 +1,6 @@ use jsonrpsee::core::JsonValue; -use std::sync::Arc; use tokio::sync::watch; -use crate::client::Client; - #[cfg(test)] mod tests; @@ -16,19 +13,16 @@ pub use substrate::SubstrateApi; pub use value_handle::ValueHandle; pub(crate) struct BaseApi { - pub client: Arc, pub head_rx: watch::Receiver>, pub finalized_head_rx: watch::Receiver>, } impl BaseApi { pub fn new( - client: Arc, head_rx: watch::Receiver>, finalized_head_rx: watch::Receiver>, ) -> Self { Self { - client, head_rx, finalized_head_rx, } diff --git a/src/api/substrate.rs b/src/extensions/api/substrate.rs similarity index 81% rename from src/api/substrate.rs rename to src/extensions/api/substrate.rs index 74cbba1..02e05c4 100644 --- a/src/api/substrate.rs +++ b/src/extensions/api/substrate.rs @@ -1,16 +1,47 @@ -use crate::{ - api::{BaseApi, ValueHandle}, - client::Client, -}; -use jsonrpsee::core::JsonValue; use std::{sync::Arc, time::Duration}; + +use async_trait::async_trait; +use jsonrpsee::core::JsonValue; +use serde::Deserialize; use tokio::sync::watch; +use crate::{ + extension::Extension, + extensions::{ + api::{BaseApi, ValueHandle}, + client::Client, + }, + middleware::ExtensionRegistry, +}; + pub struct SubstrateApi { + client: Arc, inner: BaseApi, stale_timeout: Duration, } +#[derive(Deserialize, Debug)] +pub struct SubstrateApiConfig { + stale_timeout_seconds: u64, +} + +#[async_trait] +impl Extension for SubstrateApi { + type Config = SubstrateApiConfig; + + async fn from_config( + config: &Self::Config, + registry: &ExtensionRegistry, + ) -> Result { + let client = registry.get::().await.expect("Client not found"); + + Ok(Self::new( + client, + Duration::from_secs(config.stale_timeout_seconds), + )) + } +} + impl SubstrateApi { pub fn new(client: Arc, stale_timeout: Duration) -> Self { let (head_tx, head_rx) = watch::channel::>(None); @@ -18,7 +49,8 @@ impl SubstrateApi { watch::channel::>(None); let this = Self { - inner: BaseApi::new(client, head_rx, finalized_head_rx), + client, + inner: BaseApi::new(head_rx, finalized_head_rx), stale_timeout, }; @@ -40,15 +72,15 @@ impl SubstrateApi { head_tx: watch::Sender>, finalized_head_tx: watch::Sender>, ) { - let client = self.inner.client.clone(); + let client = self.client.clone(); let stale_timeout = self.stale_timeout; tokio::spawn(async move { let mut interval = tokio::time::interval(stale_timeout); - loop { - let client = client.clone(); + let client = client.clone(); + loop { let run = async { interval.reset(); @@ -96,12 +128,10 @@ impl SubstrateApi { } }); - let client = self.inner.client.clone(); + let client = self.client.clone(); tokio::spawn(async move { loop { - let client = client.clone(); - let run = async { let sub = client .subscribe( diff --git a/src/api/tests.rs b/src/extensions/api/tests.rs similarity index 95% rename from src/api/tests.rs rename to src/extensions/api/tests.rs index cf343bd..21ee5da 100644 --- a/src/api/tests.rs +++ b/src/extensions/api/tests.rs @@ -1,13 +1,14 @@ use std::net::SocketAddr; +use std::sync::Arc; -use crate::api::substrate::SubstrateApi; use jsonrpsee::{server::ServerHandle, SubscriptionMessage, SubscriptionSink}; use serde_json::json; use tokio::sync::{mpsc, oneshot}; +use super::substrate::SubstrateApi; use super::*; -use crate::client::mock::TestServerBuilder; +use crate::extensions::client::{mock::TestServerBuilder, Client}; async fn create_server() -> ( SocketAddr, @@ -46,7 +47,7 @@ async fn create_client() -> ( ) { let (addr, server, head_rx, finalized_head_rx, block_hash_rx) = create_server().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); (client, server, head_rx, finalized_head_rx, block_hash_rx) } @@ -168,11 +169,7 @@ async fn rotate_endpoint_on_stale() { let (addr, server, mut head_rx, _, mut block_rx) = create_server().await; let (addr2, server2, mut head_rx2, _, mut block_rx2) = create_server().await; - println!("{} {}", addr, addr2); - - let client = Client::new(&[format!("ws://{addr}"), format!("ws://{addr2}")]) - .await - .unwrap(); + let client = Client::new([format!("ws://{addr}"), format!("ws://{addr2}")]).unwrap(); let api = SubstrateApi::new(Arc::new(client), std::time::Duration::from_millis(10)); let head = api.get_head(); diff --git a/src/api/value_handle.rs b/src/extensions/api/value_handle.rs similarity index 98% rename from src/api/value_handle.rs rename to src/extensions/api/value_handle.rs index 08e36b4..425c2ec 100644 --- a/src/api/value_handle.rs +++ b/src/extensions/api/value_handle.rs @@ -39,7 +39,7 @@ impl ValueHandle { #[cfg(test)] mod tests { - use crate::api::ValueHandle; + use super::*; use std::time::Duration; #[tokio::test] diff --git a/src/extensions/cache.rs b/src/extensions/cache.rs new file mode 100644 index 0000000..4bf5dad --- /dev/null +++ b/src/extensions/cache.rs @@ -0,0 +1,34 @@ +use async_trait::async_trait; +use serde::Deserialize; + +use crate::{extension::Extension, middleware::ExtensionRegistry}; + +pub struct Cache { + pub config: CacheConfig, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct CacheConfig { + // None means no cache expiration + #[serde(default)] + pub default_ttl_seconds: Option, + pub default_size: u32, +} + +#[async_trait] +impl Extension for Cache { + type Config = CacheConfig; + + async fn from_config( + config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + Ok(Self::new(config.clone())) + } +} + +impl Cache { + pub fn new(config: CacheConfig) -> Self { + Self { config } + } +} diff --git a/src/client/mock.rs b/src/extensions/client/mock.rs similarity index 100% rename from src/client/mock.rs rename to src/extensions/client/mock.rs diff --git a/src/client/mod.rs b/src/extensions/client/mod.rs similarity index 92% rename from src/client/mod.rs rename to src/extensions/client/mod.rs index 9e4b9df..fdcad9f 100644 --- a/src/client/mod.rs +++ b/src/extensions/client/mod.rs @@ -1,5 +1,7 @@ use std::sync::{atomic::AtomicUsize, Arc}; +use anyhow::anyhow; +use async_trait::async_trait; use futures::TryFutureExt; use jsonrpsee::{ core::{ @@ -10,20 +12,37 @@ use jsonrpsee::{ ws_client::{WsClient, WsClientBuilder}, }; use opentelemetry::trace::FutureExt; +use rand::{seq::SliceRandom, thread_rng}; +use serde::Deserialize; -use crate::helpers::{self, errors}; +use crate::{ + extension::Extension, + middleware::ExtensionRegistry, + utils::{self, errors}, +}; #[cfg(test)] pub mod mock; #[cfg(test)] mod tests; -const TRACER: helpers::telemetry::Tracer = helpers::telemetry::Tracer::new("client"); +const TRACER: utils::telemetry::Tracer = utils::telemetry::Tracer::new("client"); pub struct Client { sender: tokio::sync::mpsc::Sender, } +#[derive(Deserialize, Debug)] +pub struct ClientConfig { + pub endpoints: Vec, + #[serde(default = "bool_true")] + pub shuffle_endpoints: bool, +} + +pub fn bool_true() -> bool { + true +} + #[derive(Debug)] enum Message { Request { @@ -40,15 +59,35 @@ enum Message { RotateEndpoint, } +#[async_trait] +impl Extension for Client { + type Config = ClientConfig; + + async fn from_config( + config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + if config.shuffle_endpoints { + let mut endpoints = config.endpoints.clone(); + endpoints.shuffle(&mut thread_rng()); + Ok(Self::new(endpoints)?) + } else { + Ok(Self::new(config.endpoints.clone())?) + } + } +} + impl Client { - pub async fn new(endpoints: impl IntoIterator>) -> Result { + pub fn new( + endpoints: impl IntoIterator>, + ) -> Result { let endpoints: Vec<_> = endpoints .into_iter() .map(|e| e.as_ref().to_string()) .collect(); if endpoints.is_empty() { - return Err("No endpoints provided".into()); + return Err(anyhow!("No endpoints provided")); } tracing::debug!("New client with endpoints: {:?}", endpoints); diff --git a/src/client/tests.rs b/src/extensions/client/tests.rs similarity index 93% rename from src/client/tests.rs rename to src/extensions/client/tests.rs index 95d332c..dc9e91c 100644 --- a/src/client/tests.rs +++ b/src/extensions/client/tests.rs @@ -11,7 +11,7 @@ use tokio::sync::{mpsc, oneshot}; async fn basic_request() { let (addr, handle, mut rx, _) = dummy_server().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let task = tokio::spawn(async move { let (params, resp_tx) = rx.recv().await.unwrap(); @@ -31,7 +31,7 @@ async fn basic_request() { async fn basic_subscription() { let (addr, handle, _, mut rx) = dummy_server().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let task = tokio::spawn(async move { let (params, sink) = rx.recv().await.unwrap(); @@ -71,12 +71,11 @@ async fn multiple_endpoints() { let (addr2, handle2, rx2, _) = dummy_server().await; let (addr3, handle3, rx3, _) = dummy_server().await; - let client = Client::new(&[ + let client = Client::new([ format!("ws://{addr1}"), format!("ws://{addr2}"), format!("ws://{addr3}"), ]) - .await .unwrap(); let handle_requests = |mut rx: mpsc::Receiver<(JsonValue, oneshot::Sender)>, @@ -128,7 +127,7 @@ async fn multiple_endpoints() { async fn concurrent_requests() { let (addr, handle, mut rx, _) = dummy_server().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let task = tokio::spawn(async move { let (_, tx1) = rx.recv().await.unwrap(); @@ -160,9 +159,7 @@ async fn retry_requests() { let (addr1, handle1, mut rx1, _) = dummy_server().await; let (addr2, handle2, mut rx2, _) = dummy_server().await; - let client = Client::new(&[format!("ws://{addr1}"), format!("ws://{addr2}")]) - .await - .unwrap(); + let client = Client::new([format!("ws://{addr1}"), format!("ws://{addr2}")]).unwrap(); let h1 = tokio::spawn(async move { let (_, tx) = rx1.recv().await.unwrap(); diff --git a/src/extensions/event_bus.rs b/src/extensions/event_bus.rs new file mode 100644 index 0000000..abb7c5f --- /dev/null +++ b/src/extensions/event_bus.rs @@ -0,0 +1,21 @@ +use async_trait::async_trait; +use serde::Deserialize; + +use crate::{extension::Extension, middleware::ExtensionRegistry}; + +pub struct EventBus; + +#[derive(Deserialize, Debug, Clone)] +pub struct EventBusConfig; + +#[async_trait] +impl Extension for EventBus { + type Config = EventBusConfig; + + async fn from_config( + _config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + Ok(EventBus) + } +} diff --git a/src/extensions/merge_subscription.rs b/src/extensions/merge_subscription.rs new file mode 100644 index 0000000..8b262c0 --- /dev/null +++ b/src/extensions/merge_subscription.rs @@ -0,0 +1,32 @@ +use async_trait::async_trait; +use serde::Deserialize; + +use crate::{extension::Extension, middleware::ExtensionRegistry}; + +pub struct MergeSubscription { + pub config: MergeSubscriptionConfig, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct MergeSubscriptionConfig { + #[serde(default)] + pub keep_alive_seconds: Option, +} + +#[async_trait] +impl Extension for MergeSubscription { + type Config = MergeSubscriptionConfig; + + async fn from_config( + config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + Ok(Self::new(config.clone())) + } +} + +impl MergeSubscription { + pub fn new(config: MergeSubscriptionConfig) -> Self { + Self { config } + } +} diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs new file mode 100644 index 0000000..20f83b6 --- /dev/null +++ b/src/extensions/mod.rs @@ -0,0 +1,92 @@ +use std::{ + any::{Any, TypeId}, + sync::Arc, +}; + +use async_trait::async_trait; +use serde::Deserialize; +use tokio::sync::RwLock; + +use crate::{ + extension::{Extension, ExtensionBuilder, ExtensionRegistry}, + utils::{TypeRegistry, TypeRegistryRef}, +}; + +pub mod api; +pub mod cache; +pub mod client; +pub mod event_bus; +pub mod merge_subscription; +pub mod server; +pub mod telemetry; + +macro_rules! define_all_extensions { + ( + $( + $ext_name:ident: $ext_type:ty + ),* $(,)? + ) => { + #[derive(Deserialize, Debug, Default)] + pub struct ExtensionsConfig { + $( + #[serde(default)] + pub $ext_name: Option<<$ext_type as Extension>::Config>, + )* + } + + #[async_trait] + impl ExtensionBuilder for ExtensionsConfig { + fn has(&self, type_id: TypeId) -> bool { + match type_id { + $( + id if id == TypeId::of::<$ext_type>() => self.$ext_name.is_some(), + )* + _ => false, + } + } + + async fn build(&self, type_id: TypeId, registry: &ExtensionRegistry) -> anyhow::Result> { + match type_id { + $( + id if id == TypeId::of::<$ext_type>() => { + if let Some(config) = &self.$ext_name { + let ext = <$ext_type as Extension>::from_config(&config, ®istry).await?; + Ok(Arc::new(ext)) + } else { + anyhow::bail!("No config for extension: {}", stringify!($ext_name)); + } + } + )* + id => { + anyhow::bail!("Unknown extension: {:?}", id); + } + } + } + } + + impl ExtensionsConfig { + pub async fn create_registry(self) -> Result { + let reg = Arc::new(RwLock::new(TypeRegistry::new())); + let ext_reg = ExtensionRegistry::new(reg.clone(), Arc::new(self)); + + // ensure all the extensions are created + $( + let _ = ext_reg.get::<$ext_type>().await; + )* + + Ok(reg) + } + } + }; +} + +define_all_extensions! { + telemetry: telemetry::Telemetry, + cache: cache::Cache, + client: client::Client, + merge_subscription: merge_subscription::MergeSubscription, + substrate_api: api::SubstrateApi, + eth_api: api::EthApi, + server: server::Server, + event_bus: event_bus::EventBus, +} diff --git a/src/extensions/server.rs b/src/extensions/server.rs new file mode 100644 index 0000000..a70471e --- /dev/null +++ b/src/extensions/server.rs @@ -0,0 +1,72 @@ +use std::{future::Future, net::SocketAddr}; + +use async_trait::async_trait; +use jsonrpsee::server::{ + middleware::proxy_get_request::ProxyGetRequestLayer, + {RandomStringIdProvider, RpcModule, ServerBuilder, ServerHandle}, +}; +use serde::Deserialize; + +use crate::{extension::Extension, middleware::ExtensionRegistry}; + +pub struct Server { + config: ServerConfig, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct HealthConfig { + pub path: String, + pub method: String, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct ServerConfig { + pub port: u16, + pub listen_address: String, + pub max_connections: u32, + #[serde(default)] + pub health: Option, +} + +#[async_trait] +impl Extension for Server { + type Config = ServerConfig; + + async fn from_config( + config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + Ok(Self::new(config.clone())) + } +} + +impl Server { + pub fn new(config: ServerConfig) -> Self { + Self { config } + } + + pub async fn create_server>>>( + &self, + builder: impl FnOnce() -> Fut, + ) -> anyhow::Result<(SocketAddr, ServerHandle)> { + let service_builder = + tower::ServiceBuilder::new().option_layer(self.config.health.as_ref().map(|h| { + ProxyGetRequestLayer::new(h.path.clone(), h.method.clone()) + .expect("Invalid health config") + })); + + let server = ServerBuilder::default() + .set_middleware(service_builder) + .max_connections(self.config.max_connections) + .set_id_provider(RandomStringIdProvider::new(16)) + .build((self.config.listen_address.as_str(), self.config.port)) + .await?; + + let module = builder().await?; + + let addr = server.local_addr()?; + let server = server.start(module)?; + + Ok((addr, server)) + } +} diff --git a/src/telemetry.rs b/src/extensions/telemetry.rs similarity index 57% rename from src/telemetry.rs rename to src/extensions/telemetry.rs index c2908ca..51fd10e 100644 --- a/src/telemetry.rs +++ b/src/extensions/telemetry.rs @@ -1,14 +1,57 @@ use std::env; +use async_trait::async_trait; use opentelemetry::{global, sdk::trace::Tracer, trace::TraceError}; +use serde::Deserialize; -use crate::config::{TelemetryOptions, TelemetryProvider}; +use crate::{extension::Extension, middleware::ExtensionRegistry}; -pub fn setup_telemetry(options: &Option) -> Result, TraceError> { - let Some(options) = options else { - return Ok(None); - }; +#[derive(Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum TelemetryProvider { + None, + Datadog, + Jaeger, +} + +#[derive(Deserialize, Debug)] +pub struct TelemetryConfig { + pub provider: TelemetryProvider, + #[serde(default)] + pub service_name: Option, + #[serde(default)] + pub agent_endpoint: Option, +} + +pub struct Telemetry { + tracer: Option, +} + +#[async_trait] +impl Extension for Telemetry { + type Config = TelemetryConfig; + + async fn from_config( + config: &Self::Config, + _registry: &ExtensionRegistry, + ) -> Result { + Ok(Self::new(config)?) + } +} + +impl Telemetry { + pub fn new(config: &TelemetryConfig) -> Result { + let tracer = setup_telemetry(config)?; + + Ok(Self { tracer }) + } + + pub fn tracer(&self) -> Option<&Tracer> { + self.tracer.as_ref() + } +} +pub fn setup_telemetry(options: &TelemetryConfig) -> Result, TraceError> { global::set_error_handler(|e| { log::warn!("OpenTelemetry error: {}", e); }) diff --git a/src/integration_tests/merge_subscription.rs b/src/integration_tests/merge_subscription.rs index 631fdff..4d27c71 100644 --- a/src/integration_tests/merge_subscription.rs +++ b/src/integration_tests/merge_subscription.rs @@ -1,11 +1,18 @@ use serde_json::json; -use crate::client::{ - mock::{run_sink_tasks, SinkTask, TestServerBuilder}, - Client, +use crate::{ + config::{Config, MergeStrategy, MiddlewaresConfig, RpcDefinitions, RpcSubscription}, + extensions::{ + client::{ + mock::{run_sink_tasks, SinkTask, TestServerBuilder}, + Client, ClientConfig, + }, + merge_subscription::MergeSubscriptionConfig, + server::ServerConfig, + ExtensionsConfig, + }, + server::start_server, }; -use crate::config::{Config, MergeStrategy, RpcDefinitions, RpcSubscription, ServerConfig}; -use crate::server::start_server; #[tokio::test] async fn merge_subscription_works() { @@ -40,14 +47,25 @@ async fn merge_subscription_works() { }); let config = Config { - endpoints: vec![format!("ws://{addr}")], - stale_timeout_seconds: 0, - cache_ttl_seconds: None, - merge_subscription_keep_alive_seconds: Some(1), - server: ServerConfig { - listen_address: "0.0.0.0".to_string(), - port: 0, - max_connections: 10, + extensions: ExtensionsConfig { + client: Some(ClientConfig { + endpoints: vec![format!("ws://{addr}")], + shuffle_endpoints: false, + }), + server: Some(ServerConfig { + listen_address: "0.0.0.0".to_string(), + port: 0, + max_connections: 10, + health: None, + }), + merge_subscription: Some(MergeSubscriptionConfig { + keep_alive_seconds: Some(1), + }), + ..Default::default() + }, + middlewares: MiddlewaresConfig { + methods: vec![], + subscriptions: vec!["merge_subscription".to_string(), "upstream".to_string()], }, rpcs: RpcDefinitions { methods: vec![], @@ -73,18 +91,11 @@ async fn merge_subscription_works() { ], aliases: vec![], }, - telemetry: None, - health: None, }; - let (addr, server) = start_server( - &config, - Client::new(&[format!("ws://{addr}")]).await.unwrap(), - ) - .await - .unwrap(); + let (addr, server) = start_server(config).await.unwrap(); - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let mut first_sub = client .subscribe(subscribe_mock, vec![], unsubscribe_mock) .await diff --git a/src/integration_tests/mod.rs b/src/integration_tests/mod.rs index fc93ac4..b4261f0 100644 --- a/src/integration_tests/mod.rs +++ b/src/integration_tests/mod.rs @@ -1,2 +1 @@ -#[cfg(test)] mod merge_subscription; diff --git a/src/lib.rs b/src/lib.rs index 01c57e4..ba4049a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,11 @@ -pub mod api; -pub mod cache; -pub mod client; pub mod config; -pub mod helpers; +pub mod extension; +pub mod extensions; pub mod logger; pub mod middleware; +pub mod middlewares; pub mod server; -pub mod telemetry; +pub mod utils; #[cfg(test)] mod integration_tests; diff --git a/src/bin.rs b/src/main.rs similarity index 50% rename from src/bin.rs rename to src/main.rs index 4d3a41d..f924979 100644 --- a/src/bin.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ use opentelemetry::global::shutdown_tracer_provider; -use rand::{seq::SliceRandom, thread_rng}; -use subway::{client, config, logger::enable_logger, server, telemetry::setup_telemetry}; +use subway::{config, logger::enable_logger, server}; #[tokio::main] async fn main() -> anyhow::Result<()> { @@ -12,19 +11,11 @@ async fn main() -> anyhow::Result<()> { } }; - let _tracer = setup_telemetry(&config.telemetry)?; - enable_logger(); tracing::trace!("{:#?}", config); - let mut endpoints = config.endpoints.clone(); - endpoints.shuffle(&mut thread_rng()); - let client = client::Client::new(endpoints) - .await - .map_err(anyhow::Error::msg)?; - - let (addr, server) = server::start_server(&config, client).await?; + let (addr, server) = server::start_server(config).await?; tracing::info!("Server running at {addr}"); diff --git a/src/middleware/methods/call.rs b/src/middleware/methods/call.rs deleted file mode 100644 index 23bfd73..0000000 --- a/src/middleware/methods/call.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::sync::Arc; - -use async_trait::async_trait; -use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; - -use crate::{ - client::Client, - middleware::{Middleware, NextFn}, -}; - -#[derive(Debug, Default)] -pub struct Extra { - pub bypass_cache: bool, -} - -#[derive(Debug)] -pub struct CallRequest { - pub method: String, - pub params: Vec, - pub extra: Extra, -} - -impl CallRequest { - pub fn new(method: impl AsRef, params: Vec) -> Self { - Self { - method: method.as_ref().to_string(), - params, - extra: Extra::default(), - } - } -} - -pub struct UpstreamMiddleware { - client: Arc, -} - -impl UpstreamMiddleware { - pub fn new(client: Arc) -> Self { - Self { client } - } -} - -#[async_trait] -impl Middleware> for UpstreamMiddleware { - async fn call( - &self, - request: CallRequest, - _next: NextFn>, - ) -> Result { - self.client.request(&request.method, request.params).await - } -} diff --git a/src/middleware/methods/response.rs b/src/middleware/methods/response.rs deleted file mode 100644 index 63cff82..0000000 --- a/src/middleware/methods/response.rs +++ /dev/null @@ -1,25 +0,0 @@ -use async_trait::async_trait; -use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; - -use crate::middleware::{call::CallRequest, Middleware, NextFn}; - -pub struct ResponseMiddleware { - resp: JsonValue, -} - -impl ResponseMiddleware { - pub fn new(resp: JsonValue) -> Self { - Self { resp } - } -} - -#[async_trait] -impl Middleware> for ResponseMiddleware { - async fn call( - &self, - _request: CallRequest, - _next: NextFn>, - ) -> Result { - Ok(self.resp.clone()) - } -} diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index cf113f1..449534b 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -1,30 +1,52 @@ -use std::sync::Arc; - use async_trait::async_trait; use futures::{future::BoxFuture, FutureExt}; +use std::sync::Arc; -pub mod methods; -pub mod subscriptions; +pub use crate::{ + config::{RpcMethod, RpcSubscription}, + extension::ExtensionRegistry, + utils::{TypeRegistry, TypeRegistryRef}, +}; -pub use methods::*; -pub use subscriptions::*; +#[async_trait] +pub trait MiddlewareBuilder { + async fn build( + method: &Method, + extensions: &TypeRegistryRef, + ) -> Option>>; +} -type NextFn = Box BoxFuture<'static, Result> + Send + Sync>; +pub type NextFn = + Box BoxFuture<'static, Result> + Send + Sync>; #[async_trait] -pub trait Middleware: Send + Sync { - async fn call(&self, request: Request, next: NextFn) -> Result; +pub trait Middleware: Send + Sync { + async fn call( + &self, + request: Request, + context: TypeRegistry, + next: NextFn, + ) -> Result; } pub struct Middlewares { middlewares: Vec>>, - fallback: Arc BoxFuture<'static, Result> + Send + Sync>, + fallback: Arc BoxFuture<'static, Result> + Send + Sync>, +} + +impl Clone for Middlewares { + fn clone(&self) -> Self { + Self { + middlewares: self.middlewares.clone(), + fallback: self.fallback.clone(), + } + } } impl Middlewares { pub fn new( middlewares: Vec>>, - fallback: Arc BoxFuture<'static, Result> + Send + Sync>, + fallback: Arc BoxFuture<'static, Result> + Send + Sync>, ) -> Self { Self { middlewares, @@ -35,17 +57,18 @@ impl Middlewares { pub async fn call(&self, request: Request) -> Result { let iter = self.middlewares.iter().rev(); let fallback = self.fallback.clone(); - let mut next: Box BoxFuture<'static, Result> + Send + Sync> = - Box::new(move |request| (fallback)(request)); + let mut next: Box< + dyn FnOnce(Request, TypeRegistry) -> BoxFuture<'static, Result> + Send + Sync, + > = Box::new(move |request, context| (fallback)(request, context)); for middleware in iter { let middleware = middleware.clone(); let next2 = next; - next = Box::new(move |request| { - async move { middleware.call(request, next2).await }.boxed() + next = Box::new(move |request, context| { + async move { middleware.call(request, context, next2).await }.boxed() }); } - (next)(request).await + (next)(request, TypeRegistry::new()).await } } diff --git a/src/middleware/methods/block_tag.rs b/src/middlewares/methods/block_tag.rs similarity index 81% rename from src/middleware/methods/block_tag.rs rename to src/middlewares/methods/block_tag.rs index 7e2e21e..7228fab 100644 --- a/src/middleware/methods/block_tag.rs +++ b/src/middlewares/methods/block_tag.rs @@ -1,28 +1,61 @@ +use std::sync::Arc; + use async_trait::async_trait; use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; -use std::sync::Arc; use crate::{ - api::EthApi, - middleware::{call::CallRequest, Middleware, NextFn}, + extensions::api::EthApi, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod}, + middlewares::{CallRequest, CallResult}, + utils::{TypeRegistry, TypeRegistryRef}, }; +use super::cache::BypassCache; + pub struct BlockTagMiddleware { api: Arc, index: usize, } +#[async_trait] +impl MiddlewareBuilder for BlockTagMiddleware { + async fn build( + method: &RpcMethod, + extensions: &TypeRegistryRef, + ) -> Option>> { + let Some(index) = method + .params + .iter() + .position(|p| p.ty == "BlockTag" && p.inject) + else { + return None; + }; + + let eth_api = extensions + .read() + .await + .get::() + .expect("EthApi extension not found"); + + Some(Box::new(BlockTagMiddleware::new(eth_api, index))) + } +} + impl BlockTagMiddleware { pub fn new(api: Arc, index: usize) -> Self { Self { api, index } } - async fn replace(&self, mut request: CallRequest) -> CallRequest { + async fn replace( + &self, + mut request: CallRequest, + mut context: TypeRegistry, + ) -> (CallRequest, TypeRegistry) { let maybe_value = { if let Some(param) = request.params.get(self.index).cloned() { if !param.is_string() { // nothing to do here - return request; + return (request, context); } match param.as_str().unwrap_or_default() { "finalized" => { @@ -31,7 +64,7 @@ impl BlockTagMiddleware { Some(format!("0x{:x}", finalized_number).into()) } else { // cannot determine finalized - request.extra.bypass_cache = true; + context.insert(BypassCache(true)); None } } @@ -41,7 +74,7 @@ impl BlockTagMiddleware { } "earliest" => None, // no need to replace earliest because it's always going to be genesis "pending" | "safe" => { - request.extra.bypass_cache = true; + context.insert(BypassCache(true)); None } _ => None, @@ -61,7 +94,7 @@ impl BlockTagMiddleware { request.params.insert(self.index, value); } - request + (request, context) } } @@ -70,10 +103,11 @@ impl Middleware> for BlockTagMi async fn call( &self, request: CallRequest, + context: TypeRegistry, next: NextFn>, ) -> Result { - let request = self.replace(request).await; - next(request).await + let (request, context) = self.replace(request, context).await; + next(request, context).await } } @@ -81,10 +115,12 @@ impl Middleware> for BlockTagMi mod tests { use super::*; - use crate::api::EthApi; - use crate::client::mock::{run_sink_tasks, SinkTask}; - use crate::client::{mock::TestServerBuilder, Client}; use crate::config::MethodParam; + use crate::extensions::api::EthApi; + use crate::extensions::client::{ + mock::{run_sink_tasks, SinkTask, TestServerBuilder}, + Client, + }; use futures::FutureExt; use jsonrpsee::{server::ServerHandle, SubscriptionSink}; use serde_json::json; @@ -114,7 +150,7 @@ mod tests { let (addr, _server) = builder.build().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let api = EthApi::new(Arc::new(client), Duration::from_secs(100)); ( @@ -168,7 +204,8 @@ mod tests { middleware .call( CallRequest::new("state_getStorage", params.clone()), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, params); Ok(json!("0x1111")) @@ -238,7 +275,8 @@ mod tests { middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234"), json!("latest")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!("0x4321")]); Ok(json!("0x1111")) @@ -258,7 +296,8 @@ mod tests { "state_getStorage", vec![json!("0x1234"), json!("finalized")], ), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!("finalized")]); Ok(json!("0x1111")) @@ -281,7 +320,8 @@ mod tests { "state_getStorage", vec![json!("0x1234"), json!("finalized")], ), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!("0x5430")]); Ok(json!("0x1111")) @@ -298,7 +338,8 @@ mod tests { middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234"), json!("latest")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!("0x5432")]); Ok(json!("0x1111")) diff --git a/src/middleware/methods/cache.rs b/src/middlewares/methods/cache.rs similarity index 54% rename from src/middleware/methods/cache.rs rename to src/middlewares/methods/cache.rs index e0a5c3d..6a0bf1a 100644 --- a/src/middleware/methods/cache.rs +++ b/src/middlewares/methods/cache.rs @@ -1,14 +1,19 @@ +use std::num::NonZeroUsize; + use async_trait::async_trait; use blake2::Blake2b512; use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; use opentelemetry::trace::FutureExt; use crate::{ - cache::{Cache, CacheKey}, - helpers, - middleware::{call::CallRequest, Middleware, NextFn}, + extensions::cache::Cache as CacheExtension, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod}, + middlewares::{CallRequest, CallResult}, + utils::{new_cache, telemetry, Cache, CacheKey, TypeRegistry, TypeRegistryRef}, }; +pub struct BypassCache(pub bool); + pub struct CacheMiddleware { cache: Cache, } @@ -19,18 +24,50 @@ impl CacheMiddleware { } } -const TRACER: helpers::telemetry::Tracer = helpers::telemetry::Tracer::new("cache-middleware"); +#[async_trait] +impl MiddlewareBuilder for CacheMiddleware { + async fn build( + method: &RpcMethod, + extensions: &TypeRegistryRef, + ) -> Option>> { + let params = method.cache.as_ref()?; + if params.size == Some(0) { + return None; + } + let cache_ext = extensions + .read() + .await + .get::() + .expect("Cache extension not found"); + + let size = + NonZeroUsize::new(params.size.unwrap_or(cache_ext.config.default_size) as usize)?; + + let cache = new_cache( + size, + params + .ttl_seconds + .map(|s| std::time::Duration::from_secs(s as u64)), + ); + + Some(Box::new(Self::new(cache))) + } +} + +const TRACER: telemetry::Tracer = telemetry::Tracer::new("cache-middleware"); #[async_trait] impl Middleware> for CacheMiddleware { async fn call( &self, request: CallRequest, + context: TypeRegistry, next: NextFn>, ) -> Result { async move { - if request.extra.bypass_cache { - return next(request).await; + let bypass_cache = context.get::().map(|v| v.0).unwrap_or(false); + if bypass_cache { + return next(request, context).await; } let key = CacheKey::::new(&request.method, &request.params); @@ -39,7 +76,7 @@ impl Middleware> for CacheMiddl return Ok(value); } - let result = next(request).await; + let result = next(request, context).await; if let Ok(ref value) = result { // avoid caching null value because it usually means data not available @@ -62,7 +99,6 @@ impl Middleware> for CacheMiddl #[cfg(test)] mod tests { - use crate::cache::new_cache; use futures::FutureExt; use serde_json::json; use std::num::NonZeroUsize; @@ -77,7 +113,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { Ok(json!(1)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(1)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(1)); @@ -89,7 +126,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { panic!() }.boxed()), + Default::default(), + Box::new(move |_, _| async move { panic!() }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(1)); @@ -98,7 +136,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(22)]), - Box::new(move |_| async move { Ok(json!(2)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(2)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(2)); @@ -107,7 +146,8 @@ mod tests { let res = middleware .call( CallRequest::new("test2", vec![json!(22)]), - Box::new(move |_| async move { Ok(json!(3)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(3)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(3)); @@ -116,7 +156,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { panic!() }.boxed()), + Default::default(), + Box::new(move |_, _| async move { panic!() }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(1)); @@ -125,7 +166,8 @@ mod tests { let res = middleware .call( CallRequest::new("test2", vec![json!(33)]), - Box::new(move |_| async move { Ok(json!(4)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(4)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(4)); @@ -134,7 +176,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(22)]), - Box::new(move |_| async move { Ok(json!(5)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(5)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(5)); @@ -147,7 +190,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { Ok(JsonValue::Null) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(JsonValue::Null) }.boxed()), ) .await; assert_eq!(res.unwrap(), JsonValue::Null); @@ -159,7 +203,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { Ok(json!(2)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(2)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(2)); @@ -175,7 +220,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { Ok(json!(1)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(1)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(1)); @@ -187,7 +233,8 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { panic!() }.boxed()), + Default::default(), + Box::new(move |_, _| async move { panic!() }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(1)); @@ -199,9 +246,53 @@ mod tests { let res = middleware .call( CallRequest::new("test", vec![json!(11)]), - Box::new(move |_| async move { Ok(json!(2)) }.boxed()), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(2)) }.boxed()), + ) + .await; + assert_eq!(res.unwrap(), json!(2)); + } + + #[tokio::test] + async fn bypass_cache() { + let middleware = CacheMiddleware::new(Cache::new(3)); + + let res = middleware + .call( + CallRequest::new("test", vec![json!(11)]), + Default::default(), + Box::new(move |_, _| async move { Ok(json!(1)) }.boxed()), + ) + .await; + assert_eq!(res.unwrap(), json!(1)); + + // wait for cache write + tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; + + let mut context = TypeRegistry::new(); + context.insert(BypassCache(true)); + + // bypass cache + let res = middleware + .call( + CallRequest::new("test", vec![json!(11)]), + context, + Box::new(move |_, _| async move { Ok(json!(2)) }.boxed()), ) .await; assert_eq!(res.unwrap(), json!(2)); + + let mut context = TypeRegistry::new(); + context.insert(BypassCache(false)); + + // do not bypass cache, value from bypass cache request is not cached + let res = middleware + .call( + CallRequest::new("test", vec![json!(11)]), + context, + Box::new(move |_, _| async move { panic!() }.boxed()), + ) + .await; + assert_eq!(res.unwrap(), json!(1)); } } diff --git a/src/middleware/methods/inject_params.rs b/src/middlewares/methods/inject_params.rs similarity index 87% rename from src/middleware/methods/inject_params.rs rename to src/middlewares/methods/inject_params.rs index d874a9c..3dde78d 100644 --- a/src/middleware/methods/inject_params.rs +++ b/src/middlewares/methods/inject_params.rs @@ -3,10 +3,12 @@ use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; use std::sync::Arc; use crate::{ - api::{SubstrateApi, ValueHandle}, config::MethodParam, - helpers::errors, - middleware::{call::CallRequest, Middleware, NextFn}, + extensions::api::{SubstrateApi, ValueHandle}, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod}, + middlewares::{CallRequest, CallResult}, + utils::errors, + utils::{TypeRegistry, TypeRegistryRef}, }; pub enum InjectType { @@ -20,6 +22,42 @@ pub struct InjectParamsMiddleware { params: Vec, } +fn inject_type(params: &[MethodParam]) -> Option { + let maybe_block_num = params + .iter() + .position(|p| p.inject && p.ty == "BlockNumber"); + if let Some(block_num) = maybe_block_num { + return Some(InjectType::BlockNumberAt(block_num)); + } + + let maybe_block_hash = params.iter().position(|p| p.inject && p.ty == "BlockHash"); + if let Some(block_hash) = maybe_block_hash { + return Some(InjectType::BlockHashAt(block_hash)); + } + + None +} + +#[async_trait] +impl MiddlewareBuilder for InjectParamsMiddleware { + async fn build( + method: &RpcMethod, + extensions: &TypeRegistryRef, + ) -> Option>> { + let Some(inject_type) = inject_type(&method.params) else { + return None; + }; + + let api = extensions + .read() + .await + .get::() + .expect("SubstrateApi extension not found"); + + Some(Box::new(Self::new(api, inject_type, method.params.clone()))) + } +} + impl InjectParamsMiddleware { pub fn new(api: Arc, inject: InjectType, params: Vec) -> Self { Self { @@ -58,34 +96,19 @@ impl InjectParamsMiddleware { } } -pub fn inject(params: &[MethodParam]) -> Option { - let maybe_block_num = params - .iter() - .position(|p| p.inject && p.ty == "BlockNumber"); - if let Some(block_num) = maybe_block_num { - return Some(InjectType::BlockNumberAt(block_num)); - } - - let maybe_block_hash = params.iter().position(|p| p.inject && p.ty == "BlockHash"); - if let Some(block_hash) = maybe_block_hash { - return Some(InjectType::BlockHashAt(block_hash)); - } - - None -} - #[async_trait] impl Middleware> for InjectParamsMiddleware { async fn call( &self, mut request: CallRequest, + context: TypeRegistry, next: NextFn>, ) -> Result { let idx = self.get_index(); match request.params.len() { len if len == idx + 1 => { // full params with current block - return next(request).await; + return next(request, context).await; } len if len <= idx => { // without current block @@ -108,11 +131,11 @@ impl Middleware> for InjectPara } request.params.push(to_inject); - return next(request).await; + return next(request, context).await; } _ => { // unexpected number of params - next(request).await + next(request, context).await } } } @@ -122,8 +145,8 @@ impl Middleware> for InjectPara mod tests { use super::*; - use crate::api::SubstrateApi; - use crate::client::{mock::TestServerBuilder, Client}; + use crate::extensions::api::SubstrateApi; + use crate::extensions::client::{mock::TestServerBuilder, Client}; use futures::FutureExt; use jsonrpsee::{server::ServerHandle, SubscriptionMessage, SubscriptionSink}; use serde_json::json; @@ -157,7 +180,7 @@ mod tests { let (addr, _server) = builder.build().await; - let client = Client::new(&[format!("ws://{addr}")]).await.unwrap(); + let client = Client::new([format!("ws://{addr}")]).unwrap(); let api = SubstrateApi::new(Arc::new(client), Duration::from_secs(100)); ( @@ -221,7 +244,8 @@ mod tests { let result = middleware .call( CallRequest::new("state_getStorage", params.clone()), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, params); Ok(json!("0x1111")) @@ -257,7 +281,8 @@ mod tests { let result = middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!("0xabcd")]); Ok(json!("0x1111")) @@ -299,7 +324,8 @@ mod tests { let result = middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!( req.params, @@ -344,7 +370,8 @@ mod tests { let result = middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!( req.params, @@ -387,7 +414,8 @@ mod tests { let result = middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!(0x4321)]); Ok(json!("0x1111")) @@ -415,7 +443,8 @@ mod tests { let result2 = middleware .call( CallRequest::new("state_getStorage", vec![json!("0x1234")]), - Box::new(move |req: CallRequest| { + Default::default(), + Box::new(move |req: CallRequest, _| { async move { assert_eq!(req.params, vec![json!("0x1234"), json!(0x5432)]); Ok(json!("0x1111")) diff --git a/src/middleware/methods/mod.rs b/src/middlewares/methods/mod.rs similarity index 80% rename from src/middleware/methods/mod.rs rename to src/middlewares/methods/mod.rs index cca3ce1..21816df 100644 --- a/src/middleware/methods/mod.rs +++ b/src/middlewares/methods/mod.rs @@ -1,5 +1,5 @@ pub mod block_tag; pub mod cache; -pub mod call; pub mod inject_params; pub mod response; +pub mod upstream; diff --git a/src/middlewares/methods/response.rs b/src/middlewares/methods/response.rs new file mode 100644 index 0000000..140c57a --- /dev/null +++ b/src/middlewares/methods/response.rs @@ -0,0 +1,43 @@ +use async_trait::async_trait; +use jsonrpsee::core::JsonValue; + +use crate::{ + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod}, + middlewares::{CallRequest, CallResult}, + utils::{TypeRegistry, TypeRegistryRef}, +}; + +pub struct ResponseMiddleware { + resp: JsonValue, +} + +impl ResponseMiddleware { + pub fn new(resp: JsonValue) -> Self { + Self { resp } + } +} + +#[async_trait] +impl MiddlewareBuilder for ResponseMiddleware { + async fn build( + method: &RpcMethod, + _extensions: &TypeRegistryRef, + ) -> Option>> { + method.response.as_ref().map(|resp| { + Box::new(ResponseMiddleware::new(resp.clone())) + as Box> + }) + } +} + +#[async_trait] +impl Middleware for ResponseMiddleware { + async fn call( + &self, + _request: CallRequest, + _context: TypeRegistry, + _next: NextFn, + ) -> CallResult { + Ok(self.resp.clone()) + } +} diff --git a/src/middlewares/methods/upstream.rs b/src/middlewares/methods/upstream.rs new file mode 100644 index 0000000..4d4d6ab --- /dev/null +++ b/src/middlewares/methods/upstream.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned}; + +use crate::{ + extensions::client::Client, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod}, + middlewares::{CallRequest, CallResult}, + utils::{TypeRegistry, TypeRegistryRef}, +}; + +pub struct UpstreamMiddleware { + client: Arc, +} + +impl UpstreamMiddleware { + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +#[async_trait] +impl MiddlewareBuilder for UpstreamMiddleware { + async fn build( + _method: &RpcMethod, + extensions: &TypeRegistryRef, + ) -> Option>> { + let client = extensions + .read() + .await + .get::() + .expect("Client extension not found"); + Some(Box::new(UpstreamMiddleware::new(client))) + } +} + +#[async_trait] +impl Middleware> for UpstreamMiddleware { + async fn call( + &self, + request: CallRequest, + _context: TypeRegistry, + _next: NextFn>, + ) -> Result { + self.client.request(&request.method, request.params).await + } +} diff --git a/src/middlewares/mod.rs b/src/middlewares/mod.rs new file mode 100644 index 0000000..57f07f4 --- /dev/null +++ b/src/middlewares/mod.rs @@ -0,0 +1,74 @@ +use jsonrpsee::{ + core::{JsonValue, StringError}, + types::ErrorObjectOwned, + PendingSubscriptionSink, +}; + +use crate::{ + config::{RpcMethod, RpcSubscription}, + middleware::{Middleware, MiddlewareBuilder}, + utils::TypeRegistryRef, +}; + +pub mod methods; +pub mod subscriptions; + +#[derive(Debug)] +pub struct CallRequest { + pub method: String, + pub params: Vec, +} + +impl CallRequest { + pub fn new(method: impl ToString, params: Vec) -> Self { + Self { + method: method.to_string(), + params, + } + } +} + +pub type CallResult = Result; + +pub async fn create_method_middleware( + name: &str, + method: &RpcMethod, + extensions: &TypeRegistryRef, +) -> Option>> { + use methods::*; + + match name { + "response" => response::ResponseMiddleware::build(method, extensions).await, + "upstream" => upstream::UpstreamMiddleware::build(method, extensions).await, + "cache" => cache::CacheMiddleware::build(method, extensions).await, + "block_tag" => block_tag::BlockTagMiddleware::build(method, extensions).await, + "inject_params" => inject_params::InjectParamsMiddleware::build(method, extensions).await, + _ => panic!("Unknown method middleware: {}", name), + } +} + +#[derive(Debug)] +pub struct SubscriptionRequest { + pub subscribe: String, + pub params: Vec, + pub unsubscribe: String, + pub sink: PendingSubscriptionSink, +} + +pub type SubscriptionResult = Result<(), StringError>; + +pub async fn create_subscription_middleware( + name: &str, + method: &RpcSubscription, + extensions: &TypeRegistryRef, +) -> Option>> { + use subscriptions::*; + + match name { + "upstream" => upstream::UpstreamMiddleware::build(method, extensions).await, + "merge_subscription" => { + merge_subscription::MergeSubscriptionMiddleware::build(method, extensions).await + } + _ => panic!("Unknown subscription middleware: {}", name), + } +} diff --git a/src/middleware/subscriptions/merge_subscription.rs b/src/middlewares/subscriptions/merge_subscription.rs similarity index 89% rename from src/middleware/subscriptions/merge_subscription.rs rename to src/middlewares/subscriptions/merge_subscription.rs index f9411e8..27dc8d0 100644 --- a/src/middleware/subscriptions/merge_subscription.rs +++ b/src/middlewares/subscriptions/merge_subscription.rs @@ -1,3 +1,9 @@ +use std::{ + collections::{BTreeSet, HashMap}, + sync::Arc, + time::Duration, +}; + use async_trait::async_trait; use blake2::Blake2b512; use jsonrpsee::{ @@ -5,18 +11,14 @@ use jsonrpsee::{ SubscriptionMessage, }; use serde::{Deserialize, Serialize}; -use std::{ - collections::{BTreeSet, HashMap}, - sync::Arc, - time::Duration, -}; use tokio::sync::{broadcast, RwLock}; use crate::{ - cache::CacheKey, - client::Client, config::MergeStrategy, - middleware::{subscription::SubscriptionRequest, Middleware, NextFn}, + extensions::{client::Client, merge_subscription::MergeSubscription}, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcSubscription}, + middlewares::{SubscriptionRequest, SubscriptionResult}, + utils::{CacheKey, TypeRegistry, TypeRegistryRef}, }; #[derive(Serialize, Deserialize, Debug)] @@ -188,11 +190,39 @@ impl MergeSubscriptionMiddleware { } } +#[async_trait] +impl MiddlewareBuilder + for MergeSubscriptionMiddleware +{ + async fn build( + method: &RpcSubscription, + extensions: &TypeRegistryRef, + ) -> Option>> { + let Some(merge_strategy) = method.merge_strategy else { + return None; + }; + + let ext = extensions.read().await; + let client = ext.get::().expect("Client extension not found"); + + let merge_subscription = ext + .get::() + .expect("MergeSubscription extension not found"); + + Some(Box::new(MergeSubscriptionMiddleware::new( + client, + merge_strategy, + merge_subscription.config.keep_alive_seconds, + ))) + } +} + #[async_trait] impl Middleware> for MergeSubscriptionMiddleware { async fn call( &self, request: SubscriptionRequest, + _context: TypeRegistry, _next: NextFn>, ) -> Result<(), StringError> { let key = CacheKey::new(&request.subscribe, &request.params); diff --git a/src/middleware/subscriptions/mod.rs b/src/middlewares/subscriptions/mod.rs similarity index 56% rename from src/middleware/subscriptions/mod.rs rename to src/middlewares/subscriptions/mod.rs index dfd290f..4399965 100644 --- a/src/middleware/subscriptions/mod.rs +++ b/src/middlewares/subscriptions/mod.rs @@ -1,2 +1,2 @@ pub mod merge_subscription; -pub mod subscription; +pub mod upstream; diff --git a/src/middleware/subscriptions/subscription.rs b/src/middlewares/subscriptions/upstream.rs similarity index 57% rename from src/middleware/subscriptions/subscription.rs rename to src/middlewares/subscriptions/upstream.rs index 8dc83e3..7705254 100644 --- a/src/middleware/subscriptions/subscription.rs +++ b/src/middlewares/subscriptions/upstream.rs @@ -1,22 +1,15 @@ -use async_trait::async_trait; -use jsonrpsee::{ - core::{JsonValue, StringError}, - PendingSubscriptionSink, SubscriptionMessage, -}; use std::sync::Arc; +use async_trait::async_trait; +use jsonrpsee::SubscriptionMessage; + use crate::{ - client::Client, - middleware::{Middleware, NextFn}, + extensions::client::Client, + middleware::{Middleware, MiddlewareBuilder, NextFn, RpcSubscription}, + middlewares::{SubscriptionRequest, SubscriptionResult}, + utils::{TypeRegistry, TypeRegistryRef}, }; -pub struct SubscriptionRequest { - pub subscribe: String, - pub params: Vec, - pub unsubscribe: String, - pub sink: PendingSubscriptionSink, -} - pub struct UpstreamMiddleware { client: Arc, } @@ -28,12 +21,30 @@ impl UpstreamMiddleware { } #[async_trait] -impl Middleware> for UpstreamMiddleware { +impl MiddlewareBuilder + for UpstreamMiddleware +{ + async fn build( + _method: &RpcSubscription, + extensions: &TypeRegistryRef, + ) -> Option>> { + let client = extensions + .read() + .await + .get::() + .expect("Client extension not found"); + Some(Box::new(UpstreamMiddleware::new(client))) + } +} + +#[async_trait] +impl Middleware for UpstreamMiddleware { async fn call( &self, request: SubscriptionRequest, - _next: NextFn>, - ) -> Result<(), StringError> { + _context: TypeRegistry, + _next: NextFn, + ) -> SubscriptionResult { let sink = request.sink; let mut sub = self diff --git a/src/server.rs b/src/server.rs index c01960e..9110945 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,29 +1,22 @@ +use std::{net::SocketAddr, sync::Arc}; + use futures::FutureExt; -use jsonrpsee::core::JsonValue; -use jsonrpsee::server::middleware::proxy_get_request::ProxyGetRequestLayer; -use jsonrpsee::server::{RandomStringIdProvider, RpcModule, ServerBuilder, ServerHandle}; -use jsonrpsee::types::ErrorObjectOwned; +use jsonrpsee::{ + core::JsonValue, + server::{RpcModule, ServerHandle}, + types::ErrorObjectOwned, +}; use opentelemetry::trace::FutureExt as _; use serde_json::json; -use std::time::Duration; -use std::{net::SocketAddr, sync::Arc}; -use crate::cache::new_cache; -use crate::helpers::{self, errors}; -use crate::middleware::response::ResponseMiddleware; use crate::{ - api::{EthApi, SubstrateApi}, - client::Client, config::Config, - middleware::{ - block_tag::BlockTagMiddleware, - cache::CacheMiddleware, - call::{self, CallRequest}, - inject_params::{inject, InjectParamsMiddleware}, - merge_subscription::MergeSubscriptionMiddleware, - subscription::{self, SubscriptionRequest}, - Middleware, Middlewares, + extensions::server::Server, + middleware::Middlewares, + middlewares::{ + create_method_middleware, create_subscription_middleware, CallRequest, SubscriptionRequest, }, + utils::{errors, telemetry}, }; // TODO: https://github.com/paritytech/jsonrpsee/issues/985 @@ -31,198 +24,150 @@ fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) } -pub async fn start_server( - config: &Config, - client: Client, -) -> anyhow::Result<(SocketAddr, ServerHandle)> { - let service_builder = - tower::ServiceBuilder::new().option_layer(config.health.as_ref().map(|h| { - ProxyGetRequestLayer::new(h.path.clone(), h.method.clone()) - .expect("Invalid health config") - })); - - let server = ServerBuilder::default() - .set_middleware(service_builder) - .max_connections(config.server.max_connections) - .set_id_provider(RandomStringIdProvider::new(16)) - .build((config.server.listen_address.as_str(), config.server.port)) - .await?; - - let mut module = RpcModule::new(()); - - let tracer = helpers::telemetry::Tracer::new("server"); +pub async fn start_server(config: Config) -> anyhow::Result<(SocketAddr, ServerHandle)> { + let Config { + extensions, + middlewares, + rpcs, + } = config; + + let extensions = extensions + .create_registry() + .await + .expect("Failed to create extensions registry"); + + let server = extensions + .read() + .await + .get::() + .expect("Server extension not found"); + + let res = server + .create_server(move || async move { + let mut module = RpcModule::new(()); + + let tracer = telemetry::Tracer::new("server"); + + for method in rpcs.methods { + let mut method_middlewares: Vec> = vec![]; + + for middleware_name in &middlewares.methods { + if let Some(middleware) = + create_method_middleware(middleware_name, &method, &extensions).await + { + method_middlewares.push(middleware.into()); + } + } - let client = Arc::new(client); + let method_middlewares = Middlewares::new( + method_middlewares, + Arc::new(|_, _| async { Err(errors::failed("Bad configuration")) }.boxed()), + ); + + let method_name = string_to_static_str(method.method.clone()); + + module.register_async_method(method_name, move |params, _| { + let method_middlewares = method_middlewares.clone(); + + async move { + let cx = tracer.context(method_name); + + let parsed = params.parse::()?; + let params = if parsed == JsonValue::Null { + vec![] + } else { + parsed + .as_array() + .ok_or_else(|| errors::invalid_params(""))? + .to_owned() + }; + method_middlewares + .call(CallRequest::new(method_name, params)) + .with_context(cx) + .await + } + })?; + } - let mut sub_api: Option> = None; - let mut eth_api: Option> = None; + for subscription in rpcs.subscriptions { + let subscribe_name = string_to_static_str(subscription.subscribe.clone()); + let unsubscribe_name = string_to_static_str(subscription.unsubscribe.clone()); + let name = string_to_static_str(subscription.name.clone()); - let mut get_sub_api = || { - if sub_api.is_none() { - sub_api = Some(Arc::new(SubstrateApi::new( - client.clone(), - Duration::from_secs(config.stale_timeout_seconds), - ))); - } - sub_api.as_ref().unwrap().clone() - }; + let mut subscription_middlewares: Vec> = vec![]; - let mut get_eth_api = || { - if eth_api.is_none() { - eth_api = Some(Arc::new(EthApi::new( - client.clone(), - Duration::from_secs(config.stale_timeout_seconds), - ))); - } - eth_api.as_ref().unwrap().clone() - }; + for middleware_name in &middlewares.subscriptions { + if let Some(middleware) = + create_subscription_middleware(middleware_name, &subscription, &extensions) + .await + { + subscription_middlewares.push(middleware.into()); + } + } - let upstream = Arc::new(call::UpstreamMiddleware::new(client.clone())); - - for method in &config.rpcs.methods { - let mut list: Vec>> = vec![]; - - if let Some(index) = method - .params - .iter() - .position(|p| p.ty == "BlockTag" && p.inject) - { - list.push(Arc::new(BlockTagMiddleware::new(get_eth_api(), index))) - } - - if let Some(inject_type) = inject(&method.params) { - list.push(Arc::new(InjectParamsMiddleware::new( - get_sub_api(), - inject_type, - method.params.clone(), - ))); - } - - if let Some(ref resp) = method.response { - list.push(Arc::new(ResponseMiddleware::new(resp.clone()))); - } - - if let Some(cache_size) = method.cache_size() { - // each method has it's own cache - let cache = new_cache( - cache_size, - method - .cache_ttl_seconds - .or(config.cache_ttl_seconds) - .map(Duration::from_secs), - ); - list.push(Arc::new(CacheMiddleware::new(cache))); - } - list.push(upstream.clone()); - - let middlewares = Arc::new(Middlewares::new( - list, - Arc::new(|_| async { Err(errors::failed("Bad configuration")) }.boxed()), - )); - - let method_name = string_to_static_str(method.method.clone()); - module.register_async_method(method_name, move |params, _| { - let middlewares = middlewares.clone(); - - async move { - let cx = tracer.context(method_name); - - let parsed = params.parse::()?; - let params = if parsed == JsonValue::Null { - vec![] - } else { - parsed - .as_array() - .ok_or_else(|| errors::invalid_params(""))? - .to_owned() - }; - middlewares - .call(CallRequest::new(method_name, params)) - .with_context(cx) - .await + let subscription_middlewares = Middlewares::new( + subscription_middlewares, + Arc::new(|_, _| async { Err("Bad configuration".into()) }.boxed()), + ); + + module.register_subscription( + subscribe_name, + name, + unsubscribe_name, + move |params, sink, _| { + let subscription_middlewares = subscription_middlewares.clone(); + + async move { + let cx = tracer.context(name); + + let parsed = params.parse::()?; + let params = if parsed == JsonValue::Null { + vec![] + } else { + parsed + .as_array() + .ok_or_else(|| errors::invalid_params(""))? + .to_owned() + }; + subscription_middlewares + .call(SubscriptionRequest { + subscribe: subscribe_name.into(), + params, + unsubscribe: unsubscribe_name.into(), + sink, + }) + .with_context(cx) + .await + } + }, + )?; } - })?; - } - let upstream = Arc::new(subscription::UpstreamMiddleware::new(client.clone())); - - for subscription in &config.rpcs.subscriptions { - let subscribe_name = string_to_static_str(subscription.subscribe.clone()); - let unsubscribe_name = string_to_static_str(subscription.unsubscribe.clone()); - let name = string_to_static_str(subscription.name.clone()); - - let mut list: Vec>> = vec![]; - match subscription.merge_strategy { - Some(merge_strategy) => list.push(Arc::new(MergeSubscriptionMiddleware::new( - client.clone(), - merge_strategy, - config.merge_subscription_keep_alive_seconds, - ))), - None => list.push(upstream.clone()), - }; - - let middlewares = Arc::new(Middlewares::new( - list, - Arc::new(|_| async { Err("Bad configuration".into()) }.boxed()), - )); - - module.register_subscription( - subscribe_name, - name, - unsubscribe_name, - move |params, sink, _| { - let middlewares = middlewares.clone(); - - async move { - let cx = tracer.context(name); - - let parsed = params.parse::()?; - let params = if parsed == JsonValue::Null { - vec![] - } else { - parsed - .as_array() - .ok_or_else(|| errors::invalid_params(""))? - .to_owned() - }; - middlewares - .call(SubscriptionRequest { - subscribe: subscribe_name.into(), - params, - unsubscribe: unsubscribe_name.into(), - sink, - }) - .with_context(cx) - .await - } - }, - )?; - } - - for (alias_old, alias_new) in &config.rpcs.aliases { - let alias_old = string_to_static_str(alias_old.clone()); - let alias_new = string_to_static_str(alias_new.clone()); - module.register_alias(alias_new, alias_old)?; - } + for (alias_old, alias_new) in rpcs.aliases { + let alias_old = string_to_static_str(alias_old); + let alias_new = string_to_static_str(alias_new); + module.register_alias(alias_new, alias_old)?; + } - let mut rpc_methods = module - .method_names() - .map(|x| x.to_owned()) - .collect::>(); + let mut rpc_methods = module + .method_names() + .map(|x| x.to_owned()) + .collect::>(); - rpc_methods.sort(); + rpc_methods.sort(); - module.register_method("rpc_methods", move |_, _| { - Ok::(json!({ - "version": 1, - "methods": rpc_methods - })) - })?; + module.register_method("rpc_methods", move |_, _| { + Ok::(json!({ + "version": 1, + "methods": rpc_methods + })) + })?; - let addr = server.local_addr()?; - let server = server.start(module)?; + Ok(module) + }) + .await?; - Ok((addr, server)) + Ok(res) } #[cfg(test)] @@ -230,13 +175,17 @@ mod tests { use jsonrpsee::{ core::client::ClientT, rpc_params, + server::ServerBuilder, server::ServerHandle, ws_client::{WsClient, WsClientBuilder}, RpcModule, }; use super::*; - use crate::config::{RpcDefinitions, RpcMethod, ServerConfig}; + use crate::{ + config::{MiddlewaresConfig, RpcDefinitions, RpcMethod}, + extensions::{client::ClientConfig, server::ServerConfig, ExtensionsConfig}, + }; const PHO: &str = "pho"; const BAR: &str = "bar"; @@ -244,31 +193,35 @@ mod tests { async fn server() -> (String, ServerHandle) { let config = Config { - endpoints: vec![format!("ws://{}", WS_SERVER_ENDPOINT)], - stale_timeout_seconds: 60, - cache_ttl_seconds: None, - merge_subscription_keep_alive_seconds: None, - server: ServerConfig { - listen_address: "127.0.0.1".to_string(), - port: 9944, - max_connections: 1024, + extensions: ExtensionsConfig { + client: Some(ClientConfig { + endpoints: vec![format!("ws://{}", WS_SERVER_ENDPOINT)], + shuffle_endpoints: false, + }), + server: Some(ServerConfig { + listen_address: "127.0.0.1".to_string(), + port: 9944, + max_connections: 1024, + health: None, + }), + ..Default::default() + }, + middlewares: MiddlewaresConfig { + methods: vec!["upstream".to_string()], + subscriptions: vec![], }, rpcs: RpcDefinitions { methods: vec![RpcMethod { method: PHO.to_string(), params: vec![], - cache: 0, - cache_ttl_seconds: None, + cache: None, response: None, }], subscriptions: vec![], aliases: vec![], }, - telemetry: None, - health: None, }; - let client = Client::new(&config.endpoints).await.unwrap(); - let (addr, server) = start_server(&config, client).await.unwrap(); + let (addr, server) = start_server(config).await.unwrap(); (format!("ws://{}", addr), server) } diff --git a/src/cache.rs b/src/utils/cache.rs similarity index 100% rename from src/cache.rs rename to src/utils/cache.rs diff --git a/src/helpers.rs b/src/utils/mod.rs similarity index 95% rename from src/helpers.rs rename to src/utils/mod.rs index 519bff0..bb6daba 100644 --- a/src/helpers.rs +++ b/src/utils/mod.rs @@ -1,3 +1,9 @@ +mod cache; +mod type_registry; + +pub use cache::*; +pub use type_registry::*; + pub mod errors { use jsonrpsee::types::{ error::{ diff --git a/src/utils/type_registry.rs b/src/utils/type_registry.rs new file mode 100644 index 0000000..7acee86 --- /dev/null +++ b/src/utils/type_registry.rs @@ -0,0 +1,74 @@ +// taken from https://github.com/hyperium/http/blob/master/src/extensions.rs. + +use std::{ + any::{Any, TypeId}, + collections::HashMap, + hash::{BuildHasherDefault, Hasher}, + sync::Arc, +}; +use tokio::sync::RwLock; + +pub type AnyMap = HashMap, BuildHasherDefault>; + +/// With TypeIds as keys, there's no need to hash them. They are already hashes +/// themselves, coming from the compiler. The IdHasher holds the u64 of +/// the TypeId, and then returns it, instead of doing any bit fiddling. +#[derive(Default, Debug)] +pub struct IdHasher(u64); + +impl Hasher for IdHasher { + fn write(&mut self, _: &[u8]) { + unreachable!("TypeId calls write_u64"); + } + + #[inline] + fn write_u64(&mut self, id: u64) { + self.0 = id; + } + + #[inline] + fn finish(&self) -> u64 { + self.0 + } +} + +#[derive(Default, Debug)] +pub struct TypeRegistry { + map: AnyMap, +} + +impl TypeRegistry { + pub fn new() -> TypeRegistry { + TypeRegistry { + map: AnyMap::default(), + } + } + + pub fn has(&self) -> bool { + self.map.contains_key(&TypeId::of::()) + } + + pub fn insert(&mut self, val: T) { + self.map.insert(TypeId::of::(), Arc::new(val)); + } + + pub fn insert_raw(&mut self, val: Arc) { + self.map.insert(val.as_ref().type_id(), val); + } + + pub fn get(&self) -> Option> { + self.map + .get(&TypeId::of::()) + .and_then(|boxed| boxed.clone().downcast().ok()) + } + + pub fn remove(&mut self) { + self.map.remove(&TypeId::of::()); + } + + pub fn clear(&mut self) { + self.map.clear(); + } +} + +pub type TypeRegistryRef = Arc>;