diff --git a/.woodpecker.yml b/.woodpecker.yml index 2fed1d2..197b8b3 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -2,6 +2,8 @@ steps: backend: image: rust commands: + - apt update + - apt-get install -y --no-install-recommends protobuf-compiler - cargo build # - make migrate # - make diff --git a/Cargo.lock b/Cargo.lock index 63f8203..393e1e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5" dependencies = [ "actix-rt", "actix_derive", - "bitflags", + "bitflags 1.3.2", "bytes", "crossbeam-channel", "futures-core", @@ -26,214 +26,27 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "actix-codec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-http" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "ahash 0.8.3", - "base64 0.21.1", - "bitflags", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "futures-core", - "h2", - "http", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd", -] - [[package]] name = "actix-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 1.0.109", -] - -[[package]] -name = "actix-router" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" -dependencies = [ - "bytestring", - "http", - "regex", - "serde 1.0.163", - "tracing", + "syn 2.0.16", ] [[package]] name = "actix-rt" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" dependencies = [ "actix-macros", "futures-core", "tokio", ] -[[package]] -name = "actix-server" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "num_cpus", - "socket2", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" -dependencies = [ - "futures-core", - "paste", - "pin-project-lite", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] - -[[package]] -name = "actix-web" -version = "4.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3cb42f9566ab176e1ef0b8b3a896529062b4efc6be0123046095914c4c1c96" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "ahash 0.7.6", - "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "futures-core", - "futures-util", - "http", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite", - "regex", - "serde 1.0.163", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2", - "time", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2262160a7ae29e3415554a3f1fc04c764b1540c116aa524683208078b7a75bc9" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "actix-web-codegen-const-routes" -version = "0.1.0" -source = "git+https://github.com/realaravinth/actix-web-codegen-const-routes?tag=0.1.0#1cc9b8dbaaef4b3634dabbf537f313200dd91bd9" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "actix-web-httpauth" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dda62cf04bc3a9ad2ea8f314f721951cfdb4cdacec4e984d20e77c7bb170991" -dependencies = [ - "actix-utils", - "actix-web", - "base64 0.13.1", - "futures-core", - "futures-util", - "log", - "pin-project-lite", -] - [[package]] name = "actix_derive" version = "0.6.0" @@ -245,35 +58,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" version = "1.0.1" @@ -283,21 +67,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "anstream" version = "0.3.2" @@ -374,6 +143,28 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] + [[package]] name = "async-trait" version = "0.1.68" @@ -402,6 +193,51 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde 1.0.163", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "base64" version = "0.13.1" @@ -429,6 +265,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "block-buffer" version = "0.10.4" @@ -438,33 +280,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "brotli" -version = "3.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - [[package]] name = "byte-unit" version = "4.0.19" @@ -487,24 +302,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" -[[package]] -name = "bytestring" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae" -dependencies = [ - "bytes", -] - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" -dependencies = [ - "jobserver", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -530,7 +327,7 @@ checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", - "bitflags", + "bitflags 1.3.2", "clap_lex", "strsim", ] @@ -595,33 +392,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - [[package]] name = "cpufeatures" version = "0.2.7" @@ -637,15 +407,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff" -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -716,10 +477,8 @@ version = "0.1.0" dependencies = [ "actix", "actix-rt", - "actix-web", - "actix-web-codegen-const-routes", - "actix-web-httpauth", "anyhow", + "async-stream", "async-trait", "base64 0.13.1", "byteorder", @@ -733,10 +492,13 @@ dependencies = [ "maplit", "openraft", "pretty_env_logger 0.4.0", - "reqwest", + "prost", "serde 1.0.163", "serde_json", "tokio", + "tokio-stream", + "tonic", + "tonic-build", "tracing", "tracing-subscriber", "url", @@ -829,13 +591,10 @@ dependencies = [ ] [[package]] -name = "encoding_rs" -version = "0.8.32" +name = "either" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "env_logger" @@ -864,24 +623,19 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -894,14 +648,10 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.0.26" +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" -dependencies = [ - "crc32fast", - "miniz_oxide", -] +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "fnv" @@ -909,21 +659,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.1.0" @@ -1055,7 +790,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -1068,6 +803,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.4.1" @@ -1098,6 +839,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.9" @@ -1172,16 +922,15 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-timeout" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "bytes", "hyper", - "native-tls", + "pin-project-lite", "tokio", - "tokio-native-tls", + "tokio-io-timeout", ] [[package]] @@ -1207,7 +956,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", ] [[package]] @@ -1230,12 +989,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ipnet" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" - [[package]] name = "is-terminal" version = "0.4.7" @@ -1244,40 +997,25 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", + "rustix 0.37.19", "windows-sys 0.48.0", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - [[package]] name = "lazy_static" version = "1.4.0" @@ -1291,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "cfg-if", "ryu", "static_assertions", @@ -1299,9 +1037,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libmcaptcha" @@ -1336,22 +1074,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] -name = "local-channel" -version = "0.1.3" +name = "linux-raw-sys" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" -dependencies = [ - "futures-core", - "futures-sink", - "futures-util", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -1387,6 +1113,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "mcaptcha_pow_sha256" version = "0.4.0" @@ -1412,15 +1144,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - [[package]] name = "mio" version = "0.8.6" @@ -1434,22 +1157,10 @@ dependencies = [ ] [[package]] -name = "native-tls" -version = "0.2.11" +name = "multimap" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "nom" @@ -1597,50 +1308,6 @@ dependencies = [ "tracing-futures", ] -[[package]] -name = "openssl" -version = "0.10.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -1670,18 +1337,22 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "paste" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" - [[package]] name = "percent-encoding" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.1.0", +] + [[package]] name = "pin-project" version = "1.1.0" @@ -1714,12 +1385,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1746,6 +1411,16 @@ dependencies = [ "log", ] +[[package]] +name = "prettyplease" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" +dependencies = [ + "proc-macro2", + "syn 2.0.16", +] + [[package]] name = "proc-macro2" version = "1.0.58" @@ -1755,6 +1430,60 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +dependencies = [ + "bytes", + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.16", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.16", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1844,7 +1573,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1853,7 +1582,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1888,43 +1617,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.1", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde 1.0.163", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - [[package]] name = "rust-ini" version = "0.13.0" @@ -1946,29 +1638,39 @@ version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.8", "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.12", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - [[package]] name = "scheduled-thread-pool" version = "0.2.7" @@ -1984,29 +1686,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "security-framework" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.17" @@ -2062,29 +1741,6 @@ dependencies = [ "serde 1.0.163", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde 1.0.163", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha1_smol" version = "1.0.0" @@ -2179,6 +1835,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "tempfile" version = "3.5.0" @@ -2188,7 +1850,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.19", "windows-sys 0.45.0", ] @@ -2231,33 +1893,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" -dependencies = [ - "itoa", - "serde 1.0.163", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "time-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" -dependencies = [ - "time-core", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -2292,6 +1927,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -2303,16 +1948,6 @@ dependencies = [ "syn 2.0.16", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-retry" version = "0.3.0" @@ -2324,6 +1959,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -2347,6 +1993,72 @@ dependencies = [ "serde 1.0.163", ] +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.1", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn 2.0.16", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -2498,12 +2210,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" @@ -2527,79 +2233,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.86" +name = "which" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" -dependencies = [ - "bumpalo", - "log", + "either", + "home", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.16", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" - -[[package]] -name = "web-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" -dependencies = [ - "js-sys", - "wasm-bindgen", + "rustix 0.38.28", ] [[package]] @@ -2633,21 +2275,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[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", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -2666,6 +2293,15 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -2696,6 +2332,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2708,6 +2359,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -2720,6 +2377,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -2732,6 +2395,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -2744,6 +2413,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -2756,6 +2431,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -2768,6 +2449,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -2781,13 +2468,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] -name = "winreg" -version = "0.10.1" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "yaml-rust" @@ -2797,33 +2481,3 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] - -[[package]] -name = "zstd" -version = "0.12.3+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "6.0.5+zstd.1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" -dependencies = [ - "cc", - "libc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml index 9206b7d..e5e6d72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "dcache" version = "0.1.0" edition = "2021" +build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -15,30 +16,31 @@ tracing = { version = "0.1.37", features = ["log"] } serde_json = "1.0.96" serde = { version = "1.0.163", features = ["derive"] } byteorder = "1.4.3" -actix-web = "4" -actix-web-httpauth = "0.8.0" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } lazy_static = "1.4.0" pretty_env_logger = "0.4.0" uuid = { version = "1", features = ["v4"] } -actix-web-codegen-const-routes = { version = "0.1.0", tag = "0.1.0", git = "https://github.com/realaravinth/actix-web-codegen-const-routes" } derive_builder = "0.11.2" config = { version = "0.11", features = ["toml"] } derive_more = "0.99.17" url = { version = "2.2.2", features = ["serde"]} async-trait = "0.1.36" clap = { version = "4.1.11", features = ["derive", "env"] } -reqwest = { version = "0.11.9", features = ["json"] } -tokio = { version = "1.0", default-features = false, features = ["sync"] } +tokio = { version = "1.0", default-features = false, features = ["sync", "macros", "rt-multi-thread"] } tracing-subscriber = { version = "0.3.0", features = ["env-filter"] } actix = "0.13.0" +tonic = { version = "0.10.2", features = ["transport", "channel"] } +prost = "0.12.3" +tokio-stream = "0.1.14" +async-stream = "0.3.5" +actix-rt = "2.9.0" [build-dependencies] serde_json = "1" +tonic-build = "0.10.2" [dev-dependencies] -actix-rt = "2.7.0" base64 = "0.13.0" anyhow = "1.0.63" maplit = "1.0.2" diff --git a/Dockerfile b/Dockerfile index 5d5636b..21aeea4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ FROM rust:latest as rust WORKDIR /src +RUN apt update && apt-get install -y --no-install-recommends protobuf-compiler COPY . . RUN cargo build --release diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c31aece --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +python.gen: + . venv/bin/activate && cd dcache_py + python -m grpc_tools.protoc \ + -I=./proto/dcache/ --python_out=dcache_py/ \ + --pyi_out=dcache_py/ \ + --grpc_python_out=dcache_py/ ./proto/dcache/dcache.proto diff --git a/bench/adaptor.py b/bench/adaptor.py new file mode 100644 index 0000000..78b4b5c --- /dev/null +++ b/bench/adaptor.py @@ -0,0 +1,64 @@ +import time +from typing import Any, Callable +import grpc +import grpc.experimental.gevent as grpc_gevent +from grpc_interceptor import ClientInterceptor +from locust import User +from locust.exception import LocustError + +# patch grpc so that it uses gevent instead of asyncio +grpc_gevent.init_gevent() + + +class LocustInterceptor(ClientInterceptor): + def __init__(self, environment, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.env = environment + + def intercept( + self, + method: Callable, + request_or_iterator: Any, + call_details: grpc.ClientCallDetails, + ): + response = None + exception = None + start_perf_counter = time.perf_counter() + response_length = 0 + try: + response = method(request_or_iterator, call_details) + response_length = response.result().ByteSize() + except grpc.RpcError as e: + exception = e + + self.env.events.request.fire( + request_type="grpc", + name=call_details.method, + response_time=(time.perf_counter() - start_perf_counter) * 1000, + response_length=response_length, + response=response, + context=None, + exception=exception, + ) + return response + + +class GrpcUser(User): + abstract = True + stub_class = None + + def __init__(self, environment): + super().__init__(environment) + for attr_value, attr_name in ( + (self.host, "host"), + (self.stub_class, "stub_class"), + ): + if attr_value is None: + raise LocustError(f"You must specify the {attr_name}.") + + self._channel = grpc.insecure_channel(self.host) + interceptor = LocustInterceptor(environment=environment) + self._channel = grpc.intercept_channel(self._channel, interceptor) + + self.stub = self.stub_class(self._channel) diff --git a/bench/locustfile.py b/bench/locustfile.py index 1645bb0..98259fd 100644 --- a/bench/locustfile.py +++ b/bench/locustfile.py @@ -1,95 +1,69 @@ +import json +import time +import grpc +import gevent from pprint import pprint -from locust import FastHttpUser, between, task +from locust import FastHttpUser, between, task, events -password = "fooobarasdfasdf" -username = "realaravinth" +from dcache_py import dcache_pb2 as dcache +from dcache_py.dcache_pb2 import RaftRequest +from dcache_py.dcache_pb2_grpc import DcacheServiceStub + +import adaptor + +host = "localhost:9001" +captcha_id = "locust" -class Unprotected(FastHttpUser): - # wait_time = between(5, 15) - peers = [ - "http://localhost:9001", - "http://localhost:9002", - "http://localhost:9003", - ] - leader = "http://localhost:9001" - host = leader - captcha_id="locust" - - pipeline_vote = [] - for _ in range(0,1000): - pipeline_vote.append({"AddVisitor": captcha_id}) - -# def on_start(self): -# resp = self.client.get(f"{self.leader}/metrics") -# data = resp.json() -# leader = data["Ok"]["membership_config"]["log_id"]["leader_id"]["node_id"] -# self.leader = self.peers[leader - 1] -# self.host = self.leader -# print(f"Leader: {self.host}") -# self.add_captcha(captcha_id="locust") +def add_captcha(stub: DcacheServiceStub, captcha_id: str): + msg = dcache.AddCaptchaRequest( + id=captcha_id, + mcaptcha=dcache.MCaptcha( + duration=30, + defense=dcache.Defense( + levels=[ + dcache.Level(visitor_threshold=50, difficulty_factor=500), + dcache.Level(visitor_threshold=5000, difficulty_factor=50000), + ] + ), + ), + ) + resp = stub.AddCaptcha(msg) + pprint(f"Captcha added {captcha_id}: {resp}") - - def write(self, data): - resp = self.client.post(f"{self.host}/write", json=data) - print(f"RPC Status: {resp.status_code}") - resp = resp.json() - if "Err" in resp: - leader = resp["Err"]["APIError"]["ForwardToLeader"]["leader_node"]["addr"] - print(f"Forwarding write to leader {leader}") - return write(leader, data) - return resp["Ok"]["data"] - - def pipeline_write(self, data): - resp = self.client.post(f"{self.host}/pipeline/write", json=data) -# print(f"RPC Status: {resp.status_code}") - resp = resp.json() - if "Err" in resp: - leader = resp["Err"]["APIError"]["ForwardToLeader"]["leader_node"]["addr"] - print(f"Forwarding write to leader {leader}") - return write(leader, data) - return resp +with grpc.insecure_channel(host) as channel: + stub = DcacheServiceStub(channel) + add_captcha(stub=stub, captcha_id=captcha_id) +pipeline_msgs = [] +for _ in range(0,10): + pipeline_msgs.append(dcache.DcacheRequest(addVisitor=dcache.CaptchaID(id=captcha_id))) +pipeline_msgs = dcache.DcacheBatchRequest(requests=pipeline_msgs) + +#def pipeline_generate_messages(): +# for msg in pipeline_msgs: +# yield msg + + +class HelloGrpcUser(adaptor.GrpcUser): + stub_class = DcacheServiceStub + host = host + captcha_id = captcha_id + msg = dcache.CaptchaID(id=captcha_id) def add_vote(self, captcha_id: str): - resp = self.write(data={"AddVisitor": captcha_id}) - pprint(resp) + resp = self.stub.AddVisitor(self.msg) - def add_vote_pipeline(self, captcha_id: str): - resp = self.pipeline_write(data=self.pipeline_vote) -# pprint(resp) - - def add_captcha(self, captcha_id: str): - params = { - "AddCaptcha": { - "id": captcha_id, - "mcaptcha": { - "visitor_threshold": 0, - "defense": { - "levels": [ - {"visitor_threshold": 50, "difficulty_factor": 500}, - {"visitor_threshold": 5000, "difficulty_factor": 50000}, - ], - "current_visitor_threshold": 0, - }, - "duration": 30, - }, - } - } - resp = self.write(data=params) - pprint(f"Captcha added {captcha_id}: {resp}") + def add_vote_pipeline(self): + res = self.stub.PipelineDcacheOps(pipeline_msgs) +# @task +# def addVote(self): +# self.add_vote(self.captcha_id) @task - def unprotected(self): - self.add_vote_pipeline(captcha_id=self.captcha_id) - ##self.add_vote(captcha_id="locust") -# data = { -# "username": username, -# "password": username, -# "confirm_password": username, -# } -# self.client.post("/unprotected", data=data) + def addVotePipeline(self): + self.add_vote_pipeline() diff --git a/bench/results/v2/grpc-no-conn-pool-single/bench.sh b/bench/results/v2/grpc-no-conn-pool-single/bench.sh new file mode 100755 index 0000000..af9b270 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/bench.sh @@ -0,0 +1,7 @@ +#!/bin/bash + + ghz --insecure --proto ./proto/dcache/dcache.proto --call dcache.DcacheService.Write \ + -c 300 -n 30000 --rps 4000 -O html -o out.html \ + -d '{"data":"{\"AddVisitor\": \"test_1\"}"}' \ + localhost:9001 +# -d '{"data":"{\"AddCaptcha\":{\"id\":\"test_1\",\"mcaptcha\":{\"defense\":{\"current_visitor_threshold\":0,\"levels\":[{\"difficulty_factor\":500,\"visitor_threshold\":50},{\"difficulty_factor\":50000,\"visitor_threshold\":5000}]},\"duration\":30,\"visitor_threshold\":0}}}"}' \ diff --git a/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/README.md b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/README.md new file mode 100644 index 0000000..89bcbfb --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/README.md @@ -0,0 +1 @@ +10 messages per batch request diff --git a/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/exceptions_1703846156.5374856.csv b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/exceptions_1703846156.5374856.csv new file mode 100644 index 0000000..5e0e870 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/exceptions_1703846156.5374856.csv @@ -0,0 +1 @@ +Count,Message,Traceback,Nodes diff --git a/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/failures_1703846155.0632446.csv b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/failures_1703846155.0632446.csv new file mode 100644 index 0000000..f87ff75 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/failures_1703846155.0632446.csv @@ -0,0 +1 @@ +Method,Name,Error,Occurrences diff --git a/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/report_1703846160.6884449.html b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/report_1703846160.6884449.html new file mode 100644 index 0000000..f6dbb7b --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/report_1703846160.6884449.html @@ -0,0 +1,592 @@ + + + + Test Report for locustfile.py + + + + +
+

Locust Test Report

+ +
+ +

During: 2023-12-29 10:34:29 - 2023-12-29 10:35:33

+

Target Host: localhost:9001

+

Script: locustfile.py

+
+ +
+

Request Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName# Requests# FailsAverage (ms)Min (ms)Max (ms)Average size (bytes)RPSFailures/s
grpc/dcache.DcacheService/PipelineDcacheOps41383099518240650.90.0
Aggregated41383099518240650.90.0
+
+ +
+

Response Time Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName50%ile (ms)60%ile (ms)70%ile (ms)80%ile (ms)90%ile (ms)95%ile (ms)99%ile (ms)100%ile (ms)
grpc/dcache.DcacheService/PipelineDcacheOps140150150150160160170180
Aggregated140150150150160160170180
+
+ + + + + + +
+

Charts

+
+ + +
+

Final ratio

+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/requests_1703846136.072447.csv b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/requests_1703846136.072447.csv new file mode 100644 index 0000000..51e1b08 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/grpc-no-conn-pool-batch/requests_1703846136.072447.csv @@ -0,0 +1,3 @@ +Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100% +grpc,/dcache.DcacheService/PipelineDcacheOps,41383,0,140.0,99.16818701259079,5.581609002547339,182.89305199868977,40.0,650.896214047811,0.0,140,150,150,150,160,160,160,170,180,180,180 +,Aggregated,41383,0,140.0,99.16818701259079,5.581609002547339,182.89305199868977,40.0,650.896214047811,0.0,140,150,150,150,160,160,160,170,180,180,180 diff --git a/bench/results/v2/grpc-no-conn-pool-single/json/exceptions_1703750739.8121767.csv b/bench/results/v2/grpc-no-conn-pool-single/json/exceptions_1703750739.8121767.csv new file mode 100644 index 0000000..5e0e870 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/json/exceptions_1703750739.8121767.csv @@ -0,0 +1 @@ +Count,Message,Traceback,Nodes diff --git a/bench/results/v2/grpc-no-conn-pool-single/json/failures_1703750736.2690804.csv b/bench/results/v2/grpc-no-conn-pool-single/json/failures_1703750736.2690804.csv new file mode 100644 index 0000000..f87ff75 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/json/failures_1703750736.2690804.csv @@ -0,0 +1 @@ +Method,Name,Error,Occurrences diff --git a/bench/results/v2/grpc-no-conn-pool-single/json/report_1703750744.1268215.html b/bench/results/v2/grpc-no-conn-pool-single/json/report_1703750744.1268215.html new file mode 100644 index 0000000..bddb3a0 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/json/report_1703750744.1268215.html @@ -0,0 +1,592 @@ + + + + Test Report for locustfile.py + + + + +
+

Locust Test Report

+ +
+ +

During: 2023-12-28 08:02:42 - 2023-12-28 08:04:54

+

Target Host: localhost:9001

+

Script: locustfile.py

+
+ +
+

Request Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName# Requests# FailsAverage (ms)Min (ms)Max (ms)Average size (bytes)RPSFailures/s
grpc/dcache.DcacheService/Write96465053032860130732.30.0
Aggregated96465053032860130732.30.0
+
+ +
+

Response Time Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName50%ile (ms)60%ile (ms)70%ile (ms)80%ile (ms)90%ile (ms)95%ile (ms)99%ile (ms)100%ile (ms)
grpc/dcache.DcacheService/Write6006707708801100120015002900
Aggregated6006707708801100120015002900
+
+ + + + + + +
+

Charts

+
+ + +
+

Final ratio

+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/bench/results/v2/grpc-no-conn-pool-single/json/requests_1703750722.6138687.csv b/bench/results/v2/grpc-no-conn-pool-single/json/requests_1703750722.6138687.csv new file mode 100644 index 0000000..85ebcbd --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/json/requests_1703750722.6138687.csv @@ -0,0 +1,3 @@ +Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100% +grpc,/dcache.DcacheService/Write,96465,0,600.0,530.5241670541676,3.931416000114041,2860.153126999876,130.11822940963043,732.274667601832,0.0,600,720,830,880,1100,1200,1300,1500,2300,2900,2900 +,Aggregated,96465,0,600.0,530.5241670541676,3.931416000114041,2860.153126999876,130.11822940963043,732.274667601832,0.0,600,720,830,880,1100,1200,1300,1500,2300,2900,2900 diff --git a/bench/results/v2/grpc-no-conn-pool-single/nojson/exceptions_1703752024.3059587.csv b/bench/results/v2/grpc-no-conn-pool-single/nojson/exceptions_1703752024.3059587.csv new file mode 100644 index 0000000..5e0e870 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/nojson/exceptions_1703752024.3059587.csv @@ -0,0 +1 @@ +Count,Message,Traceback,Nodes diff --git a/bench/results/v2/grpc-no-conn-pool-single/nojson/failures_1703752021.1710336.csv b/bench/results/v2/grpc-no-conn-pool-single/nojson/failures_1703752021.1710336.csv new file mode 100644 index 0000000..f87ff75 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/nojson/failures_1703752021.1710336.csv @@ -0,0 +1 @@ +Method,Name,Error,Occurrences diff --git a/bench/results/v2/grpc-no-conn-pool-single/nojson/report_1703752029.4987965.html b/bench/results/v2/grpc-no-conn-pool-single/nojson/report_1703752029.4987965.html new file mode 100644 index 0000000..3f2fea7 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/nojson/report_1703752029.4987965.html @@ -0,0 +1,592 @@ + + + + Test Report for locustfile.py + + + + +
+

Locust Test Report

+ +
+ +

During: 2023-12-28 08:25:29 - 2023-12-28 08:26:43

+

Target Host: localhost:9001

+

Script: locustfile.py

+
+ +
+

Request Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName# Requests# FailsAverage (ms)Min (ms)Max (ms)Average size (bytes)RPSFailures/s
grpc/dcache.DcacheService/AddVisitor358924077312304843.00.0
Aggregated358924077312304843.00.0
+
+ +
+

Response Time Statistics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodName50%ile (ms)60%ile (ms)70%ile (ms)80%ile (ms)90%ile (ms)95%ile (ms)99%ile (ms)100%ile (ms)
grpc/dcache.DcacheService/AddVisitor798285889296100120
Aggregated798285889296100120
+
+ + + + + + +
+

Charts

+
+ + +
+

Final ratio

+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/bench/results/v2/grpc-no-conn-pool-single/nojson/requests_1703752009.4098575.csv b/bench/results/v2/grpc-no-conn-pool-single/nojson/requests_1703752009.4098575.csv new file mode 100644 index 0000000..2ddf854 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/nojson/requests_1703752009.4098575.csv @@ -0,0 +1,3 @@ +Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,100% +grpc,/dcache.DcacheService/AddVisitor,358924,0,79,77.86313645947614,3.354386999944836,123.28810700000759,0.0,4842.970815301002,0.0,79,84,86,88,92,96,100,100,110,120,120 +,Aggregated,358924,0,79,77.86313645947614,3.354386999944836,123.28810700000759,0.0,4842.970815301002,0.0,79,84,86,88,92,96,100,100,110,120,120 diff --git a/bench/results/v2/grpc-no-conn-pool-single/out.html b/bench/results/v2/grpc-no-conn-pool-single/out.html new file mode 100644 index 0000000..5ffc5e7 --- /dev/null +++ b/bench/results/v2/grpc-no-conn-pool-single/out.html @@ -0,0 +1,413 @@ + + + + + + + ghz + + + + + + + + + + + +
+ +
+ + +

Mon Dec 25 2023 @ 21:02:15

+ +
+
+ +
+ +
+
+ + + +
+
+
+
+ +

Summary

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Count30000
Total7.50 s
Slowest3.60 ms
Fastest0.13 ms
Average0.53 ms
Requests / sec3999.44
+
+
+
+
+
+
+
+
+ +
+
+
+ +

Histogram

+
+

+

+

+
+
+ +
+
+
+ +

Latency distribution

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
10 %25 %50 %75 %90 %95 %99 %
0.43 ms0.45 ms0.50 ms0.58 ms0.65 ms0.71 ms0.89 ms
+
+
+ +
+
+
+
+
+ +

Status distribution

+
+ + + + + + + + + + + + + + + + + +
StatusCount% of Total
OK30000100.00 %
+
+
+
+
+ + + +
+
+
+
+
+ +

Data

+
+ + JSON + CSV +
+
+
+
+ +
+ +
+
+ +

Options

+
+
+
+
{
+  "call": "dcache.DcacheService.Write",
+  "host": "localhost:9001",
+  "proto": "./proto/dcache/dcache.proto",
+  "import-paths": [
+    "proto/dcache",
+    "."
+  ],
+  "insecure": true,
+  "rps": 4000,
+  "load-schedule": "const",
+  "load-start": 0,
+  "load-end": 0,
+  "load-step": 0,
+  "load-step-duration": 0,
+  "load-max-duration": 0,
+  "concurrency": 300,
+  "concurrency-schedule": "const",
+  "concurrency-start": 0,
+  "concurrency-end": 0,
+  "concurrency-step": 1,
+  "concurrency-step-duration": 0,
+  "concurrency-max-duration": 0,
+  "total": 30000,
+  "connections": 1,
+  "timeout": 20000000000,
+  "dial-timeout": 10000000000,
+  "data": {
+    "data": "{\"AddVisitor\": \"test_1\"}"
+  },
+  "binary": false,
+  "CPUs": 12
+}
+
+
+
+
+ +
+
+
+

+ Generated by ghz +

+ +
+
+ +
+ + + + + + + + diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..bec50d6 --- /dev/null +++ b/build.rs @@ -0,0 +1,10 @@ +fn main() -> Result<(), Box> { + // tonic_build::configure() + // .out_dir("protoout") + // .compile( + // &["proto/dcache/dcache.proto"], + // &["proto/dcache"], + // )?; + tonic_build::compile_protos("proto/dcache/dcache.proto")?; + Ok(()) +} diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..758cf64 --- /dev/null +++ b/check.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +protoc \ +--proto_path=${PWD}/proto \ +--proto_path=${PWD}/bufbuild \ +--go_out=${PWD} \ +--go-grpc_out=${PWD} \ +--validate_out="lang=rust:${PWD}" \ +${PWD}/proto/dcache/dcache.proto diff --git a/dcache_py/dcache_pb2.py b/dcache_py/dcache_pb2.py new file mode 100644 index 0000000..b81d9d5 --- /dev/null +++ b/dcache_py/dcache_pb2.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: dcache.proto +# Protobuf Python Version: 4.25.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x64\x63\x61\x63he.proto\x12\x06\x64\x63\x61\x63he\"?\n\x05Level\x12\x1a\n\x11visitor_threshold\x18\xad\x02 \x01(\r\x12\x1a\n\x11\x64ifficulty_factor\x18\xae\x02 \x01(\r\")\n\x07\x44\x65\x66\x65nse\x12\x1e\n\x06levels\x18\x91\x03 \x03(\x0b\x32\r.dcache.Level\"@\n\x08MCaptcha\x12\x11\n\x08\x64uration\x18\xf6\x03 \x01(\x04\x12!\n\x07\x64\x65\x66\x65nse\x18\xf7\x03 \x01(\x0b\x32\x0f.dcache.Defense\"E\n\x11\x41\x64\x64\x43\x61ptchaRequest\x12\x0b\n\x02id\x18\xd9\x04 \x01(\t\x12#\n\x08mcaptcha\x18\xda\x04 \x01(\x0b\x32\x10.dcache.MCaptcha\"9\n\x14RenameCaptchaRequest\x12\r\n\x04name\x18\xbd\x05 \x01(\t\x12\x12\n\trename_to\x18\xbe\x05 \x01(\t\"_\n\x0f\x43\x61\x63hePowRequest\x12\x0f\n\x06string\x18\xa1\x06 \x01(\t\x12\x1a\n\x11\x64ifficulty_factor\x18\xa2\x06 \x01(\r\x12\x11\n\x08\x64uration\x18\xa3\x06 \x01(\x04\x12\x0c\n\x03key\x18\xa4\x06 \x01(\t\"E\n\x12\x43\x61\x63heResultRequest\x12\x0e\n\x05token\x18\xb1\x06 \x01(\t\x12\x0c\n\x03key\x18\xb2\x06 \x01(\t\x12\x11\n\x08\x64uration\x18\xb3\x06 \x01(\x04\",\n\x1a\x44\x65leteCaptchaResultRequest\x12\x0e\n\x05token\x18\xb5\x06 \x01(\t\"\x17\n\tCaptchaID\x12\n\n\x02id\x18\x01 \x01(\t\"\x12\n\x04PoID\x12\n\n\x02id\x18\x01 \x01(\t\"A\n\x10\x41\x64\x64VisitorResult\x12\x11\n\x08\x64uration\x18\x85\x07 \x01(\x04\x12\x1a\n\x11\x64ifficulty_factor\x18\x86\x07 \x01(\r\"S\n\x16OptionAddVisitorResult\x12.\n\x06result\x18\x8f\x07 \x01(\x0b\x32\x18.dcache.AddVisitorResultH\x00\x88\x01\x01\x42\t\n\x07_result\"\x1b\n\x0bRaftRequest\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"(\n\tRaftReply\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"#\n\x07Learner\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\t\"\xbd\x02\n\rDcacheRequest\x12/\n\naddCaptcha\x18\x01 \x01(\x0b\x32\x19.dcache.AddCaptchaRequestH\x00\x12\'\n\naddVisitor\x18\x02 \x01(\x0b\x32\x11.dcache.CaptchaIDH\x00\x12\x35\n\rrenameCaptcha\x18\x03 \x01(\x0b\x32\x1c.dcache.RenameCaptchaRequestH\x00\x12*\n\rremoveCaptcha\x18\x04 \x01(\x0b\x32\x11.dcache.CaptchaIDH\x00\x12+\n\x08\x63\x61\x63hePow\x18\x05 \x01(\x0b\x32\x17.dcache.CachePowRequestH\x00\x12\x31\n\x0b\x63\x61\x63heResult\x18\x06 \x01(\x0b\x32\x1a.dcache.CacheResultRequestH\x00\x42\x0f\n\rDcacheRequest\"\x8b\x01\n\x0e\x44\x63\x61\x63heResponse\x12\x43\n\x19option_add_visitor_result\x18\x01 \x01(\x0b\x32\x1e.dcache.OptionAddVisitorResultH\x00\x12\"\n\x05other\x18\x02 \x01(\x0b\x32\x11.dcache.RaftReplyH\x00\x42\x10\n\x0e\x44\x63\x61\x63heResponse\"=\n\x12\x44\x63\x61\x63heBatchRequest\x12\'\n\x08requests\x18\x01 \x03(\x0b\x32\x15.dcache.DcacheRequest\"@\n\x13\x44\x63\x61\x63heBatchResponse\x12)\n\tresponses\x18\x01 \x03(\x0b\x32\x16.dcache.DcacheResponse2\x97\x06\n\rDcacheService\x12<\n\nAddCaptcha\x12\x19.dcache.AddCaptchaRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x41\n\nAddVisitor\x12\x11.dcache.CaptchaID\x1a\x1e.dcache.OptionAddVisitorResult\"\x00\x12\x42\n\rRenameCaptcha\x12\x1c.dcache.RenameCaptchaRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x37\n\rRemoveCaptcha\x12\x11.dcache.CaptchaID\x1a\x11.dcache.RaftReply\"\x00\x12\x38\n\x08\x43\x61\x63hePow\x12\x17.dcache.CachePowRequest\x1a\x11.dcache.RaftReply\"\x00\x12>\n\x0b\x43\x61\x63heResult\x12\x1a.dcache.CacheResultRequest\x1a\x11.dcache.RaftReply\"\x00\x12N\n\x11PipelineDcacheOps\x12\x1a.dcache.DcacheBatchRequest\x1a\x1b.dcache.DcacheBatchResponse\"\x00\x12\x32\n\nAddLearner\x12\x0f.dcache.Learner\x1a\x11.dcache.RaftReply\"\x00\x12\x31\n\x05Write\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x33\n\x07\x46orward\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x37\n\rAppendEntries\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\x12\x39\n\x0fInstallSnapshot\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\x12.\n\x04vote\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReplyb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dcache_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _globals['_LEVEL']._serialized_start=24 + _globals['_LEVEL']._serialized_end=87 + _globals['_DEFENSE']._serialized_start=89 + _globals['_DEFENSE']._serialized_end=130 + _globals['_MCAPTCHA']._serialized_start=132 + _globals['_MCAPTCHA']._serialized_end=196 + _globals['_ADDCAPTCHAREQUEST']._serialized_start=198 + _globals['_ADDCAPTCHAREQUEST']._serialized_end=267 + _globals['_RENAMECAPTCHAREQUEST']._serialized_start=269 + _globals['_RENAMECAPTCHAREQUEST']._serialized_end=326 + _globals['_CACHEPOWREQUEST']._serialized_start=328 + _globals['_CACHEPOWREQUEST']._serialized_end=423 + _globals['_CACHERESULTREQUEST']._serialized_start=425 + _globals['_CACHERESULTREQUEST']._serialized_end=494 + _globals['_DELETECAPTCHARESULTREQUEST']._serialized_start=496 + _globals['_DELETECAPTCHARESULTREQUEST']._serialized_end=540 + _globals['_CAPTCHAID']._serialized_start=542 + _globals['_CAPTCHAID']._serialized_end=565 + _globals['_POID']._serialized_start=567 + _globals['_POID']._serialized_end=585 + _globals['_ADDVISITORRESULT']._serialized_start=587 + _globals['_ADDVISITORRESULT']._serialized_end=652 + _globals['_OPTIONADDVISITORRESULT']._serialized_start=654 + _globals['_OPTIONADDVISITORRESULT']._serialized_end=737 + _globals['_RAFTREQUEST']._serialized_start=739 + _globals['_RAFTREQUEST']._serialized_end=766 + _globals['_RAFTREPLY']._serialized_start=768 + _globals['_RAFTREPLY']._serialized_end=808 + _globals['_LEARNER']._serialized_start=810 + _globals['_LEARNER']._serialized_end=845 + _globals['_DCACHEREQUEST']._serialized_start=848 + _globals['_DCACHEREQUEST']._serialized_end=1165 + _globals['_DCACHERESPONSE']._serialized_start=1168 + _globals['_DCACHERESPONSE']._serialized_end=1307 + _globals['_DCACHEBATCHREQUEST']._serialized_start=1309 + _globals['_DCACHEBATCHREQUEST']._serialized_end=1370 + _globals['_DCACHEBATCHRESPONSE']._serialized_start=1372 + _globals['_DCACHEBATCHRESPONSE']._serialized_end=1436 + _globals['_DCACHESERVICE']._serialized_start=1439 + _globals['_DCACHESERVICE']._serialized_end=2230 +# @@protoc_insertion_point(module_scope) diff --git a/dcache_py/dcache_pb2.pyi b/dcache_py/dcache_pb2.pyi new file mode 100644 index 0000000..4197ae5 --- /dev/null +++ b/dcache_py/dcache_pb2.pyi @@ -0,0 +1,156 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Level(_message.Message): + __slots__ = ("visitor_threshold", "difficulty_factor") + VISITOR_THRESHOLD_FIELD_NUMBER: _ClassVar[int] + DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int] + visitor_threshold: int + difficulty_factor: int + def __init__(self, visitor_threshold: _Optional[int] = ..., difficulty_factor: _Optional[int] = ...) -> None: ... + +class Defense(_message.Message): + __slots__ = ("levels",) + LEVELS_FIELD_NUMBER: _ClassVar[int] + levels: _containers.RepeatedCompositeFieldContainer[Level] + def __init__(self, levels: _Optional[_Iterable[_Union[Level, _Mapping]]] = ...) -> None: ... + +class MCaptcha(_message.Message): + __slots__ = ("duration", "defense") + DURATION_FIELD_NUMBER: _ClassVar[int] + DEFENSE_FIELD_NUMBER: _ClassVar[int] + duration: int + defense: Defense + def __init__(self, duration: _Optional[int] = ..., defense: _Optional[_Union[Defense, _Mapping]] = ...) -> None: ... + +class AddCaptchaRequest(_message.Message): + __slots__ = ("id", "mcaptcha") + ID_FIELD_NUMBER: _ClassVar[int] + MCAPTCHA_FIELD_NUMBER: _ClassVar[int] + id: str + mcaptcha: MCaptcha + def __init__(self, id: _Optional[str] = ..., mcaptcha: _Optional[_Union[MCaptcha, _Mapping]] = ...) -> None: ... + +class RenameCaptchaRequest(_message.Message): + __slots__ = ("name", "rename_to") + NAME_FIELD_NUMBER: _ClassVar[int] + RENAME_TO_FIELD_NUMBER: _ClassVar[int] + name: str + rename_to: str + def __init__(self, name: _Optional[str] = ..., rename_to: _Optional[str] = ...) -> None: ... + +class CachePowRequest(_message.Message): + __slots__ = ("string", "difficulty_factor", "duration", "key") + STRING_FIELD_NUMBER: _ClassVar[int] + DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int] + DURATION_FIELD_NUMBER: _ClassVar[int] + KEY_FIELD_NUMBER: _ClassVar[int] + string: str + difficulty_factor: int + duration: int + key: str + def __init__(self, string: _Optional[str] = ..., difficulty_factor: _Optional[int] = ..., duration: _Optional[int] = ..., key: _Optional[str] = ...) -> None: ... + +class CacheResultRequest(_message.Message): + __slots__ = ("token", "key", "duration") + TOKEN_FIELD_NUMBER: _ClassVar[int] + KEY_FIELD_NUMBER: _ClassVar[int] + DURATION_FIELD_NUMBER: _ClassVar[int] + token: str + key: str + duration: int + def __init__(self, token: _Optional[str] = ..., key: _Optional[str] = ..., duration: _Optional[int] = ...) -> None: ... + +class DeleteCaptchaResultRequest(_message.Message): + __slots__ = ("token",) + TOKEN_FIELD_NUMBER: _ClassVar[int] + token: str + def __init__(self, token: _Optional[str] = ...) -> None: ... + +class CaptchaID(_message.Message): + __slots__ = ("id",) + ID_FIELD_NUMBER: _ClassVar[int] + id: str + def __init__(self, id: _Optional[str] = ...) -> None: ... + +class PoID(_message.Message): + __slots__ = ("id",) + ID_FIELD_NUMBER: _ClassVar[int] + id: str + def __init__(self, id: _Optional[str] = ...) -> None: ... + +class AddVisitorResult(_message.Message): + __slots__ = ("duration", "difficulty_factor") + DURATION_FIELD_NUMBER: _ClassVar[int] + DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int] + duration: int + difficulty_factor: int + def __init__(self, duration: _Optional[int] = ..., difficulty_factor: _Optional[int] = ...) -> None: ... + +class OptionAddVisitorResult(_message.Message): + __slots__ = ("result",) + RESULT_FIELD_NUMBER: _ClassVar[int] + result: AddVisitorResult + def __init__(self, result: _Optional[_Union[AddVisitorResult, _Mapping]] = ...) -> None: ... + +class RaftRequest(_message.Message): + __slots__ = ("data",) + DATA_FIELD_NUMBER: _ClassVar[int] + data: str + def __init__(self, data: _Optional[str] = ...) -> None: ... + +class RaftReply(_message.Message): + __slots__ = ("data", "error") + DATA_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + data: str + error: str + def __init__(self, data: _Optional[str] = ..., error: _Optional[str] = ...) -> None: ... + +class Learner(_message.Message): + __slots__ = ("id", "addr") + ID_FIELD_NUMBER: _ClassVar[int] + ADDR_FIELD_NUMBER: _ClassVar[int] + id: int + addr: str + def __init__(self, id: _Optional[int] = ..., addr: _Optional[str] = ...) -> None: ... + +class DcacheRequest(_message.Message): + __slots__ = ("addCaptcha", "addVisitor", "renameCaptcha", "removeCaptcha", "cachePow", "cacheResult") + ADDCAPTCHA_FIELD_NUMBER: _ClassVar[int] + ADDVISITOR_FIELD_NUMBER: _ClassVar[int] + RENAMECAPTCHA_FIELD_NUMBER: _ClassVar[int] + REMOVECAPTCHA_FIELD_NUMBER: _ClassVar[int] + CACHEPOW_FIELD_NUMBER: _ClassVar[int] + CACHERESULT_FIELD_NUMBER: _ClassVar[int] + addCaptcha: AddCaptchaRequest + addVisitor: CaptchaID + renameCaptcha: RenameCaptchaRequest + removeCaptcha: CaptchaID + cachePow: CachePowRequest + cacheResult: CacheResultRequest + def __init__(self, addCaptcha: _Optional[_Union[AddCaptchaRequest, _Mapping]] = ..., addVisitor: _Optional[_Union[CaptchaID, _Mapping]] = ..., renameCaptcha: _Optional[_Union[RenameCaptchaRequest, _Mapping]] = ..., removeCaptcha: _Optional[_Union[CaptchaID, _Mapping]] = ..., cachePow: _Optional[_Union[CachePowRequest, _Mapping]] = ..., cacheResult: _Optional[_Union[CacheResultRequest, _Mapping]] = ...) -> None: ... + +class DcacheResponse(_message.Message): + __slots__ = ("option_add_visitor_result", "other") + OPTION_ADD_VISITOR_RESULT_FIELD_NUMBER: _ClassVar[int] + OTHER_FIELD_NUMBER: _ClassVar[int] + option_add_visitor_result: OptionAddVisitorResult + other: RaftReply + def __init__(self, option_add_visitor_result: _Optional[_Union[OptionAddVisitorResult, _Mapping]] = ..., other: _Optional[_Union[RaftReply, _Mapping]] = ...) -> None: ... + +class DcacheBatchRequest(_message.Message): + __slots__ = ("requests",) + REQUESTS_FIELD_NUMBER: _ClassVar[int] + requests: _containers.RepeatedCompositeFieldContainer[DcacheRequest] + def __init__(self, requests: _Optional[_Iterable[_Union[DcacheRequest, _Mapping]]] = ...) -> None: ... + +class DcacheBatchResponse(_message.Message): + __slots__ = ("responses",) + RESPONSES_FIELD_NUMBER: _ClassVar[int] + responses: _containers.RepeatedCompositeFieldContainer[DcacheResponse] + def __init__(self, responses: _Optional[_Iterable[_Union[DcacheResponse, _Mapping]]] = ...) -> None: ... diff --git a/dcache_py/dcache_pb2_grpc.py b/dcache_py/dcache_pb2_grpc.py new file mode 100644 index 0000000..3ad2977 --- /dev/null +++ b/dcache_py/dcache_pb2_grpc.py @@ -0,0 +1,465 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import dcache_py.dcache_pb2 as dcache__pb2 + + +class DcacheServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.AddCaptcha = channel.unary_unary( + '/dcache.DcacheService/AddCaptcha', + request_serializer=dcache__pb2.AddCaptchaRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.AddVisitor = channel.unary_unary( + '/dcache.DcacheService/AddVisitor', + request_serializer=dcache__pb2.CaptchaID.SerializeToString, + response_deserializer=dcache__pb2.OptionAddVisitorResult.FromString, + ) + self.RenameCaptcha = channel.unary_unary( + '/dcache.DcacheService/RenameCaptcha', + request_serializer=dcache__pb2.RenameCaptchaRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.RemoveCaptcha = channel.unary_unary( + '/dcache.DcacheService/RemoveCaptcha', + request_serializer=dcache__pb2.CaptchaID.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.CachePow = channel.unary_unary( + '/dcache.DcacheService/CachePow', + request_serializer=dcache__pb2.CachePowRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.CacheResult = channel.unary_unary( + '/dcache.DcacheService/CacheResult', + request_serializer=dcache__pb2.CacheResultRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.PipelineDcacheOps = channel.unary_unary( + '/dcache.DcacheService/PipelineDcacheOps', + request_serializer=dcache__pb2.DcacheBatchRequest.SerializeToString, + response_deserializer=dcache__pb2.DcacheBatchResponse.FromString, + ) + self.AddLearner = channel.unary_unary( + '/dcache.DcacheService/AddLearner', + request_serializer=dcache__pb2.Learner.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.Write = channel.unary_unary( + '/dcache.DcacheService/Write', + request_serializer=dcache__pb2.RaftRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.Forward = channel.unary_unary( + '/dcache.DcacheService/Forward', + request_serializer=dcache__pb2.RaftRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.AppendEntries = channel.unary_unary( + '/dcache.DcacheService/AppendEntries', + request_serializer=dcache__pb2.RaftRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.InstallSnapshot = channel.unary_unary( + '/dcache.DcacheService/InstallSnapshot', + request_serializer=dcache__pb2.RaftRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + self.vote = channel.unary_unary( + '/dcache.DcacheService/vote', + request_serializer=dcache__pb2.RaftRequest.SerializeToString, + response_deserializer=dcache__pb2.RaftReply.FromString, + ) + + +class DcacheServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def AddCaptcha(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AddVisitor(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def RenameCaptcha(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def RemoveCaptcha(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CachePow(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CacheResult(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def PipelineDcacheOps(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AddLearner(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Write(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Forward(self, request, context): + """/ Forward a request to other + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AppendEntries(self, request, context): + """raft RPC + + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def InstallSnapshot(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def vote(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_DcacheServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'AddCaptcha': grpc.unary_unary_rpc_method_handler( + servicer.AddCaptcha, + request_deserializer=dcache__pb2.AddCaptchaRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'AddVisitor': grpc.unary_unary_rpc_method_handler( + servicer.AddVisitor, + request_deserializer=dcache__pb2.CaptchaID.FromString, + response_serializer=dcache__pb2.OptionAddVisitorResult.SerializeToString, + ), + 'RenameCaptcha': grpc.unary_unary_rpc_method_handler( + servicer.RenameCaptcha, + request_deserializer=dcache__pb2.RenameCaptchaRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'RemoveCaptcha': grpc.unary_unary_rpc_method_handler( + servicer.RemoveCaptcha, + request_deserializer=dcache__pb2.CaptchaID.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'CachePow': grpc.unary_unary_rpc_method_handler( + servicer.CachePow, + request_deserializer=dcache__pb2.CachePowRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'CacheResult': grpc.unary_unary_rpc_method_handler( + servicer.CacheResult, + request_deserializer=dcache__pb2.CacheResultRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'PipelineDcacheOps': grpc.unary_unary_rpc_method_handler( + servicer.PipelineDcacheOps, + request_deserializer=dcache__pb2.DcacheBatchRequest.FromString, + response_serializer=dcache__pb2.DcacheBatchResponse.SerializeToString, + ), + 'AddLearner': grpc.unary_unary_rpc_method_handler( + servicer.AddLearner, + request_deserializer=dcache__pb2.Learner.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'Write': grpc.unary_unary_rpc_method_handler( + servicer.Write, + request_deserializer=dcache__pb2.RaftRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'Forward': grpc.unary_unary_rpc_method_handler( + servicer.Forward, + request_deserializer=dcache__pb2.RaftRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'AppendEntries': grpc.unary_unary_rpc_method_handler( + servicer.AppendEntries, + request_deserializer=dcache__pb2.RaftRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'InstallSnapshot': grpc.unary_unary_rpc_method_handler( + servicer.InstallSnapshot, + request_deserializer=dcache__pb2.RaftRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + 'vote': grpc.unary_unary_rpc_method_handler( + servicer.vote, + request_deserializer=dcache__pb2.RaftRequest.FromString, + response_serializer=dcache__pb2.RaftReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'dcache.DcacheService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class DcacheService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def AddCaptcha(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AddCaptcha', + dcache__pb2.AddCaptchaRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def AddVisitor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AddVisitor', + dcache__pb2.CaptchaID.SerializeToString, + dcache__pb2.OptionAddVisitorResult.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def RenameCaptcha(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/RenameCaptcha', + dcache__pb2.RenameCaptchaRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def RemoveCaptcha(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/RemoveCaptcha', + dcache__pb2.CaptchaID.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def CachePow(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/CachePow', + dcache__pb2.CachePowRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def CacheResult(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/CacheResult', + dcache__pb2.CacheResultRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def PipelineDcacheOps(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/PipelineDcacheOps', + dcache__pb2.DcacheBatchRequest.SerializeToString, + dcache__pb2.DcacheBatchResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def AddLearner(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AddLearner', + dcache__pb2.Learner.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Write(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/Write', + dcache__pb2.RaftRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Forward(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/Forward', + dcache__pb2.RaftRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def AppendEntries(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AppendEntries', + dcache__pb2.RaftRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def InstallSnapshot(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/InstallSnapshot', + dcache__pb2.RaftRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def vote(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/vote', + dcache__pb2.RaftRequest.SerializeToString, + dcache__pb2.RaftReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/proto/dcache/dcache.proto b/proto/dcache/dcache.proto new file mode 100644 index 0000000..0aa1856 --- /dev/null +++ b/proto/dcache/dcache.proto @@ -0,0 +1,129 @@ +syntax = "proto3"; + +package dcache; + +message Level { + uint32 visitor_threshold = 301; + uint32 difficulty_factor= 302; +} + +message Defense { + repeated Level levels = 401; +} +message MCaptcha { + uint64 duration = 502; + Defense defense = 503; +} + +message AddCaptchaRequest { + string id = 601; + MCaptcha mcaptcha = 602; +} + + +message RenameCaptchaRequest { + string name = 701; + string rename_to = 702; +} + + +message CachePowRequest { + string string= 801; + uint32 difficulty_factor = 802; + uint64 duration = 803; + string key = 804; +} + +message CacheResultRequest { + string token = 817; + string key = 818; + uint64 duration= 819; +} + +message DeleteCaptchaResultRequest { + string token = 821; +} + +message CaptchaID{ + string id = 1; +} + +message PoID{ + string id = 1; +} + + +message AddVisitorResult { + uint64 duration = 901; + uint32 difficulty_factor = 902; +} + +message OptionAddVisitorResult { + optional AddVisitorResult result = 911; +} + +message RaftRequest { + string data = 1; +} + +message RaftReply { + string data = 1; + string error = 2; +} + +message Learner { + uint64 id = 1; + string addr = 2; +} + + +message DcacheRequest { + oneof DcacheRequest { + AddCaptchaRequest addCaptcha = 1; + CaptchaID addVisitor = 2; + RenameCaptchaRequest renameCaptcha = 3; + CaptchaID removeCaptcha = 4; + CachePowRequest cachePow = 5; + CacheResultRequest cacheResult = 6; + } +} + + +message DcacheResponse { + oneof DcacheResponse { + OptionAddVisitorResult option_add_visitor_result = 1; + RaftReply other = 2; + } +} + +message DcacheBatchRequest { + repeated DcacheRequest requests = 1; +} + +message DcacheBatchResponse { + repeated DcacheResponse responses = 1; +} + +service DcacheService { + rpc AddCaptcha(AddCaptchaRequest) returns (RaftReply) {} + rpc AddVisitor(CaptchaID) returns (OptionAddVisitorResult) {} + rpc RenameCaptcha(RenameCaptchaRequest) returns (RaftReply) {} + rpc RemoveCaptcha(CaptchaID) returns (RaftReply) {} + rpc CachePow(CachePowRequest) returns (RaftReply) {} + rpc CacheResult(CacheResultRequest) returns (RaftReply) {} + + rpc PipelineDcacheOps(DcacheBatchRequest) returns (DcacheBatchResponse) {} + + + rpc AddLearner(Learner) returns (RaftReply) {} + rpc Write(RaftRequest) returns (RaftReply) {} + + /// Forward a request to other + rpc Forward(RaftRequest) returns (RaftReply) {} + + // raft RPC + + rpc AppendEntries(RaftRequest) returns (RaftReply); + rpc InstallSnapshot(RaftRequest) returns (RaftReply); + rpc vote(RaftRequest) returns (RaftReply); +} diff --git a/src/app.rs b/src/app.rs index e5fec4a..99d704d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -17,7 +17,6 @@ */ use std::collections::BTreeMap; use std::sync::Arc; -use std::time::Duration; use openraft::error::RaftError; use openraft::BasicNode; diff --git a/src/bin/main.rs b/src/bin/main.rs index 4059611..c31a6ef 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -16,11 +16,7 @@ * along with this program. If not, see . */ use clap::Parser; -use dcache::network::raft_network_impl::DcacheNetwork; use dcache::start_example_raft_node; -use dcache::store::DcacheStore; -use dcache::DcacheTypeConfig; -use openraft::Raft; use tracing_subscriber::EnvFilter; //pub type DcacheRaft = Raft; @@ -44,7 +40,7 @@ pub struct Opt { pub cluster_size: usize, } -#[actix_web::main] +#[actix_rt::main] async fn main() -> std::io::Result<()> { // Setup the logger tracing_subscriber::fmt() diff --git a/src/lib.rs b/src/lib.rs index df65628..fbb574d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,27 +20,24 @@ use std::io::Cursor; use std::sync::Arc; -use actix_web::middleware; -use actix_web::middleware::Logger; -use actix_web::web::Data; -use actix_web::App; -use actix_web::HttpServer; use openraft::storage::Adaptor; use openraft::BasicNode; use openraft::Config; use openraft::Raft; +use tonic::transport::Server; use crate::app::DcacheApp; -use crate::network::api; -use crate::network::management; -use crate::network::raft; use crate::network::raft_network_impl::DcacheNetwork; +use crate::protobuf::dcache::dcache_service_client::DcacheServiceClient; +use crate::protobuf::dcache::dcache_service_server::DcacheServiceServer; +use crate::protobuf::dcache::Learner; use crate::store::DcacheRequest; use crate::store::DcacheResponse; use crate::store::DcacheStore; pub mod app; pub mod network; +mod protobuf; pub mod store; pub type DcacheNodeId = u64; @@ -98,7 +95,6 @@ pub async fn start_example_raft_node( let store = Arc::new(DcacheStore::new(salt)); let (log_store, state_machine) = Adaptor::new(store.clone()); - let client = reqwest::Client::new(); // Create the network layer that will connect and communicate the raft instances and // will be used in conjunction with the store created above. @@ -106,7 +102,7 @@ pub async fn start_example_raft_node( let (manager_tx, manager_rx) = tokio::sync::mpsc::channel(1000); // let health = Arc::new(crate::network::raft_network_impl::HealthLedger::new(manager_tx)); // let network = Arc::new(DcacheNetwork::new(health)); - let network = Arc::new(DcacheNetwork::new(manager_tx, client.clone())); + let network = Arc::new(DcacheNetwork::new(manager_tx)); // Create a local raft instance. let raft = Raft::new( @@ -120,67 +116,73 @@ pub async fn start_example_raft_node( .unwrap(); raft.enable_heartbeat(true); raft.enable_elect(true); + + let captcha = serde_json::json!({ + "AddCaptcha": { + "id": "test_1", + "mcaptcha": { + "visitor_threshold": 0, + "defense": { + "levels": [ + {"visitor_threshold": 50, "difficulty_factor": 500}, + {"visitor_threshold": 5000, "difficulty_factor": 50000}, + ], + "current_visitor_threshold": 0, + }, + "duration": 30, + }}}); + #[derive(serde::Serialize)] + struct X { + data: String, + } + let x = X { + data: serde_json::to_string(&captcha).unwrap(), + }; + println!("{}", serde_json::to_string(&x).unwrap()); + // raft.enable_tick(true); // Create an application that will store all the instances created above, this will // be later used on the actix-web services. - let app = Data::new(DcacheApp { + let app = DcacheApp { id: node_id, addr: http_addr.clone(), raft, store, config, network, - }); + }; + let app = Arc::new(app); + let dcache_service = protobuf::MyDcacheImpl::new(app.clone()); if introducer_addr == http_addr { app.init().await.unwrap(); } let app_copy = app.clone(); - // Start the actix-web server. - let server = HttpServer::new(move || { - App::new() - .wrap(Logger::default()) - .wrap(Logger::new("%a %{User-Agent}i")) - .wrap(middleware::Compress::default()) - .app_data(app.clone()) - // raft internal RPC - .service(raft::append) - .service(raft::snapshot) - .service(raft::vote) - // admin API - .service(management::init) - .service(management::add_learner) - .service(management::change_membership) - .service(management::metrics) - // application API - .service(api::write) - .service(api::state) - .service(api::read) - .service(api::pipeline_read) - .service(api::pipeline_write) - // .service(api::consistent_read) - }); - let x = server.bind(&http_addr)?; + let svc = DcacheServiceServer::new(dcache_service); + + let x = Server::builder() + .add_service(svc) + .serve(http_addr.clone().parse().unwrap()); + let server_fut = tokio::spawn(x); - let server_fut = tokio::spawn(x.run()); tokio::time::sleep(std::time::Duration::new(3, 0)).await; - let req: (DcacheNodeId, String) = (node_id, http_addr); - let c = reqwest::Client::new(); - c.post(format!("http://{}/add-learner", introducer_addr)) - .json(&req) - .send() + let url = format!("http://{}", introducer_addr); + let mut client = DcacheServiceClient::connect(url).await.unwrap(); + client + .add_learner(Learner { + id: node_id, + addr: http_addr, + }) .await .unwrap(); - // let health_job = tokio::spawn(DcacheApp::health_job(app_copy)); let health_metrics_handle = crate::network::management::HealthMetrics::spawn(app_copy, 5, manager_rx).await; - server_fut.await??; + server_fut.await?.unwrap(); health_metrics_handle.abort(); - // health_job.abort(); Ok(()) } diff --git a/src/network/api.rs b/src/network/api.rs deleted file mode 100644 index 32c7ea3..0000000 --- a/src/network/api.rs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * mCaptcha - A proof of work based DoS protection system - * Copyright © 2023 Aravinth Manivannan - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -use actix_web::get; -use actix_web::post; -use actix_web::web; -use actix_web::web::Data; -use actix_web::Responder; -use libmcaptcha::cache::messages::{CachedPoWConfig, RetrivePoW, VerifyCaptchaResult}; -use libmcaptcha::master::messages::GetInternalData; -use serde::Deserialize; -use serde::Serialize; -use web::Json; - -use crate::app::DcacheApp; -use crate::store::DcacheRequest; - -#[post("/write")] -pub async fn write( - app: Data, - req: Json, -) -> actix_web::Result { - let response = app.raft.client_write(req.0).await; - Ok(Json(response)) -} - -#[get("/state")] -pub async fn state(app: Data) -> actix_web::Result { - let sm = app.store.state_machine.read().await; - let resp = sm - .data - .master - .send(GetInternalData) - .await - .unwrap() - .await - .unwrap() - .unwrap(); - Ok(Json(resp)) -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub enum ReadRequest { - RetrivePoW(RetrivePoW), //Reader - VerifyCaptchaResult(VerifyCaptchaResult), //Reader -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum ReadResponse { - VerifyCaptchaResult(bool), - RetrivePoW(Option), -} - -#[post("/read")] -pub async fn read( - app: Data, - req: Json, -) -> actix_web::Result { - let sm = app.store.state_machine.read().await; - - let req = req.into_inner(); - let res = match req { - ReadRequest::RetrivePoW(msg) => { - let cache_res = sm - .data - .cache - .send(msg.clone()) - .await - .unwrap() - .await - .unwrap() - .unwrap(); - ReadResponse::RetrivePoW(cache_res) - } - ReadRequest::VerifyCaptchaResult(msg) => { - let cache_res = sm - .data - .cache - .send(msg.clone()) - .await - .unwrap() - .await - .unwrap() - .unwrap(); - ReadResponse::VerifyCaptchaResult(cache_res) - } - }; - Ok(Json(res)) -} - -#[post("/pipeline/read")] -pub async fn pipeline_read( - app: Data, - requests: Json>, -) -> actix_web::Result { - let requests = requests.into_inner(); - let mut responses = Vec::with_capacity(requests.len()); - let sm = app.store.state_machine.read().await; - for request in requests { - let res = match request { - ReadRequest::RetrivePoW(msg) => { - let cache_res = sm - .data - .cache - .send(msg.clone()) - .await - .unwrap() - .await - .unwrap() - .unwrap(); - ReadResponse::RetrivePoW(cache_res) - } - ReadRequest::VerifyCaptchaResult(msg) => { - let cache_res = sm - .data - .cache - .send(msg.clone()) - .await - .unwrap() - .await - .unwrap() - .unwrap(); - ReadResponse::VerifyCaptchaResult(cache_res) - } - }; - - responses.push(res); - } - Ok(Json(responses)) -} - -#[post("/pipeline/write")] -pub async fn pipeline_write( - app: Data, - requests: Json>, -) -> actix_web::Result { - let mut responses = Vec::with_capacity(requests.len()); - let mut requests = requests.into_inner(); - for req in requests.drain(0..) { - responses.push(app.raft.client_write(req).await); - } - Ok(Json(responses)) -} diff --git a/src/network/management.rs b/src/network/management.rs index d3616a7..16b19a9 100644 --- a/src/network/management.rs +++ b/src/network/management.rs @@ -15,66 +15,15 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -use std::collections::BTreeMap; -use std::collections::BTreeSet; use std::collections::HashMap; +use std::sync::Arc; -use actix_web::get; -use actix_web::post; -use actix_web::web; -use actix_web::web::Data; -use actix_web::Responder; -use openraft::error::Infallible; -use openraft::BasicNode; -use openraft::RaftMetrics; -use web::Json; +//use actix_web::web; +//use actix_web::web::Data; use crate::app::DcacheApp; use crate::DcacheNodeId; -#[post("/add-learner")] -pub async fn add_learner( - app: Data, - req: Json<(DcacheNodeId, String)>, -) -> actix_web::Result { - let node_id = req.0 .0; - let node = BasicNode { - addr: req.0 .1.clone(), - }; - let res = app.raft.add_learner(node_id, node, true).await; - - Ok(Json(res)) -} - -#[post("/change-membership")] -pub async fn change_membership( - app: Data, - req: Json>, -) -> actix_web::Result { - let res = app.raft.change_membership(req.0, false).await; - Ok(Json(res)) -} - -#[post("/init")] -pub async fn init(app: Data) -> actix_web::Result { - let mut nodes = BTreeMap::new(); - nodes.insert( - app.id, - BasicNode { - addr: app.addr.clone(), - }, - ); - let res = app.raft.initialize(nodes).await; - Ok(Json(res)) -} - -#[get("/metrics")] -pub async fn metrics(app: Data) -> actix_web::Result { - let metrics = app.raft.metrics().borrow().clone(); - let res: Result, Infallible> = Ok(metrics); - Ok(Json(res)) -} - use tokio::sync::mpsc; #[derive(Debug)] @@ -87,7 +36,7 @@ pub struct HealthMetrics; impl HealthMetrics { pub async fn spawn( - app: Data, + app: Arc, threshold: usize, mut rx: mpsc::Receiver, ) -> tokio::task::JoinHandle<()> { @@ -114,7 +63,7 @@ impl HealthMetrics { new_nodes.push(*node.0); } - let res = + let _res = app.raft.change_membership(new_nodes, false).await.unwrap(); } } else { @@ -128,20 +77,3 @@ impl HealthMetrics { tokio::spawn(fut) } } - -//#[get("/self/remove/{id}")] -//pub async fn remove_node(app: Data, id: web::Path) -> actix_web::Result { -// let cluster_metrics = app.raft.metrics().borrow().clone(); -// let remote_id: u64 = 3; -// let mut new_nodes: Vec = Vec::new(); -// for node in cluster_metrics.membership_config.nodes() { -// if *node.0 == remote_id { -// continue; -// } -// -// new_nodes.push(*node.0); -// } -// -// let res = app.raft.change_membership(new_nodes, false).await; -// Ok(Json(res)) -//} diff --git a/src/network/mod.rs b/src/network/mod.rs index 555eefa..f20ed75 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -pub mod api; +//pub mod api; pub mod management; -pub mod raft; +//pub mod raft; pub mod raft_network_impl; diff --git a/src/network/raft.rs b/src/network/raft.rs deleted file mode 100644 index 2ac62d6..0000000 --- a/src/network/raft.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * mCaptcha - A proof of work based DoS protection system - * Copyright © 2023 Aravinth Manivannan - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -use actix_web::post; -use actix_web::web; -use actix_web::web::Data; -use actix_web::Responder; -use openraft::raft::AppendEntriesRequest; -use openraft::raft::InstallSnapshotRequest; -use openraft::raft::VoteRequest; -use web::Json; - -use crate::app::DcacheApp; -use crate::DcacheNodeId; -use crate::DcacheTypeConfig; - -// --- Raft communication - -#[post("/raft-vote")] -pub async fn vote( - app: Data, - req: Json>, -) -> actix_web::Result { - let res = app.raft.vote(req.0).await; - Ok(Json(res)) -} - -#[post("/raft-append")] -pub async fn append( - app: Data, - req: Json>, -) -> actix_web::Result { - let res = app.raft.append_entries(req.0).await; - Ok(Json(res)) -} - -#[post("/raft-snapshot")] -pub async fn snapshot( - app: Data, - req: Json>, -) -> actix_web::Result { - let res = app.raft.install_snapshot(req.0).await; - Ok(Json(res)) -} diff --git a/src/network/raft_network_impl.rs b/src/network/raft_network_impl.rs index 7bc2c8d..7e7e093 100644 --- a/src/network/raft_network_impl.rs +++ b/src/network/raft_network_impl.rs @@ -1,6 +1,3 @@ -use std::collections::BTreeMap; -use std::collections::BTreeSet; -use std::collections::HashSet; /* * mCaptcha - A proof of work based DoS protection system * Copyright © 2023 Aravinth Manivannan @@ -18,18 +15,13 @@ use std::collections::HashSet; * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -use std::collections::HashMap; use std::sync::Arc; -use std::sync::RwLock; -use std::time::Duration; -use std::time::Instant; use async_trait::async_trait; use openraft::error::InstallSnapshotError; use openraft::error::NetworkError; use openraft::error::RPCError; use openraft::error::RaftError; -use openraft::error::RemoteError; use openraft::raft::AppendEntriesRequest; use openraft::raft::AppendEntriesResponse; use openraft::raft::InstallSnapshotRequest; @@ -39,7 +31,6 @@ use openraft::raft::VoteResponse; use openraft::BasicNode; use openraft::RaftNetwork; use openraft::RaftNetworkFactory; -use reqwest::Client; use serde::de::DeserializeOwned; use serde::Serialize; use tokio::sync::mpsc::Sender; @@ -48,22 +39,30 @@ use super::management::HealthStatus; use crate::DcacheNodeId; use crate::DcacheTypeConfig; +use crate::protobuf::dcache::dcache_service_client::DcacheServiceClient; +use crate::protobuf::dcache::RaftRequest; + #[derive(Clone)] pub struct DcacheNetwork { pub signal: Sender, - pub client: Client, +} + +pub enum RPCType { + Vote, + Snapshot, + Append, } impl DcacheNetwork { - pub fn new(signal: Sender, client: Client) -> Self { - Self { signal, client } + pub fn new(signal: Sender) -> Self { + Self { signal } } pub async fn send_rpc( &self, target: DcacheNodeId, target_node: &BasicNode, - uri: &str, req: Req, + event: RPCType, ) -> Result> where Req: Serialize, @@ -72,34 +71,51 @@ impl DcacheNetwork { { let addr = &target_node.addr; - let url = format!("http://{}/{}", addr, uri); + let url = format!("http://{}", addr); - tracing::debug!("send_rpc to url: {}", url); + let mut client = DcacheServiceClient::connect(url).await.unwrap(); - let resp = match self.client.post(url).json(&req).send().await { - Ok(resp) => Ok(resp), + let res = match event { + RPCType::Vote => { + client + .vote(RaftRequest { + data: serde_json::to_string(&req).unwrap(), + }) + .await + } + + RPCType::Snapshot => { + client + .install_snapshot(RaftRequest { + data: serde_json::to_string(&req).unwrap(), + }) + .await + } + + RPCType::Append => { + client + .append_entries(RaftRequest { + data: serde_json::to_string(&req).unwrap(), + }) + .await + } + }; + + match res { + Ok(res) => { + let signal2 = self.signal.clone(); + let fut = async move { + let _ = signal2.send(HealthStatus::Healthy(target)).await; + }; + tokio::spawn(fut); + let res = res.into_inner(); + Ok(serde_json::from_str(&res.data).unwrap()) + } Err(e) => { - self.signal.send(HealthStatus::Down(target)).await; + let _ = self.signal.send(HealthStatus::Down(target)).await; Err(RPCError::Network(NetworkError::new(&e))) } - }?; - - tracing::debug!("client.post() is sent"); - - let res: Result = resp - .json() - .await - .map_err(|e| RPCError::Network(NetworkError::new(&e)))?; - - let res = res.map_err(|e| RPCError::RemoteError(RemoteError::new(target, e))); - if res.is_ok() { - let signal2 = self.signal.clone(); - let fut = async move { - let _ = signal2.send(HealthStatus::Healthy(target)).await; - }; - tokio::spawn(fut); } - res } } @@ -134,7 +150,7 @@ impl RaftNetwork for DcacheNetworkConnection { RPCError>, > { self.owner - .send_rpc(self.target, &self.target_node, "raft-append", req) + .send_rpc(self.target, &self.target_node, req, RPCType::Append) .await } @@ -146,7 +162,7 @@ impl RaftNetwork for DcacheNetworkConnection { RPCError>, > { self.owner - .send_rpc(self.target, &self.target_node, "raft-snapshot", req) + .send_rpc(self.target, &self.target_node, req, RPCType::Append) .await } @@ -158,7 +174,7 @@ impl RaftNetwork for DcacheNetworkConnection { RPCError>, > { self.owner - .send_rpc(self.target, &self.target_node, "raft-vote", req) + .send_rpc(self.target, &self.target_node, req, RPCType::Vote) .await } } diff --git a/src/protobuf.rs b/src/protobuf.rs new file mode 100644 index 0000000..f049b6f --- /dev/null +++ b/src/protobuf.rs @@ -0,0 +1,402 @@ +use std::sync::Arc; + +use libmcaptcha::cache::messages as CacheMessages; +use libmcaptcha::defense; +use libmcaptcha::master::messages as MasterMessages; +use libmcaptcha::mcaptcha; +use openraft::BasicNode; +use serde::de::DeserializeOwned; +use serde::Serialize; +use tonic::Response; + +use dcache::dcache_request::DcacheRequest as PipelineReq; +use dcache::dcache_response::DcacheResponse as InnerPipelineRes; +use dcache::dcache_service_server::DcacheService; +use dcache::DcacheResponse as OuterPipelineRes; +use dcache::{Learner, RaftReply, RaftRequest}; + +use crate::app::DcacheApp; +use crate::store::{DcacheRequest, DcacheResponse}; + +pub mod dcache { + tonic::include_proto!("dcache"); // The string specified here must match the proto package name +} + +#[derive(Clone)] +pub struct MyDcacheImpl { + app: Arc, +} + +impl MyDcacheImpl { + pub fn new(app: Arc) -> Self { + Self { app } + } +} + +#[tonic::async_trait] +impl DcacheService for MyDcacheImpl { + async fn add_learner( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let node_id = req.id; + let node = BasicNode { + addr: req.addr.clone(), + }; + println!("Learner added: {:?}", &req.addr); + let res = self.app.raft.add_learner(node_id, node, true).await; + Ok(Response::new(res.into())) + } + + async fn add_captcha( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::AddCaptcha(req.into())) + .await; + Ok(Response::new(res.into())) + } + + async fn add_visitor( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::AddVisitor(MasterMessages::AddVisitor( + req.id, + ))) + .await + .map_err(|e| { + tonic::Status::new(tonic::Code::Internal, serde_json::to_string(&e).unwrap()) + })?; + match res.data { + DcacheResponse::AddVisitorResult(res) => { + Ok(Response::new(dcache::OptionAddVisitorResult { + result: res.map(|f| f.into()), + })) + } + + _ => unimplemented!(), + } + } + + async fn rename_captcha( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::RenameCaptcha(req.into())) + .await; + Ok(Response::new(res.into())) + } + + async fn remove_captcha( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::RemoveCaptcha(MasterMessages::RemoveCaptcha( + req.id, + ))) + .await; + Ok(Response::new(res.into())) + } + + async fn cache_pow( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::CachePoW(req.into())) + .await; + Ok(Response::new(res.into())) + } + + async fn cache_result( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let res = self + .app + .raft + .client_write(DcacheRequest::CacheResult(req.into())) + .await; + Ok(Response::new(res.into())) + } + + // type PipelineDcacheOpsStream = + // Pin> + Send + 'static>>; + + // async fn pipeline_dcache_ops( + // &self, + // request: tonic::Request>, + // ) -> std::result::Result, tonic::Status> { + + async fn pipeline_dcache_ops( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + let mut reqs = request.into_inner(); + let mut responses = Vec::with_capacity(reqs.requests.len()); + for req in reqs.requests.drain(0..) { + let res = match req.dcache_request.unwrap() { + PipelineReq::AddCaptcha(add_captcha_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::AddCaptcha(add_captcha_req.into())) + .await; + OuterPipelineRes { + dcache_response: Some(InnerPipelineRes::Other(res.into())), + } + } + PipelineReq::AddVisitor(add_visitor_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::AddVisitor(MasterMessages::AddVisitor( + add_visitor_req.id, + ))) + .await; + match res { + Err(_) => OuterPipelineRes { + dcache_response: None, + }, + Ok(res) => match res.data { + DcacheResponse::AddVisitorResult(res) => { + let res = dcache::OptionAddVisitorResult { + result: res.map(|f| f.into()), + }; + OuterPipelineRes { + dcache_response: Some( + InnerPipelineRes::OptionAddVisitorResult(res), + ), + } + } + + _ => unimplemented!(), + }, + } + + } + PipelineReq::RenameCaptcha(rename_captcha_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::RenameCaptcha(rename_captcha_req.into())) + .await; + OuterPipelineRes { + dcache_response: Some(InnerPipelineRes::Other(res.into())), + } + } + PipelineReq::RemoveCaptcha(remove_captcha_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::RemoveCaptcha(MasterMessages::RemoveCaptcha( + remove_captcha_req.id, + ))) + .await; + OuterPipelineRes { + dcache_response: Some(InnerPipelineRes::Other(res.into())), + } + } + PipelineReq::CachePow(cache_pow_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::CachePoW(cache_pow_req.into())) + .await; + OuterPipelineRes { + dcache_response: Some(InnerPipelineRes::Other(res.into())), + } + } + PipelineReq::CacheResult(cache_result_req) => { + let res = self + .app + .raft + .client_write(DcacheRequest::CacheResult(cache_result_req.into())) + .await; + OuterPipelineRes { + dcache_response: Some(InnerPipelineRes::Other(res.into())), + } + } + }; + responses.push(res); + } + Ok(Response::new(dcache::DcacheBatchResponse { responses })) + } + + async fn write( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let req = serde_json::from_str(&req.data).unwrap(); + let res = self.app.raft.client_write(req).await; + Ok(Response::new(res.into())) + } + /// / Forward a request to other + async fn forward( + &self, + _request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + unimplemented!(); + } + async fn append_entries( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let req = serde_json::from_str(&req.data).unwrap(); + let res = self.app.raft.append_entries(req).await; + Ok(Response::new(res.into())) + } + async fn install_snapshot( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let req = serde_json::from_str(&req.data).unwrap(); + let res = self.app.raft.install_snapshot(req).await; + Ok(Response::new(res.into())) + } + async fn vote( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let req = request.into_inner(); + let req = serde_json::from_str(&req.data).unwrap(); + let res = self.app.raft.vote(req).await; + Ok(Response::new(res.into())) + } +} + +impl From for Result +where + T: DeserializeOwned, + E: DeserializeOwned, +{ + fn from(msg: RaftReply) -> Self { + if !msg.data.is_empty() { + let resp: T = serde_json::from_str(&msg.data).expect("fail to deserialize"); + Ok(resp) + } else { + let err: E = serde_json::from_str(&msg.error).expect("fail to deserialize"); + Err(err) + } + } +} + +impl From> for RaftReply +where + T: Serialize, + E: Serialize, +{ + fn from(r: Result) -> Self { + match r { + Ok(x) => { + let data = serde_json::to_string(&x).expect("fail to serialize"); + RaftReply { + data, + error: Default::default(), + } + } + Err(e) => { + let error = serde_json::to_string(&e).expect("fail to serialize"); + RaftReply { + data: Default::default(), + error, + } + } + } + } +} + +impl From for MasterMessages::AddSite { + fn from(value: dcache::AddCaptchaRequest) -> Self { + let req_mcaptcha = value.mcaptcha.unwrap(); + let mut defense = req_mcaptcha.defense.unwrap(); + let mut new_defense = defense::DefenseBuilder::default(); + for level in defense.levels.drain(0..) { + new_defense + .add_level( + defense::LevelBuilder::default() + .difficulty_factor(level.difficulty_factor) + .unwrap() + .visitor_threshold(level.visitor_threshold) + .build() + .unwrap(), + ) + .unwrap(); + } + let defense = new_defense.build().unwrap(); + let mcaptcha = mcaptcha::MCaptchaBuilder::default() + .defense(defense) + .duration(req_mcaptcha.duration) + .build() + .unwrap(); + + Self { + id: value.id, + mcaptcha, + } + } +} + +impl From for dcache::AddVisitorResult { + fn from(value: libmcaptcha::master::AddVisitorResult) -> Self { + Self { + duration: value.duration, + difficulty_factor: value.difficulty_factor, + } + } +} + +impl From for MasterMessages::Rename { + fn from(value: dcache::RenameCaptchaRequest) -> Self { + Self { + name: value.name, + rename_to: value.rename_to, + } + } +} + +impl From for CacheMessages::CachePoW { + fn from(value: dcache::CachePowRequest) -> Self { + Self { + string: value.string, + difficulty_factor: value.difficulty_factor, + duration: value.duration, + key: value.key, + } + } +} + +impl From for CacheMessages::CacheResult { + fn from(value: dcache::CacheResultRequest) -> Self { + Self { + token: value.token, + key: value.key, + duration: value.duration, + } + } +} diff --git a/src/store/mod.rs b/src/store/mod.rs index 6737a4e..b7be3c9 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -23,7 +23,6 @@ use std::ops::RangeBounds; use std::sync::Arc; use std::sync::Mutex; -use libmcaptcha::cache::messages::CachedPoWConfig; use libmcaptcha::AddVisitorResult; use libmcaptcha::MCaptcha; use openraft::async_trait::async_trait; @@ -48,15 +47,11 @@ use openraft::Vote; use serde::Deserialize; use serde::Serialize; use tokio::sync::RwLock; -use url::quirks::set_pathname; use crate::DcacheNodeId; use crate::DcacheTypeConfig; -use actix::prelude::*; -use libmcaptcha::cache::messages::{ - CachePoW, CacheResult, DeleteCaptchaResult, DeletePoW, RetrivePoW, VerifyCaptchaResult, -}; +use libmcaptcha::cache::messages::{CachePoW, CacheResult, DeleteCaptchaResult, DeletePoW}; use libmcaptcha::master::messages::{ AddSite as AddCaptcha, AddVisitor, GetInternalData, RemoveCaptcha, Rename as RenameCaptcha, SetInternalData, @@ -124,7 +119,7 @@ impl PersistableStateMachine { .unwrap() .unwrap(); Self { - last_applied_log: m.last_applied_log.clone(), + last_applied_log: m.last_applied_log, last_membership: m.last_membership.clone(), data: internal_data, } diff --git a/test.py b/test.py index c3b2909..0bc8050 100755 --- a/test.py +++ b/test.py @@ -17,6 +17,14 @@ from pprint import pprint import requests +import grpc +import json + +from dcache_py import dcache_pb2 as dcache +from dcache_py.dcache_pb2 import RaftRequest +from dcache_py.dcache_pb2_grpc import DcacheServiceStub + +# import dcache_py.dcache_resources def init(host: str): @@ -82,12 +90,13 @@ host = "localhost:9001" peers = [(2, "localhost:9002"), (3, "localhost:9003"), (4, "localhost:9004")] captcha_id = "test_1" + def initialize_cluster(): init(host) for peer_id, peer in peers: add_host(host=host, id=peer_id, peer=peer) - switch_to_cluster(host, nodes=[1, 2,3,4]) + switch_to_cluster(host, nodes=[1, 2, 3, 4]) add_captcha(host, captcha_id) add_vote(host, captcha_id) @@ -95,7 +104,75 @@ def initialize_cluster(): add_vote(host, captcha_id) +def grpc_add_vote(stub: DcacheServiceStub, captcha_id: str): + msg = dcache.CaptchaID(id=captcha_id) + # msg = RaftRequest(data=json.dumps({"AddVisitor": captcha_id})) + # resp = stub.Write(msg) + resp = stub.AddVisitor(msg) + pprint(resp) + + +def grpc_add_captcha(stub: DcacheServiceStub, captcha_id: str): + msg = dcache.AddCaptchaRequest( + id=captcha_id, + mcaptcha=dcache.MCaptcha( + duration=30, + defense=dcache.Defense( + levels=[ + dcache.Level(visitor_threshold=50, difficulty_factor=500), + dcache.Level(visitor_threshold=5000, difficulty_factor=50000), + ] + ), + ), + ) + # params = { + # "AddCaptcha": { + # "id": captcha_id, + # "mcaptcha": { + # "defense": { + # "levels": [ + # {"visitor_threshold": 50, "difficulty_factor": 500}, + # {"visitor_threshold": 5000, "difficulty_factor": 50000}, + # ], + # "current_visitor_threshold": 0, + # }, + # "duration": 30, + # }, + # } + # } + # msg = RaftRequest(data = json.dumps(params)) + resp = stub.AddCaptcha(msg) + pprint(f"Captcha added {captcha_id}: {resp}") + + + + +msgs = [] +for _ in range(0,1000): + msgs.append( + dcache.DcacheRequest(addVisitor=dcache.CaptchaID(id=captcha_id)), + ) + +msgs = dcache.DcacheBatchRequest(requests=msgs) + + + +def grpc_pipeline_add_vote(stub): + responses = stub.PipelineDcacheOps(msgs) + for r in responses.responses: + print(f"received respo: {r}") + + + + +def grpc_run(): + with grpc.insecure_channel(host) as channel: + stub = DcacheServiceStub(channel) + grpc_add_captcha(stub, captcha_id) + grpc_pipeline_add_vote(stub) + + #grpc_add_vote(stub, captcha_id) if __name__ == "__main__": - - add_vote("localhost:9002", captcha_id) + grpc_run() + # add_vote("localhost:9002", captcha_id)