From 2b8c40161e985de11a3d24a1bcf629874c44e992 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Mon, 5 May 2025 09:52:24 -0700 Subject: [PATCH 01/46] progress: split server/client connectionm handking based on uri --- Cargo.lock | 1084 +++++++++++++++++++++---- Cargo.toml | 2 +- core/main/Cargo.toml | 4 + core/main/src/firebolt/firebolt_ws.rs | 83 +- 4 files changed, 1011 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6400a3e29..939a6a213 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cipher", "cpufeatures", ] @@ -34,7 +34,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "getrandom 0.2.15", "once_cell", "serde", @@ -78,9 +78,15 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi", + "winapi 0.3.9", ] +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + [[package]] name = "anyhow" version = "1.0.96" @@ -184,7 +190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock 3.4.0", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite", @@ -251,9 +257,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", @@ -281,9 +287,9 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes", + "bytes 1.10.0", "futures-util", - "http", + "http 0.2.12", "http-body", "hyper", "itoa", @@ -307,9 +313,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes", + "bytes 1.10.0", "futures-util", - "http", + "http 0.2.12", "http-body", "mime", "rustversion", @@ -324,7 +330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -392,13 +398,25 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -407,7 +425,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -439,6 +466,12 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytecount" version = "0.6.8" @@ -451,6 +484,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.10.0" @@ -492,6 +535,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -632,7 +681,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -666,7 +715,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -712,13 +761,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -732,6 +790,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "distributor_general" version = "1.1.0" @@ -741,6 +810,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "dyn-clone" version = "1.0.18" @@ -765,7 +840,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -845,6 +920,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fancy-regex" version = "0.11.0" @@ -876,7 +967,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "libredox", "windows-sys 0.59.0", @@ -938,6 +1029,12 @@ dependencies = [ "num", ] +[[package]] +name = "fragile" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" + [[package]] name = "fs2" version = "0.4.3" @@ -945,9 +1042,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", ] +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.31" @@ -1065,6 +1178,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1075,13 +1197,24 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -1094,7 +1227,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.13.3+wasi-0.2.2", "windows-targets 0.52.6", @@ -1152,12 +1285,12 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes", + "bytes 1.10.0", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.7.1", "slab", "tokio", @@ -1250,7 +1383,18 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes", + "bytes 1.10.0", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes 1.10.0", "fnv", "itoa", ] @@ -1261,8 +1405,8 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes", - "http", + "bytes 1.10.0", + "http 0.2.12", "pin-project-lite", ] @@ -1284,12 +1428,12 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes", + "bytes 1.10.0", "futures-channel", "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "httparse", "httpdate", @@ -1309,7 +1453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", + "http 0.2.12", "hyper", "log", "rustls", @@ -1353,16 +1497,151 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.9.3" @@ -1404,7 +1683,7 @@ dependencies = [ "quote", "strum 0.26.3", "syn 2.0.98", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1426,7 +1705,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", ] [[package]] @@ -1577,13 +1865,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a" dependencies = [ "futures-util", - "http", + "http 0.2.12", "jsonrpsee-core", "jsonrpsee-types", "pin-project", "rustls-native-certs", "soketto", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls", "tokio-util", @@ -1609,12 +1897,12 @@ dependencies = [ "hyper", "jsonrpsee-types", "parking_lot", - "rand", + "rand 0.8.5", "rustc-hash", "serde", "serde_json", "soketto", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -1640,7 +1928,7 @@ checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" dependencies = [ "futures-channel", "futures-util", - "http", + "http 0.2.12", "hyper", "jsonrpsee-core", "jsonrpsee-types", @@ -1664,7 +1952,7 @@ dependencies = [ "beef", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -1674,7 +1962,7 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e1b3975ed5d73f456478681a417128597acd6a2487855fdb7b4a3d4d195bf5e" dependencies = [ - "http", + "http 0.2.12", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -1708,6 +1996,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1723,6 +2021,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "lenient_semver" version = "0.4.2" @@ -1764,8 +2068,8 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if", - "winapi", + "cfg-if 1.0.0", + "winapi 0.3.9", ] [[package]] @@ -1791,6 +2095,12 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + [[package]] name = "lock_api" version = "0.4.12" @@ -1862,7 +2172,7 @@ dependencies = [ "openrpc_validator", "proc-macro2", "querystring", - "rand", + "rand 0.8.5", "regex", "ripple_sdk", "ripple_tdk", @@ -1871,7 +2181,9 @@ dependencies = [ "serde", "serde_json", "serial_test", - "tokio-tungstenite", + "ssda_service", + "ssda_types", + "tokio-tungstenite 0.20.1", "url", "vergen", ] @@ -1921,6 +2233,25 @@ dependencies = [ "adler2", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "1.0.3" @@ -1932,30 +2263,80 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "mock_device" version = "1.0.0" dependencies = [ - "http", + "http 0.2.12", "jsonrpsee", "ripple_sdk", "ripple_tdk", "serde", "serde_json", - "tokio-tungstenite", + "tokio-tungstenite 0.20.1", "url", ] +[[package]] +name = "mockall" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" +dependencies = [ + "cfg-if 1.0.0", + "downcast", + "fragile", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "multer" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "bytes", + "bytes 1.10.0", "encoding_rs", "futures-util", - "http", + "http 0.2.12", "httparse", "log", "memchr", @@ -1990,6 +2371,17 @@ dependencies = [ "tempfile", ] +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nom" version = "7.1.3" @@ -2015,7 +2407,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2146,6 +2538,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2169,7 +2567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" dependencies = [ "bitflags 2.8.0", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -2232,7 +2630,7 @@ dependencies = [ "anyhow", "async-trait", "backtrace", - "bytes", + "bytes 1.10.0", "chrono", "flate2", "futures-util", @@ -2273,7 +2671,7 @@ checksum = "cdff329c97c39ffbc78640c83d33cd1d28f2ea8ecb7f0d9e48cbfcce95960b96" dependencies = [ "anyhow", "async-trait", - "bytes", + "bytes 1.10.0", "futures", "itertools 0.10.5", "lazy_static", @@ -2300,12 +2698,12 @@ dependencies = [ "ansi_term", "anyhow", "base64 0.21.7", - "bytes", + "bytes 1.10.0", "chrono", "difference", "futures", "hex", - "http", + "http 0.2.12", "itertools 0.10.5", "lazy_static", "lenient_semver", @@ -2317,7 +2715,7 @@ dependencies = [ "onig", "pact-plugin-driver", "pact_models", - "rand", + "rand 0.8.5", "reqwest", "semver", "serde", @@ -2338,7 +2736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb13cec89b68677e5701d4861a24335bf614b103bb9328bbf605276f758c506" dependencies = [ "anyhow", - "bytes", + "bytes 1.10.0", "futures", "hyper", "hyper-rustls", @@ -2352,7 +2750,7 @@ dependencies = [ "rustls-pemfile", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls", "tracing", @@ -2370,7 +2768,7 @@ dependencies = [ "anyhow", "ariadne", "base64 0.21.7", - "bytes", + "bytes 1.10.0", "chrono", "chrono-tz", "fs2", @@ -2387,7 +2785,7 @@ dependencies = [ "nom 7.1.3", "onig", "parse-zoneinfo", - "rand", + "rand 0.8.5", "rand_regex", "regex", "regex-syntax 0.6.29", @@ -2422,7 +2820,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -2445,7 +2843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2509,7 +2907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -2576,7 +2974,7 @@ version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "hermit-abi", "pin-project-lite", @@ -2606,6 +3004,32 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettyplease" version = "0.1.25" @@ -2641,7 +3065,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes", + "bytes 1.10.0", "prost-derive", ] @@ -2651,7 +3075,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ - "bytes", + "bytes 1.10.0", "heck 0.4.1", "itertools 0.10.5", "lazy_static", @@ -2706,23 +3130,75 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ + "getrandom 0.1.16", "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", ] [[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -2734,13 +3210,31 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_regex" version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b2a9fe2d7d9eeaf3279d1780452a5bbd26b31b27938787ef1c3e930d1e9cfbd" dependencies = [ - "rand", + "rand 0.8.5", "regex-syntax 0.6.29", ] @@ -2822,12 +3316,12 @@ checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", - "bytes", + "bytes 1.10.0", "encoding_rs", "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "hyper", "hyper-rustls", @@ -2865,7 +3359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.0", "getrandom 0.2.15", "libc", "untrusted", @@ -2937,7 +3431,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "glob", "proc-macro2", "quote", @@ -3117,18 +3611,18 @@ checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -3137,9 +3631,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -3215,6 +3709,18 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -3222,10 +3728,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.1", ] [[package]] @@ -3234,7 +3740,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", ] @@ -3251,7 +3757,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", ] @@ -3271,6 +3777,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.1" @@ -3299,7 +3811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3319,13 +3831,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes", + "bytes 1.10.0", "futures", - "http", + "http 0.2.12", "httparse", "log", - "rand", - "sha-1", + "rand 0.8.5", + "sha-1 0.9.8", ] [[package]] @@ -3334,6 +3846,80 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "ssda_client" +version = "0.1.0" +dependencies = [ + "async-trait", + "log", + "serde", + "serde_json", + "ssda_types", + "tokio", + "tokio-tungstenite 0.20.1", + "tungstenite 0.26.2", + "url", + "ws", +] + +[[package]] +name = "ssda_service" +version = "0.1.0" +dependencies = [ + "async-trait", + "http 0.2.12", + "mockall", + "serde_json", + "ssda_client", + "ssda_types", + "tokio", + "tokio-tungstenite 0.20.1", + "url", +] + +[[package]] +name = "ssda_types" +version = "0.1.0" +dependencies = [ + "async-trait", + "futures-util", + "http 0.2.12", + "mockall", + "serde", + "serde_json", + "stream-tungstenite", + "tokio", + "tokio-tungstenite 0.20.1", + "tokio-websockets", + "url", + "uuid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stream-tungstenite" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a1faabcaf0ade00ed119bec2bbde8a1b687ee67f608ac51d6a19ca730285cb" +dependencies = [ + "async-trait", + "eyre", + "futures", + "futures-util", + "rand 0.9.1", + "thiserror 2.0.12", + "tokio", + "tokio-stream", + "tokio-tungstenite 0.26.2", + "tracing", + "tungstenite 0.26.2", +] + [[package]] name = "strum" version = "0.24.1" @@ -3419,19 +4005,30 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "sysinfo" version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "core-foundation-sys", "libc", "ntapi", "once_cell", "rayon", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3472,7 +4069,7 @@ version = "3.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "getrandom 0.3.1", "once_cell", @@ -3480,6 +4077,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + [[package]] name = "test-log" version = "0.2.11" @@ -3506,7 +4109,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -3520,6 +4132,17 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "thunder" version = "1.1.0" @@ -3552,7 +4175,7 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "test-log", - "tokio-tungstenite", + "tokio-tungstenite 0.20.1", "tree_magic_mini", "url", ] @@ -3588,20 +4211,15 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.1" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tm_extn" version = "1.1.0" @@ -3609,20 +4227,20 @@ dependencies = [ "ripple_sdk", "serde", "serde_json", - "tokio-tungstenite", + "tokio-tungstenite 0.20.1", "url", ] [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", - "bytes", + "bytes 1.10.0", "libc", - "mio", + "mio 1.0.3", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -3681,6 +4299,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] @@ -3694,7 +4313,21 @@ dependencies = [ "native-tls", "tokio", "tokio-native-tls", - "tungstenite", + "tungstenite 0.20.1", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "native-tls", + "tokio", + "tokio-native-tls", + "tungstenite 0.26.2", ] [[package]] @@ -3703,7 +4336,7 @@ version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ - "bytes", + "bytes 1.10.0", "futures-core", "futures-io", "futures-sink", @@ -3711,6 +4344,25 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-websockets" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fcaf159b4e7a376b05b5bfd77bfd38f3324f5fce751b4213bfc7eaa47affb4e" +dependencies = [ + "base64 0.22.1", + "bytes 1.10.0", + "futures-core", + "futures-sink", + "http 1.3.1", + "httparse", + "openssl", + "rand 0.9.1", + "simdutf8", + "tokio", + "tokio-util", +] + [[package]] name = "toml" version = "0.8.20" @@ -3765,11 +4417,11 @@ dependencies = [ "async-trait", "axum", "base64 0.21.7", - "bytes", + "bytes 1.10.0", "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -3808,7 +4460,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -3889,19 +4541,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", - "bytes", + "bytes 1.10.0", "data-encoding", - "http", + "http 0.2.12", "httparse", "log", "native-tls", - "rand", + "rand 0.8.5", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes 1.10.0", + "data-encoding", + "http 1.3.1", + "httparse", + "log", + "native-tls", + "rand 0.9.1", + "sha1", + "thiserror 2.0.12", + "utf-8", +] + [[package]] name = "typed-arena" version = "1.7.0" @@ -3914,27 +4584,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.14" @@ -3961,9 +4616,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -3982,11 +4637,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" -version = "1.13.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f41ffb7cf259f1ecc2876861a17e7142e63ead296f671f81f6ae85903e0d6" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ "getrandom 0.3.1", "serde", @@ -4037,6 +4704,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4058,7 +4731,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -4084,7 +4757,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "once_cell", "wasm-bindgen", @@ -4174,6 +4847,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -4184,6 +4863,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4377,7 +5062,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] @@ -4390,6 +5075,46 @@ dependencies = [ "bitflags 2.8.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "ws" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "httparse", + "log", + "mio 0.6.23", + "mio-extras", + "rand 0.7.3", + "sha-1 0.8.2", + "slab", + "url", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "xattr" version = "1.4.0" @@ -4407,6 +5132,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4428,6 +5177,49 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 916cd258f..6d367c530 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ serde_json = { version = "1.0", default-features = false} serde = { version = "1.0", features = ["derive"], default-features = false } tokio = { version = "1.44.1", default-features = false } tokio-tungstenite = { version = "0.20.1", default-features = false } -url = { version = "=2.5.0", default-features = false} +url = { version = "=2.5.4", default-features = false} urlencoding = { version = "2.1.0", default-features = false} uuid = { version = "1.13.1", default-features = false } ripple_sdk = { path = "./core/sdk" } diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index d97f45823..99694eb35 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -70,6 +70,10 @@ jaq-std = { version = "1.5.1", default-features = false } openrpc_validator = { path = "../../openrpc_validator" } proc-macro2.workspace = true +ssda_service = {path = "../../../../ssda/ssda_service/"} +ssda_types = {path = "../../../../ssda/ssda_types/"} + + [build-dependencies] vergen = "1" diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 0d9a94f3a..0c3f4f585 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -17,7 +17,7 @@ use std::{ net::SocketAddr, - sync::{Arc, RwLock}, + sync::{Arc, Mutex, RwLock}, }; use super::firebolt_gateway::FireboltGatewayCommand; @@ -47,6 +47,8 @@ use ripple_sdk::{ uuid::Uuid, }; use ripple_sdk::{log::debug, tokio}; +use ssda_service::ApiGateway; +use ssda_types::{APIGatewayServiceConnectionDisposition, ServiceId}; use tokio_tungstenite::{ tungstenite::{self, Message}, WebSocketStream, @@ -61,12 +63,16 @@ pub struct ClientIdentity { app_id: String, rpc_v2: bool, } - +#[derive(Debug, Clone)] +struct ServiceConnection { + service_id: ServiceId, +} struct ConnectionCallbackConfig { pub next: oneshot::Sender, pub app_state: AppManagerState, pub secure: bool, pub internal_app_id: Option, + pub service_connection: Arc>>, } pub struct ConnectionCallback(ConnectionCallbackConfig); @@ -123,6 +129,12 @@ impl tungstenite::handshake::server::Callback for ConnectionCallback { None => cfg.internal_app_id, }, }; + if let Ok(APIGatewayServiceConnectionDisposition::Accept(service_id)) = + ApiGateway::is_apigateway_connection(request.uri()) + { + let service_connection = ServiceConnection { service_id }; + *cfg.service_connection.lock().unwrap() = Some(service_connection); + }; let session_id = match app_id_opt { Some(_) => Uuid::new_v4().to_string(), // can unwrap here because if session is not given, then error will be returned @@ -194,34 +206,75 @@ impl FireboltWs { // Let's spawn the handling of each connection in a separate task. while let Ok((stream, client_addr)) = listener.accept().await { let (connect_tx, connect_rx) = oneshot::channel::(); + let service_connection_state = Arc::new(Mutex::new(None)); let cfg = ConnectionCallbackConfig { next: connect_tx, app_state: app_state.clone(), secure, internal_app_id: internal_app_id.clone(), + service_connection: service_connection_state.clone(), }; match tokio_tungstenite::accept_hdr_async(stream, ConnectionCallback(cfg)).await { Err(e) => { error!("websocket connection error {:?}", e); } Ok(ws_stream) => { - trace!("websocket connection success"); - let state_for_connection_c = state_for_connection.clone(); - tokio::spawn(async move { - FireboltWs::handle_connection( - client_addr, - ws_stream, - connect_rx, - state_for_connection_c.clone(), - secure, - ) - .await; - }); + let connection = service_connection_state.clone(); + let service_connection_state = connection.lock().unwrap().clone(); + match service_connection_state { + Some(service_connection) => { + let service_connection = service_connection.clone(); + let service_id = service_connection.service_id.clone(); + + info!("Service connection for service_id={:?}", service_id); + let state_for_connection_c = state_for_connection.clone(); + tokio::spawn(async move { + FireboltWs::handle_service_connection( + client_addr, + ws_stream, + connect_rx, + state_for_connection_c.clone(), + secure, + ) + .await; + }); + } + None => { + let state_for_connection_c = state_for_connection.clone(); + tokio::spawn(async move { + FireboltWs::handle_connection( + client_addr, + ws_stream, + connect_rx, + state_for_connection_c.clone(), + secure, + ) + .await; + }); + } + } } } } } - + async fn handle_service_connection( + _client_addr: SocketAddr, + ws_stream: WebSocketStream, + connect_rx: oneshot::Receiver, + state: PlatformState, + gateway_secure: bool, + ) { + info!("handle_service_connection"); + let (mut send, mut recv) = ws_stream.split(); + let identity = connect_rx.await.unwrap(); + tokio::spawn(async move { + while let Some(api_message) = recv.next().await { + //nfo!("Received server request {}", api_message.jsonrpc_msg); + info!("Received server request {:?}", api_message); + send.send("item".into()).await; + } + }); + } async fn handle_connection( _client_addr: SocketAddr, ws_stream: WebSocketStream, From a0d15ad41dac90df3da3d214385cce0f672ac585 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Wed, 7 May 2025 17:24:04 -0700 Subject: [PATCH 02/46] } --- Cargo.lock | 12 +- .../bootstrap/start_communication_broker.rs | 6 +- core/main/src/bootstrap/start_ws_step.rs | 25 +- core/main/src/broker/endpoint_broker.rs | 116 +- core/main/src/broker/mod.rs | 1 + core/main/src/broker/rules_engine.rs | 1417 ++++++++--------- core/main/src/broker/service_broker.rs | 31 + .../src/broker/thunder/user_data_migrator.rs | 10 +- core/main/src/broker/workflow_broker.rs | 39 +- core/main/src/firebolt/firebolt_gateway.rs | 19 +- core/main/src/firebolt/firebolt_ws.rs | 47 +- .../apps/delegated_launcher_handler.rs | 2 + core/main/src/state/bootstrap_state.rs | 28 +- core/main/src/state/platform_state.rs | 48 +- core/sdk/Cargo.toml | 4 + core/sdk/src/api/mod.rs | 1 + core/sdk/src/api/rules_engine/mod.rs | 785 +++++++++ 17 files changed, 1775 insertions(+), 816 deletions(-) create mode 100644 core/main/src/broker/service_broker.rs create mode 100644 core/sdk/src/api/rules_engine/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 939a6a213..c33c91096 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2113,9 +2113,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "value-bag", ] @@ -3377,6 +3377,10 @@ dependencies = [ "fern", "futures", "futures-channel", + "jaq-core", + "jaq-interpret", + "jaq-parse", + "jaq-std", "jsonrpsee", "lazy_static", "libloading", @@ -3867,14 +3871,18 @@ name = "ssda_service" version = "0.1.0" dependencies = [ "async-trait", + "futures-util", "http 0.2.12", + "log", "mockall", + "ripple_sdk", "serde_json", "ssda_client", "ssda_types", "tokio", "tokio-tungstenite 0.20.1", "url", + "uuid", ] [[package]] diff --git a/core/main/src/bootstrap/start_communication_broker.rs b/core/main/src/bootstrap/start_communication_broker.rs index 26a8279a3..024485334 100644 --- a/core/main/src/bootstrap/start_communication_broker.rs +++ b/core/main/src/bootstrap/start_communication_broker.rs @@ -46,7 +46,7 @@ impl Bootstep for StartCommunicationBroker { } // Setup the endpoints from the manifests let mut endpoint_state = ps.clone().endpoint_state; - endpoint_state.build_thunder_endpoint(); + endpoint_state.build_thunder_endpoint().await; Ok(()) } } @@ -67,7 +67,9 @@ impl Bootstep for StartOtherBrokers { } // Setup the endpoints from the manifests let mut endpoint_state = ps.clone().endpoint_state; - endpoint_state.build_other_endpoints(ps.clone(), ps.session_state.get_account_session()); + endpoint_state + .build_other_endpoints(ps.clone(), ps.session_state.get_account_session()) + .await; Ok(()) } } diff --git a/core/main/src/bootstrap/start_ws_step.rs b/core/main/src/bootstrap/start_ws_step.rs index 512c53a89..c5d90b22f 100644 --- a/core/main/src/bootstrap/start_ws_step.rs +++ b/core/main/src/bootstrap/start_ws_step.rs @@ -19,9 +19,11 @@ use ripple_sdk::{ async_trait::async_trait, framework::bootstrap::Bootstep, tokio, utils::error::RippleError, }; +use crate::firebolt::handlers::audio_description_rpc; use crate::state::bootstrap_state::BootstrapState; use crate::firebolt::firebolt_ws::FireboltWs; +use crate::state::openrpc_state::ApiSurface; pub struct StartWsStep; @@ -37,19 +39,38 @@ impl Bootstep for StartWsStep { let ws_enabled = manifest.get_web_socket_enabled(); let internal_ws_enabled = manifest.get_internal_ws_enabled(); let iai_c = iai.clone(); + if ws_enabled { + let api_gateway_state_ws = state.platform_state.services_gateway_api.clone(); let ws_addr = manifest.get_ws_gateway_host(); let state_for_ws = state.platform_state.clone(); + tokio::spawn(async move { - FireboltWs::start(ws_addr.as_str(), state_for_ws, true, iai.clone()).await; + FireboltWs::start( + ws_addr.as_str(), + state_for_ws, + true, + iai.clone(), + api_gateway_state_ws, + ) + .await; }); } if internal_ws_enabled { + let api_gateway_state_internal_ws = state.platform_state.services_gateway_api.clone(); + let ws_addr = manifest.get_internal_gateway_host(); let state_for_ws = state.platform_state; tokio::spawn(async move { - FireboltWs::start(ws_addr.as_str(), state_for_ws, false, iai_c).await; + FireboltWs::start( + ws_addr.as_str(), + state_for_ws, + false, + iai_c, + api_gateway_state_internal_ws, + ) + .await; }); } diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index c1e7bb66d..92694bccd 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -15,6 +15,7 @@ // SPDX-License-Identifier: Apache-2.0 // +use ripple_sdk::tokio::sync::RwLock as TokioRwLock; use ripple_sdk::{ api::{ firebolt::fb_capabilities::{ @@ -25,6 +26,10 @@ use ripple_sdk::{ RpcRequest, RPC_V2, }, observability::log_signal::LogSignal, + rules_engine::{ + jq_compile, Rule, RuleEndpoint, RuleEndpointProtocol, RuleEngine, RuleEngineProvider, + RuleRetrievalError, RuleRetrieved, RuleTransformType, RuleType, + }, session::AccountSession, }, extn::extn_client_message::{ExtnEvent, ExtnMessage}, @@ -37,11 +42,12 @@ use ripple_sdk::{ utils::error::RippleError, }; use serde_json::{json, Value}; +use std::sync::RwLock; use std::{ collections::HashMap, sync::{ atomic::{AtomicU64, Ordering}, - Arc, RwLock, + Arc, }, }; @@ -50,7 +56,9 @@ use crate::{ firebolt::firebolt_gateway::JsonRpcError, service::extn::ripple_client::RippleClient, state::{ - ops_metrics_state::OpMetricState, platform_state::PlatformState, session_state::Session, + ops_metrics_state::OpMetricState, + platform_state::{self, PlatformState}, + session_state::Session, }, utils::router_utils::{ add_telemetry_status_code, capture_stage, get_rpc_header, return_extn_response, @@ -62,10 +70,7 @@ use super::{ extn_broker::ExtnBroker, http_broker::HttpBroker, provider_broker_state::{ProvideBrokerState, ProviderResult}, - rules_engine::{ - jq_compile, Rule, RuleEndpoint, RuleEndpointProtocol, RuleEngine, RuleRetrievalError, - RuleRetrieved, RuleType, - }, + service_broker::ServiceBroker, thunder_broker::ThunderBroker, websocket_broker::WebsocketBroker, workflow_broker::WorkflowBroker, @@ -363,18 +368,23 @@ impl BrokerSender { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct EndpointBrokerState { endpoint_map: Arc>>, callback: BrokerCallback, request_map: Arc>>, extension_request_map: Arc>>, - rule_engine: RuleEngine, + rule_engine: Arc>>, cleaner_list: Arc>>, reconnect_tx: Sender, provider_broker_state: ProvideBrokerState, metrics_state: OpMetricState, } +impl std::fmt::Debug for EndpointBrokerState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "EndpointBrokerState {{}}") + } +} #[derive(Debug)] pub enum HandleBrokerageError { @@ -460,7 +470,7 @@ impl Default for EndpointBrokerState { callback: BrokerCallback::default(), request_map: Arc::new(RwLock::new(HashMap::new())), extension_request_map: Arc::new(RwLock::new(HashMap::new())), - rule_engine: RuleEngine::default(), + rule_engine: Arc::new(TokioRwLock::new(Box::new(RuleEngine::default()))), cleaner_list: Arc::new(RwLock::new(Vec::new())), reconnect_tx: mpsc::channel(2).0, provider_broker_state: ProvideBrokerState::default(), @@ -473,7 +483,7 @@ impl EndpointBrokerState { pub fn new( metrics_state: OpMetricState, tx: Sender, - rule_engine: RuleEngine, + rule_engine: Arc>>, _ripple_client: RippleClient, ) -> Self { let (reconnect_tx, _rec_tr) = mpsc::channel(2); @@ -482,7 +492,7 @@ impl EndpointBrokerState { callback: BrokerCallback { sender: tx }, request_map: Arc::new(RwLock::new(HashMap::new())), extension_request_map: Arc::new(RwLock::new(HashMap::new())), - rule_engine, + rule_engine: rule_engine, cleaner_list: Arc::new(RwLock::new(Vec::new())), reconnect_tx, provider_broker_state: ProvideBrokerState::default(), @@ -493,16 +503,20 @@ impl EndpointBrokerState { state.reconnect_thread(_rec_tr, _ripple_client); state } - pub fn with_rules_engine(mut self, rule_engine: RuleEngine) -> Self { + pub fn with_rules_engine( + mut self, + rule_engine: Arc>>, + ) -> Self { self.rule_engine = rule_engine; self } - pub fn add_rule(mut self, rule: Rule) -> Self { - self.rule_engine.add_rule(rule); - self - } - pub fn has_rule(&self, rule: &str) -> bool { - self.rule_engine.has_rule(rule) + // pub fn add_rule(mut self, rule: Rule) -> Self { + // self.rule_engine.add_rule(rule); + // self + // } + pub async fn has_rule(&self, rule: &str) -> bool { + self.rule_engine.read().await.has_rule(rule) + //self.rule_engine.lock().has_rule(rule) } #[cfg(not(test))] fn reconnect_thread(&self, mut rx: Receiver, client: RippleClient) { @@ -586,7 +600,7 @@ impl EndpointBrokerState { if let Some(filter) = rpc_request .rule .transform - .get_transform_data(super::rules_engine::RuleTransformType::Request) + .get_transform_data(RuleTransformType::Request) { let transformed_request_res = jq_compile( last, @@ -705,8 +719,9 @@ impl EndpointBrokerState { telemetry_response_listeners, ) } - pub fn build_thunder_endpoint(&mut self) { - if let Some(endpoint) = self.rule_engine.rules.endpoints.get("thunder").cloned() { + pub async fn build_thunder_endpoint(&mut self) { + let rules = self.rule_engine.read().await.get_rules().clone(); + if let Some(endpoint) = rules.endpoints.get("thunder").cloned() { let request = BrokerConnectRequest::new( "thunder".to_owned(), endpoint.clone(), @@ -716,8 +731,13 @@ impl EndpointBrokerState { } } - pub fn build_other_endpoints(&mut self, ps: PlatformState, session: Option) { - for (key, endpoint) in self.rule_engine.rules.endpoints.clone() { + pub async fn build_other_endpoints( + &mut self, + ps: PlatformState, + session: Option, + ) { + let rules = self.rule_engine.read().await.get_rules().endpoints.clone(); + for (key, endpoint) in rules { // skip thunder endpoint as it is already built using build_thunder_endpoint if let RuleEndpointProtocol::Thunder = endpoint.protocol { continue; @@ -772,6 +792,10 @@ impl EndpointBrokerState { ExtnBroker::get_broker(ps, request, self.callback.clone(), self).get_sender(), None, ), + RuleEndpointProtocol::Service => { + let service_broker = ServiceBroker::new(ps.clone()); + (service_broker.get_sender(), None) + } }; self.add_endpoint(key, broker); @@ -850,15 +874,15 @@ impl EndpointBrokerState { fn get_sender(&self, hash: &str) -> Option { self.endpoint_map.read().unwrap().get(hash).cloned() } - fn get_broker_rule( + async fn get_broker_rule( &self, rpc_request: &RpcRequest, ) -> Result { - self.rule_engine.get_rule(rpc_request) + self.rule_engine.read().await.get_rule(rpc_request) } /// Main handler method whcih checks for brokerage and then sends the request for /// asynchronous processing - pub fn handle_brokerage( + pub async fn handle_brokerage( &self, rpc_request: RpcRequest, extn_message: Option, @@ -883,6 +907,7 @@ impl EndpointBrokerState { session, telemetry_response_listeners, ) + .await .is_ok() } @@ -937,12 +962,12 @@ impl EndpointBrokerState { let rpc_request = broker_request.rpc.clone(); match rule.rule_type() { - super::rules_engine::RuleType::Static => { + RuleType::Static => { let response = RenderedRequest::JsonRpc(self.handle_static_request(rpc_request.clone())); Ok(response) } - super::rules_engine::RuleType::Provider => { + RuleType::Provider => { let response = self.handle_provided_request( &rpc_request, rpc_request.ctx.call_id, @@ -951,7 +976,7 @@ impl EndpointBrokerState { ); Ok(response) } - super::rules_engine::RuleType::Endpoint => { + RuleType::Endpoint => { if rpc_request.is_unlisten() { Ok(RenderedRequest::Unlisten(broker_request.clone())) } else { @@ -961,7 +986,7 @@ impl EndpointBrokerState { } } - pub fn handle_brokerage_workflow( + pub async fn handle_brokerage_workflow( &self, rpc_request: RpcRequest, extn_message: Option, @@ -971,7 +996,7 @@ impl EndpointBrokerState { telemetry_response_listeners: Vec>, ) -> Result { /*if rule not found, "unhandled https://github.com/rdkcentral/Ripple/blob/ae3fcd78b055cf70022959bf827de9ed569762aa/core/main/src/broker/endpoint_broker.rs#L719" */ - let rule: Rule = match self.get_broker_rule(&rpc_request)? { + let rule: Rule = match self.get_broker_rule(&rpc_request).await? { RuleRetrieved::ExactMatch(rule) | RuleRetrieved::WildcardMatch(rule) => rule, }; /* @@ -1091,8 +1116,11 @@ impl EndpointBrokerState { } } - pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { - self.rule_engine.get_rule(rpc_request) + pub async fn get_rule( + &self, + rpc_request: &RpcRequest, + ) -> Result { + self.rule_engine.read().await.get_rule(rpc_request) } // Method to cleanup all subscription on App termination @@ -1162,7 +1190,7 @@ pub trait EndpointBroker { if let Some(filter) = rpc_request .rule .transform - .get_transform_data(super::rules_engine::RuleTransformType::Request) + .get_transform_data(RuleTransformType::Request) { let transformed_request_res = jq_compile( last, @@ -1304,12 +1332,12 @@ impl BrokerOutputForwarder { continue; } - if let Some(filter) = - broker_request.rule.transform.get_transform_data( - super::rules_engine::RuleTransformType::Event( - rpc_request.ctx.context.contains(&RPC_V2.into()), - ), - ) + if let Some(filter) = broker_request + .rule + .transform + .get_transform_data(RuleTransformType::Event( + rpc_request.ctx.context.contains(&RPC_V2.into()), + )) { apply_rule_for_event( &broker_request, @@ -1426,10 +1454,10 @@ impl BrokerOutputForwarder { } } if apply_response_using_main_req_needed { - if let Some(filter) = - broker_request.rule.transform.get_transform_data( - super::rules_engine::RuleTransformType::Response, - ) + if let Some(filter) = broker_request + .rule + .transform + .get_transform_data(RuleTransformType::Response) { apply_response(filter, &rule_context_name, &mut response); } else if response.result.is_none() && response.error.is_none() { diff --git a/core/main/src/broker/mod.rs b/core/main/src/broker/mod.rs index 9abc434b8..d4e44bce6 100644 --- a/core/main/src/broker/mod.rs +++ b/core/main/src/broker/mod.rs @@ -21,6 +21,7 @@ pub mod extn_broker; pub mod http_broker; pub mod provider_broker_state; pub mod rules_engine; +pub mod service_broker; #[cfg(test)] pub mod test; pub mod thunder; diff --git a/core/main/src/broker/rules_engine.rs b/core/main/src/broker/rules_engine.rs index 270efedfe..015682599 100644 --- a/core/main/src/broker/rules_engine.rs +++ b/core/main/src/broker/rules_engine.rs @@ -1,709 +1,708 @@ -// Copyright 2023 Comcast Cable Communications Management, LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 -// -use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val}; -use ripple_sdk::api::{ - gateway::rpc_gateway_api::RpcRequest, manifest::extn_manifest::ExtnManifest, -}; - -use ripple_sdk::{ - chrono::Utc, - log::{debug, error, info, trace, warn}, - serde_json::Value, - utils::error::RippleError, -}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -use std::{fs, path::Path}; - -#[derive(Debug, Deserialize, Default, Clone)] -pub struct RuleSet { - pub endpoints: HashMap, - pub rules: HashMap, -} - -impl RuleSet { - pub fn append(&mut self, rule_set: RuleSet) { - self.endpoints.extend(rule_set.endpoints); - let rules: HashMap = rule_set - .rules - .into_iter() - .map(|(k, v)| { - trace!("Loading JQ Rule for {}", k.to_lowercase()); - (k.to_lowercase(), v) - }) - .collect(); - self.rules.extend(rules); - } - pub fn get(&self, key: &str) -> Option<&Rule> { - self.rules.get(key) - } -} -#[derive(Debug, Deserialize, Clone, Default)] -pub struct RuleEndpoint { - pub protocol: RuleEndpointProtocol, - pub url: String, - #[serde(default = "default_autostart")] - pub jsonrpc: bool, -} - -impl RuleEndpoint { - pub fn get_url(&self) -> String { - if cfg!(feature = "local_dev") { - if let Ok(host_override) = std::env::var("DEVICE_HOST") { - if !host_override.is_empty() { - return self.url.replace("127.0.0.1", &host_override); - } - } - } - self.url.clone() - } -} - -fn default_autostart() -> bool { - true -} - -#[derive(Deserialize, Debug, Clone, Default)] -#[serde(rename_all = "lowercase")] -#[cfg_attr(test, derive(PartialEq))] -pub enum RuleEndpointProtocol { - #[default] - Websocket, - Http, - Thunder, - Workflow, - Extn, -} -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct JsonDataSource { - // configurable namespace to "stuff" an in individual result payload into - pub namespace: Option, - pub method: String, - pub params: Option, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct Rule { - pub alias: String, - // Not every rule needs transform - #[serde(default)] - pub transform: RuleTransform, - #[serde(skip_serializing_if = "Option::is_none")] - pub filter: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub event_handler: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub endpoint: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub sources: Option>, -} -impl std::fmt::Display for Rule { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Rule {{ alias: {} }}", self.alias) - } -} -/* -war on dots -*/ -#[derive(PartialEq)] -pub enum RuleType { - Static, - Provider, - Endpoint, -} -impl Rule { - fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { - self.transform.apply_context(rpc_request); - self - } - pub fn rule_type(&self) -> RuleType { - match self.alias.trim().to_ascii_lowercase().as_str() { - "static" => RuleType::Static, - "provided" => RuleType::Provider, - /* - maps to a sender that can be used to send a message to the endpoint, for instance: Thunder - */ - _ => RuleType::Endpoint, - } - } - pub fn with_alias(&mut self, alias: String) -> &mut Self { - self.alias = alias; - self - } - pub fn with_rule_tranformt(&mut self, transform: RuleTransform) -> &mut Self { - self.transform = transform; - self - } - pub fn with_filter(&mut self, filter: String) -> &mut Self { - self.filter = Some(filter); - self - } - pub fn with_event_handler(&mut self, event_handler: String) -> &mut Self { - self.event_handler = Some(event_handler); - self - } - pub fn with_endpoint(&mut self, endpoint: String) -> &mut Self { - self.endpoint = Some(endpoint); - self - } - pub fn with_sources(&mut self, sources: Vec) -> &mut Self { - self.sources = Some(sources); - self - } - pub fn with_source(&mut self, source: JsonDataSource) -> &mut Self { - if let Some(sources) = &mut self.sources { - sources.push(source); - } else { - self.sources = Some(vec![source]); - } - self - } -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct RuleTransform { - #[serde(skip_serializing_if = "Option::is_none")] - pub request: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub response: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub event: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub rpcv2_event: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub event_decorator_method: Option, -} - -impl RuleTransform { - fn check_and_replace(&self, input: &str, rpc_request: &RpcRequest) -> String { - trace!( - "check_and_replace: input: {}, rpc_request: {:?}", - input, - rpc_request - ); - - let mut output = input.replace("$context.appId", &rpc_request.ctx.app_id); - - if let Some(event) = &self.event { - output = output.replace("$event", event); - } - - output - } - - pub fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { - if let Some(value) = self.request.take() { - let _ = self - .request - .insert(self.check_and_replace(&value, rpc_request)); - } - - if let Some(value) = self.event.take() { - let _ = self - .event - .insert(self.check_and_replace(&value, rpc_request)); - } - - if let Some(value) = self.rpcv2_event.take() { - let _ = self - .rpcv2_event - .insert(self.check_and_replace(&value, rpc_request)); - } - self - } - - pub fn get_transform_data(&self, typ: RuleTransformType) -> Option { - match typ { - RuleTransformType::Request => self.request.clone(), - RuleTransformType::Event(rpc_v2) => { - if rpc_v2 { - self.rpcv2_event.clone() - } else { - self.event.clone() - } - } - RuleTransformType::Response => self.response.clone(), - } - } -} - -pub enum RuleTransformType { - Request, - Response, - Event(bool), -} - -#[derive(Debug, Clone, Default)] -pub struct RuleEngine { - pub rules: RuleSet, -} - -impl RuleEngine { - fn build_path(path: &str, default_path: &str) -> String { - if path.starts_with('/') { - path.to_owned() - } else { - format!("{}{}", default_path, path) - } - } - - pub fn load(path: &str) -> Result { - let path = Path::new(path); - if path.exists() { - let contents = fs::read_to_string(path).unwrap(); - Self::load_from_string_literal(contents) - } else { - warn!("path for the rule is invalid {}", path.display()); - Err(RippleError::InvalidInput) - } - } - pub fn load_from_string_literal(contents: String) -> Result { - let (_content, rule_set) = Self::load_from_content(contents)?; - let mut rules_engine = RuleEngine::default(); - rules_engine.rules.append(rule_set); - Ok(rules_engine.clone()) - } - - pub fn build(extn_manifest: &ExtnManifest) -> Self { - trace!("building rules engine {:?}", extn_manifest.rules_path); - let mut engine = RuleEngine::default(); - for path in extn_manifest.rules_path.iter() { - let path_for_rule = Self::build_path(path, &extn_manifest.default_path); - debug!("loading rules file {}", path_for_rule); - if let Some(p) = Path::new(&path_for_rule).to_str() { - if let Ok(contents) = fs::read_to_string(p) { - info!("Rules content {}", contents); - info!("loading rules from path {}", path); - info!("loading rule {}", path_for_rule); - if let Ok((_, rule_set)) = Self::load_from_content(contents) { - engine.rules.append(rule_set) - } else { - warn!("invalid rule found in path {}", path) - } - } else { - warn!("path for the rule is invalid {}", path) - } - } else { - warn!("invalid rule path {}", path) - } - } - engine - } - - pub fn load_from_content(contents: String) -> Result<(String, RuleSet), RippleError> { - match serde_json::from_str::(&contents) { - Ok(manifest) => Ok((contents, manifest)), - Err(err) => { - error!("{:?} could not load rule", err); - Err(RippleError::InvalidInput) - } - } - } - pub fn add_rules(&mut self, rules: RuleSet) { - self.rules.append(rules); - } - pub fn add_rule(&mut self, rule: Rule) { - self.rules.rules.insert(rule.alias.clone(), rule); - } - - pub fn has_rule(&self, request: &str) -> bool { - self.rules.rules.contains_key(&request.to_lowercase()) - } - fn wildcard_match(rule_name: &str, method: &str) -> bool { - rule_name.ends_with(".*") && method.starts_with(&rule_name[..rule_name.len() - 2]) - } - fn find_wildcard_rule( - rules: &HashMap, - method: &str, - ) -> Result { - let filtered_rules: Vec<&Rule> = rules - .iter() - .filter(|(rule_name, _)| Self::wildcard_match(rule_name, method)) - .map(|(_, rule)| rule) - .collect(); - - match filtered_rules.len() { - 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), - 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), - _ => Err(RuleRetrievalError::TooManyWildcardMatches), - } - } - - pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { - let method = rpc_request.method.to_lowercase(); - /* - match directly from method name - */ - - if let Some(mut rule) = self.rules.get(&method).cloned() { - return Ok(RuleRetrieved::ExactMatch( - rule.apply_context(rpc_request).to_owned(), - )); - } else { - /* - * match, for example api.v1.* as rule name and api.v1.get as method name - */ - Self::find_wildcard_rule(&self.rules.rules, &method) - } - } - - pub fn get_rule_by_method(&self, method: &str) -> Option { - self.rules.rules.get(&method.to_lowercase()).cloned() - } -} -#[derive(Debug)] -pub enum RuleRetrieved { - ExactMatch(Rule), - WildcardMatch(Rule), -} -impl From for Rule { - fn from(rule_retrieved: RuleRetrieved) -> Self { - match rule_retrieved { - RuleRetrieved::ExactMatch(rule) => rule, - RuleRetrieved::WildcardMatch(rule) => rule, - } - } -} - -#[derive(Debug)] -pub enum RuleRetrievalError { - RuleNotFound(String), - RuleNotFoundAsWildcard, - TooManyWildcardMatches, -} - -/// Compiles and executes a JQ filter on a given JSON input value. -/// -/// # Arguments -/// -/// * `input` - A `serde_json::Value` representing the JSON input to be processed. -/// * `filter` - A string slice that holds the JQ filter to be applied. -/// * `reference` - A string used for logging purposes to identify the rule being processed. -/// -/// # Returns -/// -/// * `Ok(Value)` - If the filter is successfully compiled and executed, returns the resulting JSON value. -/// * `Err(RippleError)` - If there is an error during the compilation or execution of the filter, returns a `RippleError`. -/// -/// # Errors -/// -/// This function will return an error if: -/// * The JQ filter contains syntax errors. -/// * There are errors during the compilation of the filter. -/// * The execution of the filter does not produce a valid output. -/// -/// # Example -/// -/// ``` -/// use serde_json::json; -/// use ripple_sdk::utils::error::RippleError; -/// use crate::jq_compile; -/// -/// let filter = "if .success then .stbVersion else { code: -32100, message: \"couldn't get version\" } end"; -/// let input = json!({ -/// "stbVersion": "SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", -/// "success": true -/// }); -/// let result = jq_compile(input, filter, String::new()); -/// assert_eq!(result.unwrap(), json!("SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT")); -/// ``` -pub fn jq_compile(input: Value, filter: &str, reference: String) -> Result { - info!( - "Jq rule {} input {:?}, reference {}", - filter, input, reference - ); - let start = Utc::now().timestamp_millis(); - // start out only from core filters, - // which do not include filters in the standard library - // such as `map`, `select` etc. - - let mut defs = ParseCtx::new(Vec::new()); - defs.insert_natives(jaq_core::core()); - defs.insert_defs(jaq_std::std()); - // parse the filter - let (f, errs) = jaq_parse::parse(filter, jaq_parse::main()); - if !errs.is_empty() { - error!("Error in rule {:?}", errs); - return Err(RippleError::RuleError); - } - // compile the filter in the context of the given definitions - let f = defs.compile(f.unwrap()); - if !defs.errs.is_empty() { - error!("Error in rule {}", reference); - for (err, _) in defs.errs { - error!("reference={} {}", reference, err); - } - return Err(RippleError::RuleError); - } - - let inputs = RcIter::new(core::iter::empty()); - // iterator over the output values - let mut out = f.run((Ctx::new([], &inputs), Val::from(input))); - if let Some(Ok(v)) = out.next() { - info!( - "Ripple Gateway Rule Processing Time: {},{}", - reference, - Utc::now().timestamp_millis() - start - ); - return Ok(Value::from(v)); - } - - Err(RippleError::ParseError) -} -pub fn compose_json_values(values: Vec) -> Value { - if values.len() == 1 { - return values[0].clone(); - } - debug!("Composing values {:?}", values); - - let mut composition_filter = ".[0]".to_string(); - for v in 1..values.len() { - composition_filter = format!("{} * .[{}]", composition_filter, v); - } - match jq_compile(Value::Array(values), &composition_filter, String::new()) { - Ok(composed_value) => composed_value, - Err(err) => { - error!("Failed to compose JSON values with error: {:?}", err); - Value::Null // Return a default value on failure - } - } -} -pub fn make_name_json_safe(name: &str) -> String { - name.replace([' ', '.', ','], "_") -} - -#[cfg(test)] -mod tests { - use super::*; - use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; - use ripple_sdk::serde_json::json; - - #[test] - fn test_jq_compile() { - let filter = "if .success then ( .stbVersion | split(\"_\")[0] ) else { code: -32100, message: \"couldn't get version\" } end"; - let input = json!({ - "stbVersion":"SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", - "receiverVersion":"7.2.0.0", - "stbTimestamp":"Thu 20 Jun 2024 14:00:24 UTC", - "success":true - }); - let resp = jq_compile(input, filter, String::new()); - assert_eq!(resp.unwrap(), "SCXI11BEI".to_string()); - - let filter = "{ namespace: \"refui\", scope: .scope, key: .key, value: .value }"; - let input = json!({ - "key": "key3", - "scope": "account", - "value": "value2" - }); - let resp = jq_compile(input, filter, String::new()); - let expected = json!({ - "namespace": "refui", - "key": "key3", - "scope": "account", - "value": "value2" - }); - assert_eq!(resp.unwrap(), expected); - - let filter = "if .success and ( .supportedHDCPVersion | contains(\"2.2\")) then {\"hdcp2.2\": true} elif .success and ( .supportedHDCPVersion | contains(\"1.4\")) then {\"hdcp1.4\": true} else {\"code\": -32100, \"message\": \"couldn't get version\"} end"; - let input = json!({ - "supportedHDCPVersion":"2.2", - "isHDCPSupported":true, - "success":true - }); - let resp = jq_compile(input, filter, String::new()); - let expected = json!({ - "hdcp2.2": true - }); - assert_eq!(resp.unwrap(), expected); - - let filter = "if .success then (.value | fromjson | .value) else { \"code\": -32100, \"message\": \"couldn't get language\" } end"; - let input = json!({ - "value": "{\"update_time\":\"2024-07-26T23:39:57.831726080Z\",\"value\":\"EN\"}", - "success":true - }); - let resp = jq_compile(input, filter, String::new()); - assert_eq!(resp.unwrap(), "EN".to_string()); - } - #[test] - fn test_composed_jq_compile() { - let a = json!({"asome": "avalue"}); - let b = json!({"bsome": "bvalue"}); - let c = json!({"csome": {"cvalue" : "nested"}}); - let vals = vec![a, b, c]; - let mut composition_filter = ".[0]".to_string(); - for v in 1..vals.len() { - composition_filter = format!("{} * .[{}]", composition_filter, v); - } - - assert!(jq_compile( - jq_compile( - Value::Array(vals.clone()), - &composition_filter, - String::new() - ) - .unwrap(), - ".asome", - String::new() - ) - .unwrap() - .as_str() - .unwrap() - .contains("avalue")); - assert!(jq_compile( - jq_compile( - Value::Array(vals.clone()), - &composition_filter, - String::new() - ) - .unwrap(), - ".bsome", - String::new() - ) - .unwrap() - .as_str() - .unwrap() - .contains("bvalue")); - assert!(jq_compile( - jq_compile( - Value::Array(vals.clone()), - &composition_filter, - String::new() - ) - .unwrap(), - ".csome.cvalue", - String::new() - ) - .unwrap() - .as_str() - .unwrap() - .contains("nested")); - } - use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; - - #[test] - fn test_get_rule_exact_match() { - let mut rule_set = RuleSet::default(); - let rule = Rule { - alias: "test_rule".to_string(), - ..Default::default() - }; - rule_set - .rules - .insert("test.method".to_string(), rule.clone()); - - let rule_engine = RuleEngine { rules: rule_set }; - - let rpc_request = RpcRequest { - method: "test.method".to_string(), - ctx: CallContext { - app_id: "test_app".to_string(), - method: "test.method".to_string(), - ..Default::default() - }, - ..Default::default() - }; - - let result = rule_engine.get_rule(&rpc_request); - match result { - Ok(RuleRetrieved::ExactMatch(retrieved_rule)) => { - assert_eq!(retrieved_rule.alias, rule.alias); - } - _ => panic!("Expected exact match, but got {:?}", result), - } - } - - #[test] - fn test_get_rule_wildcard_match() { - let mut rule_set = RuleSet::default(); - let rule = Rule { - alias: "wildcard_rule".to_string(), - ..Default::default() - }; - rule_set.rules.insert("api.v1.*".to_string(), rule.clone()); - - let rule_engine = RuleEngine { rules: rule_set }; - - let rpc_request = RpcRequest { - method: "api.v1.get".to_string(), - ctx: CallContext { - app_id: "test_app".to_string(), - method: "api.v1.get".to_string(), - ..Default::default() - }, - ..Default::default() - }; - - let result = rule_engine.get_rule(&rpc_request); - match result { - Ok(RuleRetrieved::WildcardMatch(retrieved_rule)) => { - assert_eq!(retrieved_rule.alias, rule.alias); - } - _ => panic!("Expected wildcard match, but got {:?}", result), - } - } - - #[test] - fn test_get_rule_no_match() { - let rule_set = RuleSet::default(); - let rule_engine = RuleEngine { rules: rule_set }; - - let rpc_request = RpcRequest { - method: "nonexistent.method".to_string(), - ctx: CallContext { - app_id: "test_app".to_string(), - method: "nonexistent.method".to_string(), - ..Default::default() - }, - ..Default::default() - }; - - let result = rule_engine.get_rule(&rpc_request); - assert!(matches!( - result, - Err(RuleRetrievalError::RuleNotFoundAsWildcard) - )); - } - - #[test] - fn test_get_rule_multiple_wildcard_matches() { - let mut rule_set = RuleSet::default(); - rule_set - .rules - .insert("api.v1.*".to_string(), Rule::default()); - rule_set.rules.insert("api.*".to_string(), Rule::default()); - - let rule_engine = RuleEngine { rules: rule_set }; - - let rpc_request = RpcRequest { - method: "api.v1.get".to_string(), - ctx: CallContext { - app_id: "test_app".to_string(), - method: "api.v1.get".to_string(), - ..Default::default() - }, - ..Default::default() - }; - - let result = rule_engine.get_rule(&rpc_request); - assert!(matches!( - result, - Err(RuleRetrievalError::TooManyWildcardMatches) - )); - } -} +// // Copyright 2023 Comcast Cable Communications Management, LLC +// // +// // Licensed under the Apache License, Version 2.0 (the "License"); +// // you may not use this file except in compliance with the License. +// // You may obtain a copy of the License at +// // +// // http://www.apache.org/licenses/LICENSE-2.0 +// // +// // Unless required by applicable law or agreed to in writing, software +// // distributed under the License is distributed on an "AS IS" BASIS, +// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// // See the License for the specific language governing permissions and +// // limitations under the License. +// // +// // SPDX-License-Identifier: Apache-2.0 +// // +// use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val}; +// use ripple_sdk::api::{ +// gateway::rpc_gateway_api::RpcRequest, manifest::extn_manifest::ExtnManifest, +// }; + +// use ripple_sdk::{ +// chrono::Utc, +// log::{debug, error, info, trace, warn}, +// serde_json::Value, +// utils::error::RippleError, +// }; +// use serde::{Deserialize, Serialize}; +// use std::collections::HashMap; + +// use std::{fs, path::Path}; + +// #[derive(Debug, Deserialize, Default, Clone)] +// pub struct RuleSet { +// pub endpoints: HashMap, +// pub rules: HashMap, +// } + +// impl RuleSet { +// pub fn append(&mut self, rule_set: RuleSet) { +// self.endpoints.extend(rule_set.endpoints); +// let rules: HashMap = rule_set +// .rules +// .into_iter() +// .map(|(k, v)| { +// trace!("Loading JQ Rule for {}", k.to_lowercase()); +// (k.to_lowercase(), v) +// }) +// .collect(); +// self.rules.extend(rules); +// } +// pub fn get(&self, key: &str) -> Option<&Rule> { +// self.rules.get(key) +// } +// } +// #[derive(Debug, Deserialize, Clone, Default)] +// pub struct RuleEndpoint { +// pub protocol: RuleEndpointProtocol, +// pub url: String, +// #[serde(default = "default_autostart")] +// pub jsonrpc: bool, +// } + +// impl RuleEndpoint { +// pub fn get_url(&self) -> String { +// if cfg!(feature = "local_dev") { +// if let Ok(host_override) = std::env::var("DEVICE_HOST") { +// if !host_override.is_empty() { +// return self.url.replace("127.0.0.1", &host_override); +// } +// } +// } +// self.url.clone() +// } +// } + +// fn default_autostart() -> bool { +// true +// } + +// #[derive(Deserialize, Debug, Clone, Default)] +// #[serde(rename_all = "lowercase")] +// #[cfg_attr(test, derive(PartialEq))] +// pub enum RuleEndpointProtocol { +// #[default] +// Websocket, +// Http, +// Thunder, +// Workflow, +// Extn, +// } +// #[derive(Debug, Default, Clone, Serialize, Deserialize)] +// pub struct JsonDataSource { +// // configurable namespace to "stuff" an in individual result payload into +// pub namespace: Option, +// pub method: String, +// pub params: Option, +// } + +// #[derive(Debug, Default, Clone, Serialize, Deserialize)] +// pub struct Rule { +// pub alias: String, +// // Not every rule needs transform +// #[serde(default)] +// pub transform: RuleTransform, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub filter: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub event_handler: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub endpoint: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub sources: Option>, +// } +// impl std::fmt::Display for Rule { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// write!(f, "Rule {{ alias: {} }}", self.alias) +// } +// } +// /* +// war on dots +// */ +// #[derive(PartialEq)] +// pub enum RuleType { +// Static, +// Provider, +// Endpoint, +// } +// impl Rule { +// fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { +// self.transform.apply_context(rpc_request); +// self +// } +// pub fn rule_type(&self) -> RuleType { +// match self.alias.trim().to_ascii_lowercase().as_str() { +// "static" => RuleType::Static, +// "provided" => RuleType::Provider, +// /* +// maps to a sender that can be used to send a message to the endpoint, for instance: Thunder +// */ +// _ => RuleType::Endpoint, +// } +// } +// pub fn with_alias(&mut self, alias: String) -> &mut Self { +// self.alias = alias; +// self +// } +// pub fn with_rule_tranformt(&mut self, transform: RuleTransform) -> &mut Self { +// self.transform = transform; +// self +// } +// pub fn with_filter(&mut self, filter: String) -> &mut Self { +// self.filter = Some(filter); +// self +// } +// pub fn with_event_handler(&mut self, event_handler: String) -> &mut Self { +// self.event_handler = Some(event_handler); +// self +// } +// pub fn with_endpoint(&mut self, endpoint: String) -> &mut Self { +// self.endpoint = Some(endpoint); +// self +// } +// pub fn with_sources(&mut self, sources: Vec) -> &mut Self { +// self.sources = Some(sources); +// self +// } +// pub fn with_source(&mut self, source: JsonDataSource) -> &mut Self { +// if let Some(sources) = &mut self.sources { +// sources.push(source); +// } else { +// self.sources = Some(vec![source]); +// } +// self +// } +// } + +// #[derive(Debug, Default, Clone, Serialize, Deserialize)] +// pub struct RuleTransform { +// #[serde(skip_serializing_if = "Option::is_none")] +// pub request: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub response: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub event: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub rpcv2_event: Option, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub event_decorator_method: Option, +// } + +// impl RuleTransform { +// fn check_and_replace(&self, input: &str, rpc_request: &RpcRequest) -> String { +// trace!( +// "check_and_replace: input: {}, rpc_request: {:?}", +// input, +// rpc_request +// ); + +// let mut output = input.replace("$context.appId", &rpc_request.ctx.app_id); + +// if let Some(event) = &self.event { +// output = output.replace("$event", event); +// } + +// output +// } + +// pub fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { +// if let Some(value) = self.request.take() { +// let _ = self +// .request +// .insert(self.check_and_replace(&value, rpc_request)); +// } + +// if let Some(value) = self.event.take() { +// let _ = self +// .event +// .insert(self.check_and_replace(&value, rpc_request)); +// } + +// if let Some(value) = self.rpcv2_event.take() { +// let _ = self +// .rpcv2_event +// .insert(self.check_and_replace(&value, rpc_request)); +// } +// self +// } + +// pub fn get_transform_data(&self, typ: RuleTransformType) -> Option { +// match typ { +// RuleTransformType::Request => self.request.clone(), +// RuleTransformType::Event(rpc_v2) => { +// if rpc_v2 { +// self.rpcv2_event.clone() +// } else { +// self.event.clone() +// } +// } +// RuleTransformType::Response => self.response.clone(), +// } +// } +// } + +// pub enum RuleTransformType { +// Request, +// Response, +// Event(bool), +// } + +// #[derive(Debug, Clone, Default)] +// pub struct RuleEngine { +// pub rules: RuleSet, +// } + +// impl RuleEngine { +// fn build_path(path: &str, default_path: &str) -> String { +// if path.starts_with('/') { +// path.to_owned() +// } else { +// format!("{}{}", default_path, path) +// } +// } + +// pub fn load(path: &str) -> Result { +// let path = Path::new(path); +// if path.exists() { +// let contents = fs::read_to_string(path).unwrap(); +// Self::load_from_string_literal(contents) +// } else { +// warn!("path for the rule is invalid {}", path.display()); +// Err(RippleError::InvalidInput) +// } +// } +// pub fn load_from_string_literal(contents: String) -> Result { +// let (_content, rule_set) = Self::load_from_content(contents)?; +// let mut rules_engine = RuleEngine::default(); +// rules_engine.rules.append(rule_set); +// Ok(rules_engine.clone()) +// } + +// pub fn build(extn_manifest: &ExtnManifest) -> Self { +// trace!("building rules engine {:?}", extn_manifest.rules_path); +// let mut engine = RuleEngine::default(); +// for path in extn_manifest.rules_path.iter() { +// let path_for_rule = Self::build_path(path, &extn_manifest.default_path); +// debug!("loading rules file {}", path_for_rule); +// if let Some(p) = Path::new(&path_for_rule).to_str() { +// if let Ok(contents) = fs::read_to_string(p) { +// info!("Rules content {}", contents); +// info!("loading rules from path {}", path); +// info!("loading rule {}", path_for_rule); +// if let Ok((_, rule_set)) = Self::load_from_content(contents) { +// engine.rules.append(rule_set) +// } else { +// warn!("invalid rule found in path {}", path) +// } +// } else { +// warn!("path for the rule is invalid {}", path) +// } +// } else { +// warn!("invalid rule path {}", path) +// } +// } +// engine +// } + +// pub fn load_from_content(contents: String) -> Result<(String, RuleSet), RippleError> { +// match serde_json::from_str::(&contents) { +// Ok(manifest) => Ok((contents, manifest)), +// Err(err) => { +// error!("{:?} could not load rule", err); +// Err(RippleError::InvalidInput) +// } +// } +// } +// pub fn add_rules(&mut self, rules: RuleSet) { +// self.rules.append(rules); +// } +// pub fn add_rule(&mut self, rule: Rule) { +// self.rules.rules.insert(rule.alias.clone(), rule); +// } + +// pub fn has_rule(&self, request: &str) -> bool { +// self.rules.rules.contains_key(&request.to_lowercase()) +// } +// fn wildcard_match(rule_name: &str, method: &str) -> bool { +// rule_name.ends_with(".*") && method.starts_with(&rule_name[..rule_name.len() - 2]) +// } +// fn find_wildcard_rule( +// rules: &HashMap, +// method: &str, +// ) -> Result { +// let filtered_rules: Vec<&Rule> = rules +// .iter() +// .filter(|(rule_name, _)| Self::wildcard_match(rule_name, method)) +// .map(|(_, rule)| rule) +// .collect(); + +// match filtered_rules.len() { +// 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), +// 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), +// _ => Err(RuleRetrievalError::TooManyWildcardMatches), +// } +// } + +// pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { +// let method = rpc_request.method.to_lowercase(); +// /* +// match directly from method name +// */ +// if let Some(mut rule) = self.rules.get(&method).cloned() { +// return Ok(RuleRetrieved::ExactMatch( +// rule.apply_context(rpc_request).to_owned(), +// )); +// } else { +// /* +// * match, for example api.v1.* as rule name and api.v1.get as method name +// */ +// Self::find_wildcard_rule(&self.rules.rules, &method) +// } +// } + +// pub fn get_rule_by_method(&self, method: &str) -> Option { +// self.rules.rules.get(&method.to_lowercase()).cloned() +// } +// } +// #[derive(Debug)] +// pub enum RuleRetrieved { +// ExactMatch(Rule), +// WildcardMatch(Rule), +// } +// impl From for Rule { +// fn from(rule_retrieved: RuleRetrieved) -> Self { +// match rule_retrieved { +// RuleRetrieved::ExactMatch(rule) => rule, +// RuleRetrieved::WildcardMatch(rule) => rule, +// } +// } +// } + +// #[derive(Debug)] +// pub enum RuleRetrievalError { +// RuleNotFound(String), +// RuleNotFoundAsWildcard, +// TooManyWildcardMatches, +// } + +// /// Compiles and executes a JQ filter on a given JSON input value. +// /// +// /// # Arguments +// /// +// /// * `input` - A `serde_json::Value` representing the JSON input to be processed. +// /// * `filter` - A string slice that holds the JQ filter to be applied. +// /// * `reference` - A string used for logging purposes to identify the rule being processed. +// /// +// /// # Returns +// /// +// /// * `Ok(Value)` - If the filter is successfully compiled and executed, returns the resulting JSON value. +// /// * `Err(RippleError)` - If there is an error during the compilation or execution of the filter, returns a `RippleError`. +// /// +// /// # Errors +// /// +// /// This function will return an error if: +// /// * The JQ filter contains syntax errors. +// /// * There are errors during the compilation of the filter. +// /// * The execution of the filter does not produce a valid output. +// /// +// /// # Example +// /// +// /// ``` +// /// use serde_json::json; +// /// use ripple_sdk::utils::error::RippleError; +// /// use crate::jq_compile; +// /// +// /// let filter = "if .success then .stbVersion else { code: -32100, message: \"couldn't get version\" } end"; +// /// let input = json!({ +// /// "stbVersion": "SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", +// /// "success": true +// /// }); +// /// let result = jq_compile(input, filter, String::new()); +// /// assert_eq!(result.unwrap(), json!("SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT")); +// /// ``` +// pub fn jq_compile(input: Value, filter: &str, reference: String) -> Result { +// info!( +// "Jq rule {} input {:?}, reference {}", +// filter, input, reference +// ); +// let start = Utc::now().timestamp_millis(); +// // start out only from core filters, +// // which do not include filters in the standard library +// // such as `map`, `select` etc. + +// let mut defs = ParseCtx::new(Vec::new()); +// defs.insert_natives(jaq_core::core()); +// defs.insert_defs(jaq_std::std()); +// // parse the filter +// let (f, errs) = jaq_parse::parse(filter, jaq_parse::main()); +// if !errs.is_empty() { +// error!("Error in rule {:?}", errs); +// return Err(RippleError::RuleError); +// } +// // compile the filter in the context of the given definitions +// let f = defs.compile(f.unwrap()); +// if !defs.errs.is_empty() { +// error!("Error in rule {}", reference); +// for (err, _) in defs.errs { +// error!("reference={} {}", reference, err); +// } +// return Err(RippleError::RuleError); +// } + +// let inputs = RcIter::new(core::iter::empty()); +// // iterator over the output values +// let mut out = f.run((Ctx::new([], &inputs), Val::from(input))); +// if let Some(Ok(v)) = out.next() { +// info!( +// "Ripple Gateway Rule Processing Time: {},{}", +// reference, +// Utc::now().timestamp_millis() - start +// ); +// return Ok(Value::from(v)); +// } + +// Err(RippleError::ParseError) +// } +// pub fn compose_json_values(values: Vec) -> Value { +// if values.len() == 1 { +// return values[0].clone(); +// } +// debug!("Composing values {:?}", values); + +// let mut composition_filter = ".[0]".to_string(); +// for v in 1..values.len() { +// composition_filter = format!("{} * .[{}]", composition_filter, v); +// } +// match jq_compile(Value::Array(values), &composition_filter, String::new()) { +// Ok(composed_value) => composed_value, +// Err(err) => { +// error!("Failed to compose JSON values with error: {:?}", err); +// Value::Null // Return a default value on failure +// } +// } +// } +// pub fn make_name_json_safe(name: &str) -> String { +// name.replace([' ', '.', ','], "_") +// } + +// #[cfg(test)] +// mod tests { +// use super::*; +// use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; +// use ripple_sdk::serde_json::json; + +// #[test] +// fn test_jq_compile() { +// let filter = "if .success then ( .stbVersion | split(\"_\")[0] ) else { code: -32100, message: \"couldn't get version\" } end"; +// let input = json!({ +// "stbVersion":"SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", +// "receiverVersion":"7.2.0.0", +// "stbTimestamp":"Thu 20 Jun 2024 14:00:24 UTC", +// "success":true +// }); +// let resp = jq_compile(input, filter, String::new()); +// assert_eq!(resp.unwrap(), "SCXI11BEI".to_string()); + +// let filter = "{ namespace: \"refui\", scope: .scope, key: .key, value: .value }"; +// let input = json!({ +// "key": "key3", +// "scope": "account", +// "value": "value2" +// }); +// let resp = jq_compile(input, filter, String::new()); +// let expected = json!({ +// "namespace": "refui", +// "key": "key3", +// "scope": "account", +// "value": "value2" +// }); +// assert_eq!(resp.unwrap(), expected); + +// let filter = "if .success and ( .supportedHDCPVersion | contains(\"2.2\")) then {\"hdcp2.2\": true} elif .success and ( .supportedHDCPVersion | contains(\"1.4\")) then {\"hdcp1.4\": true} else {\"code\": -32100, \"message\": \"couldn't get version\"} end"; +// let input = json!({ +// "supportedHDCPVersion":"2.2", +// "isHDCPSupported":true, +// "success":true +// }); +// let resp = jq_compile(input, filter, String::new()); +// let expected = json!({ +// "hdcp2.2": true +// }); +// assert_eq!(resp.unwrap(), expected); + +// let filter = "if .success then (.value | fromjson | .value) else { \"code\": -32100, \"message\": \"couldn't get language\" } end"; +// let input = json!({ +// "value": "{\"update_time\":\"2024-07-26T23:39:57.831726080Z\",\"value\":\"EN\"}", +// "success":true +// }); +// let resp = jq_compile(input, filter, String::new()); +// assert_eq!(resp.unwrap(), "EN".to_string()); +// } +// #[test] +// fn test_composed_jq_compile() { +// let a = json!({"asome": "avalue"}); +// let b = json!({"bsome": "bvalue"}); +// let c = json!({"csome": {"cvalue" : "nested"}}); +// let vals = vec![a, b, c]; +// let mut composition_filter = ".[0]".to_string(); +// for v in 1..vals.len() { +// composition_filter = format!("{} * .[{}]", composition_filter, v); +// } + +// assert!(jq_compile( +// jq_compile( +// Value::Array(vals.clone()), +// &composition_filter, +// String::new() +// ) +// .unwrap(), +// ".asome", +// String::new() +// ) +// .unwrap() +// .as_str() +// .unwrap() +// .contains("avalue")); +// assert!(jq_compile( +// jq_compile( +// Value::Array(vals.clone()), +// &composition_filter, +// String::new() +// ) +// .unwrap(), +// ".bsome", +// String::new() +// ) +// .unwrap() +// .as_str() +// .unwrap() +// .contains("bvalue")); +// assert!(jq_compile( +// jq_compile( +// Value::Array(vals.clone()), +// &composition_filter, +// String::new() +// ) +// .unwrap(), +// ".csome.cvalue", +// String::new() +// ) +// .unwrap() +// .as_str() +// .unwrap() +// .contains("nested")); +// } +// use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; + +// #[test] +// fn test_get_rule_exact_match() { +// let mut rule_set = RuleSet::default(); +// let rule = Rule { +// alias: "test_rule".to_string(), +// ..Default::default() +// }; +// rule_set +// .rules +// .insert("test.method".to_string(), rule.clone()); + +// let rule_engine = RuleEngine { rules: rule_set }; + +// let rpc_request = RpcRequest { +// method: "test.method".to_string(), +// ctx: CallContext { +// app_id: "test_app".to_string(), +// method: "test.method".to_string(), +// ..Default::default() +// }, +// ..Default::default() +// }; + +// let result = rule_engine.get_rule(&rpc_request); +// match result { +// Ok(RuleRetrieved::ExactMatch(retrieved_rule)) => { +// assert_eq!(retrieved_rule.alias, rule.alias); +// } +// _ => panic!("Expected exact match, but got {:?}", result), +// } +// } + +// #[test] +// fn test_get_rule_wildcard_match() { +// let mut rule_set = RuleSet::default(); +// let rule = Rule { +// alias: "wildcard_rule".to_string(), +// ..Default::default() +// }; +// rule_set.rules.insert("api.v1.*".to_string(), rule.clone()); + +// let rule_engine = RuleEngine { rules: rule_set }; + +// let rpc_request = RpcRequest { +// method: "api.v1.get".to_string(), +// ctx: CallContext { +// app_id: "test_app".to_string(), +// method: "api.v1.get".to_string(), +// ..Default::default() +// }, +// ..Default::default() +// }; + +// let result = rule_engine.get_rule(&rpc_request); +// match result { +// Ok(RuleRetrieved::WildcardMatch(retrieved_rule)) => { +// assert_eq!(retrieved_rule.alias, rule.alias); +// } +// _ => panic!("Expected wildcard match, but got {:?}", result), +// } +// } + +// #[test] +// fn test_get_rule_no_match() { +// let rule_set = RuleSet::default(); +// let rule_engine = RuleEngine { rules: rule_set }; + +// let rpc_request = RpcRequest { +// method: "nonexistent.method".to_string(), +// ctx: CallContext { +// app_id: "test_app".to_string(), +// method: "nonexistent.method".to_string(), +// ..Default::default() +// }, +// ..Default::default() +// }; + +// let result = rule_engine.get_rule(&rpc_request); +// assert!(matches!( +// result, +// Err(RuleRetrievalError::RuleNotFoundAsWildcard) +// )); +// } + +// #[test] +// fn test_get_rule_multiple_wildcard_matches() { +// let mut rule_set = RuleSet::default(); +// rule_set +// .rules +// .insert("api.v1.*".to_string(), Rule::default()); +// rule_set.rules.insert("api.*".to_string(), Rule::default()); + +// let rule_engine = RuleEngine { rules: rule_set }; + +// let rpc_request = RpcRequest { +// method: "api.v1.get".to_string(), +// ctx: CallContext { +// app_id: "test_app".to_string(), +// method: "api.v1.get".to_string(), +// ..Default::default() +// }, +// ..Default::default() +// }; + +// let result = rule_engine.get_rule(&rpc_request); +// assert!(matches!( +// result, +// Err(RuleRetrievalError::TooManyWildcardMatches) +// )); +// } +// } diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs new file mode 100644 index 000000000..bc541f12b --- /dev/null +++ b/core/main/src/broker/service_broker.rs @@ -0,0 +1,31 @@ +use crate::state::platform_state::{self, PlatformState}; + +use super::endpoint_broker::{EndpointBroker, EndpointBrokerState}; + +pub struct ServiceBroker { + platform_state: Option, +} + +impl ServiceBroker { + pub fn new(platform_state: Option) -> Self { + Self { platform_state } + } +} +impl EndpointBroker for ServiceBroker { + fn get_broker( + ps: Option, + request: super::endpoint_broker::BrokerConnectRequest, + callback: super::endpoint_broker::BrokerCallback, + endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, + ) -> Self { + todo!() + } + + fn get_sender(&self) -> super::endpoint_broker::BrokerSender { + todo!() + } + + fn get_cleaner(&self) -> super::endpoint_broker::BrokerCleaner { + todo!() + } +} diff --git a/core/main/src/broker/thunder/user_data_migrator.rs b/core/main/src/broker/thunder/user_data_migrator.rs index 47e479ea3..adf179c0f 100644 --- a/core/main/src/broker/thunder/user_data_migrator.rs +++ b/core/main/src/broker/thunder/user_data_migrator.rs @@ -24,6 +24,7 @@ use std::{ }; use ripple_sdk::{ + api::rules_engine::{jq_compile, Rule, RuleTransformType}, api::{device::device_peristence::StorageData, gateway::rpc_gateway_api::JsonRpcApiResponse}, log::{debug, error, info}, tokio::{ @@ -40,7 +41,6 @@ use serde_json::{json, Value}; use crate::broker::{ endpoint_broker::{self, BrokerCallback, BrokerOutput, BrokerRequest, EndpointBrokerState}, - rules_engine::{Rule, RuleTransformType}, thunder_broker::ThunderBroker, }; @@ -472,11 +472,7 @@ impl UserDataMigrator { .transform .get_transform_data(RuleTransformType::Request) { - return crate::broker::rules_engine::jq_compile( - data, - &filter, - format!("{}_request", method), - ); + return jq_compile(data, &filter, format!("{}_request", method)); } serde_json::to_value(&data).map_err(|e| { error!( @@ -863,7 +859,7 @@ impl UserDataMigrator { response.data.result = Some(legacy_value.clone()); if let Some(conversion_rule) = &config_entry.legacy_to_plugin_value_conversion { - let data = crate::broker::rules_engine::jq_compile( + let data = jq_compile( json!({ "value": legacy_value }), &conversion_rule.conversion_rule, "legacy_to_plugin_value_conversion".to_string(), diff --git a/core/main/src/broker/workflow_broker.rs b/core/main/src/broker/workflow_broker.rs index 9cd96c01b..9c45723c7 100644 --- a/core/main/src/broker/workflow_broker.rs +++ b/core/main/src/broker/workflow_broker.rs @@ -2,12 +2,12 @@ use super::endpoint_broker::{ BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerRequest, BrokerSender, EndpointBroker, HandleBrokerageError, BROKER_CHANNEL_BUFFER_SIZE, }; -use super::rules_engine::JsonDataSource; + use crate::broker::endpoint_broker::{BrokerOutput, EndpointBrokerState}; -use crate::broker::rules_engine::{compose_json_values, make_name_json_safe}; use crate::state::platform_state::PlatformState; use futures::future::{join_all, BoxFuture}; use futures::FutureExt; +use ripple_sdk::api::rules_engine::{compose_json_values, make_name_json_safe, JsonDataSource}; use serde_json::json; use ripple_sdk::api::gateway::rpc_gateway_api::{JsonRpcApiError, JsonRpcApiResponse, RpcRequest}; @@ -55,16 +55,18 @@ async fn subbroker_call( source: JsonDataSource, ) -> Result { let (brokered_tx, mut brokered_rx) = mpsc::channel::(BROKER_CHANNEL_BUFFER_SIZE); - endpoint_broker.handle_brokerage( - rpc_request, - None, - Some(BrokerCallback { - sender: brokered_tx, - }), - Vec::new(), - None, - vec![], - ); + endpoint_broker + .handle_brokerage( + rpc_request, + None, + Some(BrokerCallback { + sender: brokered_tx, + }), + Vec::new(), + None, + vec![], + ) + .await; match brokered_rx.recv().await { Some(msg) => { @@ -307,13 +309,16 @@ write exhaustive tests for the WorkflowBroker #[cfg(test)] pub mod tests { - use ripple_sdk::{api::gateway::rpc_gateway_api::RpcRequest, tokio, Mockable}; + use ripple_sdk::{ + api::{ + gateway::rpc_gateway_api::RpcRequest, + rules_engine::{JsonDataSource, Rule, RuleEngine}, + }, + tokio, Mockable, + }; use serde_json::json; - use crate::broker::{ - endpoint_broker::{BrokerCallback, BrokerRequest, EndpointBrokerState}, - rules_engine::{JsonDataSource, Rule, RuleEngine}, - }; + use crate::broker::endpoint_broker::{BrokerCallback, BrokerRequest, EndpointBrokerState}; pub fn broker_request(callback: BrokerCallback) -> BrokerRequest { let mut rule = Rule { alias: "module.method".to_string(), diff --git a/core/main/src/firebolt/firebolt_gateway.rs b/core/main/src/firebolt/firebolt_gateway.rs index 1dcacdd59..186ab5a78 100644 --- a/core/main/src/firebolt/firebolt_gateway.rs +++ b/core/main/src/firebolt/firebolt_gateway.rs @@ -366,14 +366,17 @@ impl FireboltGateway { let requestor_callback_tx = Self::handle_broker_callback(platform_state.clone(), request_c.clone()); - let handled = platform_state.endpoint_state.handle_brokerage( - request_c.clone(), - extn_msg.clone(), - None, - p, - session.clone(), - vec![requestor_callback_tx], - ); + let handled = platform_state + .endpoint_state + .handle_brokerage( + request_c.clone(), + extn_msg.clone(), + None, + p, + session.clone(), + vec![requestor_callback_tx], + ) + .await; //.is_ok(); if !handled { diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 0c3f4f585..2550216d2 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -17,7 +17,7 @@ use std::{ net::SocketAddr, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, RwLock}, }; use super::firebolt_gateway::FireboltGatewayCommand; @@ -28,8 +28,12 @@ use crate::{ session_state::Session, }, }; -use futures::SinkExt; use futures::StreamExt; +use futures::{ + stream::{SplitSink, SplitStream}, + SinkExt, +}; +use hyper::client::service; use jsonrpsee::types::{error::INVALID_REQUEST_CODE, ErrorObject, ErrorResponse, Id}; use ripple_sdk::{ api::{ @@ -41,14 +45,14 @@ use ripple_sdk::{ log::{error, info, trace}, tokio::{ net::{TcpListener, TcpStream}, - sync::{mpsc, oneshot}, + sync::{mpsc, oneshot, Mutex}, }, utils::channel_utils::oneshot_send_and_log, uuid::Uuid, }; use ripple_sdk::{log::debug, tokio}; use ssda_service::ApiGateway; -use ssda_types::{APIGatewayServiceConnectionDisposition, ServiceId}; +use ssda_types::{APIGatewayServiceConnectionDisposition, ApiGatewayServer, ServiceId}; use tokio_tungstenite::{ tungstenite::{self, Message}, WebSocketStream, @@ -72,7 +76,7 @@ struct ConnectionCallbackConfig { pub app_state: AppManagerState, pub secure: bool, pub internal_app_id: Option, - pub service_connection: Arc>>, + pub service_connection: Arc>>, } pub struct ConnectionCallback(ConnectionCallbackConfig); @@ -196,6 +200,7 @@ impl FireboltWs { state: PlatformState, secure: bool, internal_app_id: Option, + service_manager: Arc>>, ) { // Create the event loop and TCP listener we'll accept connections on. let try_socket = TcpListener::bind(&server_addr).await; //create the server on the address @@ -204,9 +209,12 @@ impl FireboltWs { let state_for_connection = state.clone(); let app_state = state.app_manager_state.clone(); // Let's spawn the handling of each connection in a separate task. + while let Ok((stream, client_addr)) = listener.accept().await { let (connect_tx, connect_rx) = oneshot::channel::(); - let service_connection_state = Arc::new(Mutex::new(None)); + let service_manager_clone = Arc::clone(&service_manager); + let service_connection_state = Arc::new(std::sync::Mutex::new(None)); + let service_manager_for_connection = service_manager_clone.clone(); let cfg = ConnectionCallbackConfig { next: connect_tx, app_state: app_state.clone(), @@ -219,8 +227,11 @@ impl FireboltWs { error!("websocket connection error {:?}", e); } Ok(ws_stream) => { + // let (mut send , mut recv) = ws_stream.split();; + //let c = send; let connection = service_connection_state.clone(); let service_connection_state = connection.lock().unwrap().clone(); + match service_connection_state { Some(service_connection) => { let service_connection = service_connection.clone(); @@ -230,7 +241,10 @@ impl FireboltWs { let state_for_connection_c = state_for_connection.clone(); tokio::spawn(async move { FireboltWs::handle_service_connection( - client_addr, + service_id, + // send, + // recv, + service_manager_clone, ws_stream, connect_rx, state_for_connection_c.clone(), @@ -258,22 +272,23 @@ impl FireboltWs { } } async fn handle_service_connection( - _client_addr: SocketAddr, + service_id: ServiceId, + //send: SplitSink, Message>, + //recv: SplitStream>, + service_manager: Arc>>, ws_stream: WebSocketStream, connect_rx: oneshot::Receiver, state: PlatformState, gateway_secure: bool, ) { info!("handle_service_connection"); - let (mut send, mut recv) = ws_stream.split(); + //let (mut send, mut recv) = ws_stream.split(); let identity = connect_rx.await.unwrap(); - tokio::spawn(async move { - while let Some(api_message) = recv.next().await { - //nfo!("Received server request {}", api_message.jsonrpc_msg); - info!("Received server request {:?}", api_message); - send.send("item".into()).await; - } - }); + { + let mut guard = service_manager.lock().await; + let mut instance = guard.as_mut(); + guard.service_connect(service_id, ws_stream).await.unwrap(); + } } async fn handle_connection( _client_addr: SocketAddr, diff --git a/core/main/src/service/apps/delegated_launcher_handler.rs b/core/main/src/service/apps/delegated_launcher_handler.rs index 27daf0018..2c49dd6b8 100644 --- a/core/main/src/service/apps/delegated_launcher_handler.rs +++ b/core/main/src/service/apps/delegated_launcher_handler.rs @@ -543,6 +543,7 @@ impl DelegatedLauncherHandler { if platform_state .endpoint_state .has_rule("ripple.reportSessionUpdate") + .await { if let Ok(AppManagerResponse::Session(a)) = app_manager_response { let params = serde_json::to_value(a).unwrap(); @@ -563,6 +564,7 @@ impl DelegatedLauncherHandler { if platform_state .endpoint_state .has_rule("ripple.reportLifecycleStateChange") + .await { let previous_state = platform_state.app_manager_state.get_internal_state(app_id); diff --git a/core/main/src/state/bootstrap_state.rs b/core/main/src/state/bootstrap_state.rs index 89422c089..4a3f7e202 100644 --- a/core/main/src/state/bootstrap_state.rs +++ b/core/main/src/state/bootstrap_state.rs @@ -15,17 +15,25 @@ // SPDX-License-Identifier: Apache-2.0 // -use std::time::Instant; +use std::{sync::Arc, time::Instant}; use ripple_sdk::{ - api::{apps::AppRequest, manifest::ripple_manifest_loader::RippleManifestLoader}, + api::{ + apps::AppRequest, + manifest::ripple_manifest_loader::RippleManifestLoader, + rules_engine::{RuleEngine, RuleEngineProvider}, + }, async_channel::{unbounded, Receiver as CReceiver, Sender as CSender}, extn::ffi::ffi_message::CExtnMessage, framework::bootstrap::TransientChannel, log::{error, info, warn}, - tokio::sync::mpsc::{self, Receiver, Sender}, + tokio::{ + self, + sync::mpsc::{self, Receiver, Sender}, + }, utils::error::RippleError, }; +use ssda_types::ApiGatewayServer; use crate::{ bootstrap::manifest::apps::LoadAppLibraryStep, @@ -105,7 +113,7 @@ impl Default for ChannelsState { } } -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] pub struct BootstrapState { pub start_time: Instant, pub platform_state: PlatformState, @@ -123,12 +131,23 @@ impl BootstrapState { }; let app_manifest_result = LoadAppLibraryStep::load_app_library(); let extn_state = ExtnState::new(channels_state.clone(), extn_manifest.clone()); + let rules_engine: Arc>> = + Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( + &extn_manifest, + )))); + let api_gateway_state: Arc>> = + Arc::new(tokio::sync::Mutex::new(Box::new( + ssda_service::ApiGateway::new(rules_engine.clone()), + ))); + let platform_state = PlatformState::new( extn_manifest, device_manifest, client, app_manifest_result, ripple_version_from_etc(), + api_gateway_state.clone(), + rules_engine.clone(), ); fn ripple_version_from_etc() -> Option { @@ -159,6 +178,7 @@ impl BootstrapState { warn!("error reading versions from {}", version_file_name,); None } + Ok(BootstrapState { start_time: Instant::now(), platform_state, diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index 5954ce514..cbae6995d 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -25,6 +25,7 @@ use ripple_sdk::{ exclusory::ExclusoryImpl, extn_manifest::ExtnManifest, }, + rules_engine::RuleEngineProvider, session::SessionAdjective, }, extn::{ @@ -32,13 +33,15 @@ use ripple_sdk::{ extn_id::ExtnId, }, framework::ripple_contract::RippleContract, + tokio, utils::error::RippleError, uuid::Uuid, }; -use std::collections::HashMap; +use ssda_types::ApiGatewayServer; +use std::{collections::HashMap, fmt, sync::Arc}; use crate::{ - broker::{endpoint_broker::EndpointBrokerState, rules_engine::RuleEngine}, + broker::endpoint_broker::EndpointBrokerState, firebolt::rpc_router::RouterState, service::{ apps::{ @@ -70,6 +73,19 @@ pub struct DeviceSessionIdentifier { pub device_session_id: Uuid, } +/// A wrapper for `Arc>>` +/// that implements the `Debug` trait. +#[derive(Clone)] +pub struct DebuggableApiGatewayServer( + pub Arc>>, +); + +impl fmt::Debug for DebuggableApiGatewayServer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "DebuggableApiGatewayServer") + } +} + impl Default for DeviceSessionIdentifier { fn default() -> Self { Self { @@ -90,7 +106,7 @@ impl From for DeviceSessionIdentifier { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct PlatformState { extn_manifest: ExtnManifest, device_manifest: DeviceManifest, @@ -108,8 +124,27 @@ pub struct PlatformState { pub ripple_cache: RippleCache, pub version: Option, pub endpoint_state: EndpointBrokerState, + pub services_gateway_api: Arc>>, +} +impl std::fmt::Debug for PlatformState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PlatformState") + .field("extn_manifest", &self.extn_manifest) + .field("device_manifest", &self.device_manifest) + .field("ripple_client", &self.ripple_client) + .field("app_library_state", &self.app_library_state) + .field("session_state", &self.session_state) + .field("cap_state", &self.cap_state) + .field("app_events_state", &self.app_events_state) + .field("provider_broker_state", &self.provider_broker_state) + .field("app_manager_state", &self.app_manager_state) + .field("open_rpc_state", &self.open_rpc_state) + .field("router_state", &self.router_state) + .field("metrics", &self.metrics) + .field("device_session_id", &self.device_session_id) + .finish() + } } - impl PlatformState { pub fn new( extn_manifest: ExtnManifest, @@ -117,10 +152,12 @@ impl PlatformState { client: RippleClient, app_library: Vec, version: Option, + services_gateway_api: Arc>>, + rule_engine: Arc>>, ) -> PlatformState { let exclusory = ExclusoryImpl::get(&manifest); let broker_sender = client.get_broker_sender(); - let rule_engine = RuleEngine::build(&extn_manifest); + //let rule_engine = RuleEngine::build(&extn_manifest); let extn_sdks = extn_manifest.extn_sdks.clone(); let provider_registations = extn_manifest.provider_registrations.clone(); let metrics_state = OpMetricState::default(); @@ -146,6 +183,7 @@ impl PlatformState { rule_engine, client, ), + services_gateway_api: services_gateway_api.clone(), } } diff --git a/core/sdk/Cargo.toml b/core/sdk/Cargo.toml index 786a1db71..e22be6598 100644 --- a/core/sdk/Cargo.toml +++ b/core/sdk/Cargo.toml @@ -69,6 +69,10 @@ libloading = "0.7.4" async-channel = { version = "2.1.0", default-features = false } tree_magic_mini = { version = "3.0.3", optional = true} lazy_static = "1.5.0" +jaq-interpret = { version = "1.5.0", default-features = false } +jaq-parse = { version = "1.0.2", default-features = false } +jaq-core = "1.5.0" +jaq-std = { version = "1.5.1", default-features = false } [dev-dependencies] ripple_sdk = { path = ".", features=["tdk"]} diff --git a/core/sdk/src/api/mod.rs b/core/sdk/src/api/mod.rs index d0a8511c5..1482ae782 100644 --- a/core/sdk/src/api/mod.rs +++ b/core/sdk/src/api/mod.rs @@ -25,6 +25,7 @@ pub mod default_storage_properties; pub mod device; pub mod manifest; pub mod ripple_cache; +pub mod rules_engine; pub mod session; pub mod settings; pub mod status_update; diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs new file mode 100644 index 000000000..c4d415df6 --- /dev/null +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -0,0 +1,785 @@ +use std::collections::HashMap; + +use chrono::Utc; +use log::{debug, error, info, trace, warn}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::utils::error::RippleError; + +use super::{gateway::rpc_gateway_api::RpcRequest, manifest::extn_manifest::ExtnManifest}; + +// Copyright 2023 Comcast Cable Communications Management, LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val}; +// use ripple_sdk::api::{ +// gateway::rpc_gateway_api::RpcRequest, manifest::extn_manifest::ExtnManifest, +// }; + +// use ripple_sdk::{ +// chrono::Utc, +// log::{debug, error, info, trace, warn}, +// serde_json::Value, +// utils::error::RippleError, +// }; +// use serde::{Deserialize, Serialize}; +// use std::collections::HashMap; + +use std::{fs, path::Path}; + +#[derive(Debug, Deserialize, Default, Clone)] +pub struct RuleSet { + pub endpoints: HashMap, + pub rules: HashMap, +} + +impl RuleSet { + pub fn append(&mut self, rule_set: RuleSet) { + self.endpoints.extend(rule_set.endpoints); + let rules: HashMap = rule_set + .rules + .into_iter() + .map(|(k, v)| { + trace!("Loading JQ Rule for {}", k.to_lowercase()); + (k.to_lowercase(), v) + }) + .collect(); + self.rules.extend(rules); + } + pub fn get(&self, key: &str) -> Option<&Rule> { + self.rules.get(key) + } +} +#[derive(Debug, Deserialize, Clone, Default)] +pub struct RuleEndpoint { + pub protocol: RuleEndpointProtocol, + pub url: String, + #[serde(default = "default_autostart")] + pub jsonrpc: bool, +} + +impl RuleEndpoint { + pub fn get_url(&self) -> String { + if cfg!(feature = "local_dev") { + if let Ok(host_override) = std::env::var("DEVICE_HOST") { + if !host_override.is_empty() { + return self.url.replace("127.0.0.1", &host_override); + } + } + } + self.url.clone() + } +} + +fn default_autostart() -> bool { + true +} + +#[derive(Deserialize, Debug, Clone, Default)] +#[serde(rename_all = "lowercase")] +#[cfg_attr(test, derive(PartialEq))] +pub enum RuleEndpointProtocol { + #[default] + Websocket, + Http, + Thunder, + Workflow, + Extn, + Service, +} +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct JsonDataSource { + // configurable namespace to "stuff" an in individual result payload into + pub namespace: Option, + pub method: String, + pub params: Option, +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct Rule { + pub alias: String, + // Not every rule needs transform + #[serde(default)] + pub transform: RuleTransform, + #[serde(skip_serializing_if = "Option::is_none")] + pub filter: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub event_handler: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub endpoint: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub sources: Option>, +} +impl std::fmt::Display for Rule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Rule {{ alias: {} }}", self.alias) + } +} +/* +war on dots +*/ +#[derive(PartialEq)] +pub enum RuleType { + Static, + Provider, + Endpoint, +} +impl Rule { + fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { + self.transform.apply_context(rpc_request); + self + } + pub fn rule_type(&self) -> RuleType { + match self.alias.trim().to_ascii_lowercase().as_str() { + "static" => RuleType::Static, + "provided" => RuleType::Provider, + /* + maps to a sender that can be used to send a message to the endpoint, for instance: Thunder + */ + _ => RuleType::Endpoint, + } + } + pub fn with_alias(&mut self, alias: String) -> &mut Self { + self.alias = alias; + self + } + pub fn with_rule_tranformt(&mut self, transform: RuleTransform) -> &mut Self { + self.transform = transform; + self + } + pub fn with_filter(&mut self, filter: String) -> &mut Self { + self.filter = Some(filter); + self + } + pub fn with_event_handler(&mut self, event_handler: String) -> &mut Self { + self.event_handler = Some(event_handler); + self + } + pub fn with_endpoint(&mut self, endpoint: String) -> &mut Self { + self.endpoint = Some(endpoint); + self + } + pub fn with_sources(&mut self, sources: Vec) -> &mut Self { + self.sources = Some(sources); + self + } + pub fn with_source(&mut self, source: JsonDataSource) -> &mut Self { + if let Some(sources) = &mut self.sources { + sources.push(source); + } else { + self.sources = Some(vec![source]); + } + self + } +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct RuleTransform { + #[serde(skip_serializing_if = "Option::is_none")] + pub request: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub response: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub event: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub rpcv2_event: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub event_decorator_method: Option, +} + +impl RuleTransform { + fn check_and_replace(&self, input: &str, rpc_request: &RpcRequest) -> String { + trace!( + "check_and_replace: input: {}, rpc_request: {:?}", + input, + rpc_request + ); + + let mut output = input.replace("$context.appId", &rpc_request.ctx.app_id); + + if let Some(event) = &self.event { + output = output.replace("$event", event); + } + + output + } + + pub fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { + if let Some(value) = self.request.take() { + let _ = self + .request + .insert(self.check_and_replace(&value, rpc_request)); + } + + if let Some(value) = self.event.take() { + let _ = self + .event + .insert(self.check_and_replace(&value, rpc_request)); + } + + if let Some(value) = self.rpcv2_event.take() { + let _ = self + .rpcv2_event + .insert(self.check_and_replace(&value, rpc_request)); + } + self + } + + pub fn get_transform_data(&self, typ: RuleTransformType) -> Option { + match typ { + RuleTransformType::Request => self.request.clone(), + RuleTransformType::Event(rpc_v2) => { + if rpc_v2 { + self.rpcv2_event.clone() + } else { + self.event.clone() + } + } + RuleTransformType::Response => self.response.clone(), + } + } +} + +pub enum RuleTransformType { + Request, + Response, + Event(bool), +} + +#[derive(Debug, Clone, Default)] +pub struct RuleEngine { + pub rules: RuleSet, +} + +impl RuleEngine { + fn build_path(path: &str, default_path: &str) -> String { + if path.starts_with('/') { + path.to_owned() + } else { + format!("{}{}", default_path, path) + } + } + + pub fn load(path: &str) -> Result { + let path = Path::new(path); + if path.exists() { + let contents = fs::read_to_string(path).unwrap(); + Self::load_from_string_literal(contents) + } else { + warn!("path for the rule is invalid {}", path.display()); + Err(RippleError::InvalidInput) + } + } + pub fn load_from_string_literal(contents: String) -> Result { + let (_content, rule_set) = Self::load_from_content(contents)?; + let mut rules_engine = RuleEngine::default(); + rules_engine.rules.append(rule_set); + Ok(rules_engine.clone()) + } + + pub fn build(extn_manifest: &ExtnManifest) -> Self { + trace!("building rules engine {:?}", extn_manifest.rules_path); + let mut engine = RuleEngine::default(); + for path in extn_manifest.rules_path.iter() { + let path_for_rule = Self::build_path(path, &extn_manifest.default_path); + debug!("loading rules file {}", path_for_rule); + if let Some(p) = Path::new(&path_for_rule).to_str() { + if let Ok(contents) = fs::read_to_string(p) { + info!("Rules content {}", contents); + info!("loading rules from path {}", path); + info!("loading rule {}", path_for_rule); + if let Ok((_, rule_set)) = Self::load_from_content(contents) { + engine.rules.append(rule_set) + } else { + warn!("invalid rule found in path {}", path) + } + } else { + warn!("path for the rule is invalid {}", path) + } + } else { + warn!("invalid rule path {}", path) + } + } + engine + } + + pub fn load_from_content(contents: String) -> Result<(String, RuleSet), RippleError> { + match serde_json::from_str::(&contents) { + Ok(manifest) => Ok((contents, manifest)), + Err(err) => { + error!("{:?} could not load rule", err); + Err(RippleError::InvalidInput) + } + } + } + pub fn add_rules(&mut self, rules: RuleSet) { + self.rules.append(rules); + } + pub fn add_rule(&mut self, rule: Rule) { + self.rules.rules.insert(rule.alias.clone(), rule); + } + + pub fn has_rule(&self, request: &str) -> bool { + self.rules.rules.contains_key(&request.to_lowercase()) + } + fn wildcard_match(rule_name: &str, method: &str) -> bool { + rule_name.ends_with(".*") && method.starts_with(&rule_name[..rule_name.len() - 2]) + } + fn find_wildcard_rule( + rules: &HashMap, + method: &str, + ) -> Result { + let filtered_rules: Vec<&Rule> = rules + .iter() + .filter(|(rule_name, _)| Self::wildcard_match(rule_name, method)) + .map(|(_, rule)| rule) + .collect(); + + match filtered_rules.len() { + 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), + 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), + _ => Err(RuleRetrievalError::TooManyWildcardMatches), + } + } + + pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { + let method = rpc_request.method.to_lowercase(); + /* + match directly from method name + */ + + if let Some(mut rule) = self.rules.get(&method).cloned() { + return Ok(RuleRetrieved::ExactMatch( + rule.apply_context(rpc_request).to_owned(), + )); + } else { + /* + * match, for example api.v1.* as rule name and api.v1.get as method name + */ + Self::find_wildcard_rule(&self.rules.rules, &method) + } + } + + pub fn get_rule_by_method(&self, method: &str) -> Option { + self.rules.rules.get(&method.to_lowercase()).cloned() + } +} +#[derive(Debug)] +pub enum RuleRetrieved { + ExactMatch(Rule), + WildcardMatch(Rule), +} +impl From for Rule { + fn from(rule_retrieved: RuleRetrieved) -> Self { + match rule_retrieved { + RuleRetrieved::ExactMatch(rule) => rule, + RuleRetrieved::WildcardMatch(rule) => rule, + } + } +} + +#[derive(Debug)] +pub enum RuleRetrievalError { + RuleNotFound(String), + RuleNotFoundAsWildcard, + TooManyWildcardMatches, +} + +/// Compiles and executes a JQ filter on a given JSON input value. +/// +/// # Arguments +/// +/// * `input` - A `serde_json::Value` representing the JSON input to be processed. +/// * `filter` - A string slice that holds the JQ filter to be applied. +/// * `reference` - A string used for logging purposes to identify the rule being processed. +/// +/// # Returns +/// +/// * `Ok(Value)` - If the filter is successfully compiled and executed, returns the resulting JSON value. +/// * `Err(RippleError)` - If there is an error during the compilation or execution of the filter, returns a `RippleError`. +/// +/// # Errors +/// +/// This function will return an error if: +/// * The JQ filter contains syntax errors. +/// * There are errors during the compilation of the filter. +/// * The execution of the filter does not produce a valid output. +/// +/// # Example +/// +/// ``` +/// use serde_json::json; +/// use ripple_sdk::utils::error::RippleError; +/// use crate::jq_compile; +/// +/// let filter = "if .success then .stbVersion else { code: -32100, message: \"couldn't get version\" } end"; +/// let input = json!({ +/// "stbVersion": "SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", +/// "success": true +/// }); +/// let result = jq_compile(input, filter, String::new()); +/// assert_eq!(result.unwrap(), json!("SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT")); +/// ``` +pub fn jq_compile(input: Value, filter: &str, reference: String) -> Result { + info!( + "Jq rule {} input {:?}, reference {}", + filter, input, reference + ); + let start = Utc::now().timestamp_millis(); + // start out only from core filters, + // which do not include filters in the standard library + // such as `map`, `select` etc. + + let mut defs = ParseCtx::new(Vec::new()); + defs.insert_natives(jaq_core::core()); + defs.insert_defs(jaq_std::std()); + // parse the filter + let (f, errs) = jaq_parse::parse(filter, jaq_parse::main()); + if !errs.is_empty() { + error!("Error in rule {:?}", errs); + return Err(RippleError::RuleError); + } + // compile the filter in the context of the given definitions + let f = defs.compile(f.unwrap()); + if !defs.errs.is_empty() { + error!("Error in rule {}", reference); + for (err, _) in defs.errs { + error!("reference={} {}", reference, err); + } + return Err(RippleError::RuleError); + } + + let inputs = RcIter::new(core::iter::empty()); + // iterator over the output values + let mut out = f.run((Ctx::new([], &inputs), Val::from(input))); + if let Some(Ok(v)) = out.next() { + info!( + "Ripple Gateway Rule Processing Time: {},{}", + reference, + Utc::now().timestamp_millis() - start + ); + return Ok(Value::from(v)); + } + + Err(RippleError::ParseError) +} +pub fn compose_json_values(values: Vec) -> Value { + if values.len() == 1 { + return values[0].clone(); + } + debug!("Composing values {:?}", values); + + let mut composition_filter = ".[0]".to_string(); + for v in 1..values.len() { + composition_filter = format!("{} * .[{}]", composition_filter, v); + } + match jq_compile(Value::Array(values), &composition_filter, String::new()) { + Ok(composed_value) => composed_value, + Err(err) => { + error!("Failed to compose JSON values with error: {:?}", err); + Value::Null // Return a default value on failure + } + } +} +pub fn make_name_json_safe(name: &str) -> String { + name.replace([' ', '.', ','], "_") +} + +#[async_trait::async_trait] +pub trait RuleEngineProvider: Send + Sync { + fn add_rules(&mut self, rules: RuleSet); + fn add_rule(&mut self, rule: Rule); + fn remove_rule(&mut self, alias: &str); + fn has_rule(&self, request: &str) -> bool; + fn wildcard_match(&self, rule_name: &str, method: &str) -> bool; + fn find_wildcard_rule( + &self, + rules: &HashMap, + method: &str, + ) -> Result; + fn get_rule(&self, rpc_request: &RpcRequest) -> Result; + fn get_rule_by_method(&self, method: &str) -> Option; + fn get_rules(&self) -> RuleSet; +} + +#[async_trait::async_trait] +impl RuleEngineProvider for RuleEngine { + fn add_rules(&mut self, rules: RuleSet) { + self.rules.append(rules); + } + fn add_rule(&mut self, rule: Rule) { + debug!("Adding rule: {:?}", rule); + self.rules.rules.insert(rule.alias.clone(), rule); + } + fn remove_rule(&mut self, alias: &str) { + debug!("Removing rule: {}", alias); + self.rules.rules.remove(alias); + } + fn has_rule(&self, request: &str) -> bool { + self.rules.rules.contains_key(&request.to_lowercase()) + } + fn wildcard_match(&self, rule_name: &str, method: &str) -> bool { + rule_name.ends_with(".*") && method.starts_with(&rule_name[..rule_name.len() - 2]) + } + fn find_wildcard_rule( + &self, + rules: &HashMap, + method: &str, + ) -> Result { + let filtered_rules: Vec<&Rule> = rules + .iter() + .filter(|(rule_name, _)| Self::wildcard_match(rule_name, method)) + .map(|(_, rule)| rule) + .collect(); + + match filtered_rules.len() { + 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), + 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), + _ => Err(RuleRetrievalError::TooManyWildcardMatches), + } + } + fn get_rule(&self, rpc_request: &RpcRequest) -> Result { + self.get_rule(rpc_request) + } + fn get_rule_by_method(&self, method: &str) -> Option { + self.get_rule_by_method(method) + } + fn get_rules(&self) -> RuleSet { + self.rules.clone() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; + use ripple_sdk::serde_json::json; + + #[test] + fn test_jq_compile() { + let filter = "if .success then ( .stbVersion | split(\"_\")[0] ) else { code: -32100, message: \"couldn't get version\" } end"; + let input = json!({ + "stbVersion":"SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", + "receiverVersion":"7.2.0.0", + "stbTimestamp":"Thu 20 Jun 2024 14:00:24 UTC", + "success":true + }); + let resp = jq_compile(input, filter, String::new()); + assert_eq!(resp.unwrap(), "SCXI11BEI".to_string()); + + let filter = "{ namespace: \"refui\", scope: .scope, key: .key, value: .value }"; + let input = json!({ + "key": "key3", + "scope": "account", + "value": "value2" + }); + let resp = jq_compile(input, filter, String::new()); + let expected = json!({ + "namespace": "refui", + "key": "key3", + "scope": "account", + "value": "value2" + }); + assert_eq!(resp.unwrap(), expected); + + let filter = "if .success and ( .supportedHDCPVersion | contains(\"2.2\")) then {\"hdcp2.2\": true} elif .success and ( .supportedHDCPVersion | contains(\"1.4\")) then {\"hdcp1.4\": true} else {\"code\": -32100, \"message\": \"couldn't get version\"} end"; + let input = json!({ + "supportedHDCPVersion":"2.2", + "isHDCPSupported":true, + "success":true + }); + let resp = jq_compile(input, filter, String::new()); + let expected = json!({ + "hdcp2.2": true + }); + assert_eq!(resp.unwrap(), expected); + + let filter = "if .success then (.value | fromjson | .value) else { \"code\": -32100, \"message\": \"couldn't get language\" } end"; + let input = json!({ + "value": "{\"update_time\":\"2024-07-26T23:39:57.831726080Z\",\"value\":\"EN\"}", + "success":true + }); + let resp = jq_compile(input, filter, String::new()); + assert_eq!(resp.unwrap(), "EN".to_string()); + } + #[test] + fn test_composed_jq_compile() { + let a = json!({"asome": "avalue"}); + let b = json!({"bsome": "bvalue"}); + let c = json!({"csome": {"cvalue" : "nested"}}); + let vals = vec![a, b, c]; + let mut composition_filter = ".[0]".to_string(); + for v in 1..vals.len() { + composition_filter = format!("{} * .[{}]", composition_filter, v); + } + + assert!(jq_compile( + jq_compile( + Value::Array(vals.clone()), + &composition_filter, + String::new() + ) + .unwrap(), + ".asome", + String::new() + ) + .unwrap() + .as_str() + .unwrap() + .contains("avalue")); + assert!(jq_compile( + jq_compile( + Value::Array(vals.clone()), + &composition_filter, + String::new() + ) + .unwrap(), + ".bsome", + String::new() + ) + .unwrap() + .as_str() + .unwrap() + .contains("bvalue")); + assert!(jq_compile( + jq_compile( + Value::Array(vals.clone()), + &composition_filter, + String::new() + ) + .unwrap(), + ".csome.cvalue", + String::new() + ) + .unwrap() + .as_str() + .unwrap() + .contains("nested")); + } + use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; + + #[test] + fn test_get_rule_exact_match() { + let mut rule_set = RuleSet::default(); + let rule = Rule { + alias: "test_rule".to_string(), + ..Default::default() + }; + rule_set + .rules + .insert("test.method".to_string(), rule.clone()); + + let rule_engine = RuleEngine { rules: rule_set }; + + let rpc_request = RpcRequest { + method: "test.method".to_string(), + ctx: CallContext { + app_id: "test_app".to_string(), + method: "test.method".to_string(), + ..Default::default() + }, + ..Default::default() + }; + + let result = rule_engine.get_rule(&rpc_request); + match result { + Ok(RuleRetrieved::ExactMatch(retrieved_rule)) => { + assert_eq!(retrieved_rule.alias, rule.alias); + } + _ => panic!("Expected exact match, but got {:?}", result), + } + } + + #[test] + fn test_get_rule_wildcard_match() { + let mut rule_set = RuleSet::default(); + let rule = Rule { + alias: "wildcard_rule".to_string(), + ..Default::default() + }; + rule_set.rules.insert("api.v1.*".to_string(), rule.clone()); + + let rule_engine = RuleEngine { rules: rule_set }; + + let rpc_request = RpcRequest { + method: "api.v1.get".to_string(), + ctx: CallContext { + app_id: "test_app".to_string(), + method: "api.v1.get".to_string(), + ..Default::default() + }, + ..Default::default() + }; + + let result = rule_engine.get_rule(&rpc_request); + match result { + Ok(RuleRetrieved::WildcardMatch(retrieved_rule)) => { + assert_eq!(retrieved_rule.alias, rule.alias); + } + _ => panic!("Expected wildcard match, but got {:?}", result), + } + } + + #[test] + fn test_get_rule_no_match() { + let rule_set = RuleSet::default(); + let rule_engine = RuleEngine { rules: rule_set }; + + let rpc_request = RpcRequest { + method: "nonexistent.method".to_string(), + ctx: CallContext { + app_id: "test_app".to_string(), + method: "nonexistent.method".to_string(), + ..Default::default() + }, + ..Default::default() + }; + + let result = rule_engine.get_rule(&rpc_request); + assert!(matches!( + result, + Err(RuleRetrievalError::RuleNotFoundAsWildcard) + )); + } + + #[test] + fn test_get_rule_multiple_wildcard_matches() { + let mut rule_set = RuleSet::default(); + rule_set + .rules + .insert("api.v1.*".to_string(), Rule::default()); + rule_set.rules.insert("api.*".to_string(), Rule::default()); + + let rule_engine = RuleEngine { rules: rule_set }; + + let rpc_request = RpcRequest { + method: "api.v1.get".to_string(), + ctx: CallContext { + app_id: "test_app".to_string(), + method: "api.v1.get".to_string(), + ..Default::default() + }, + ..Default::default() + }; + + let result = rule_engine.get_rule(&rpc_request); + assert!(matches!( + result, + Err(RuleRetrievalError::TooManyWildcardMatches) + )); + } +} From 2054c353106acfb122b01eef792744a92f12a79f Mon Sep 17 00:00:00 2001 From: brendanobra Date: Fri, 9 May 2025 13:34:02 -0700 Subject: [PATCH 03/46] chore: refactor modules --- core/main/src/broker/endpoint_broker.rs | 36 +++++++---- core/main/src/broker/service_broker.rs | 80 +++++++++++++++++++++---- core/main/src/firebolt/firebolt_ws.rs | 4 +- core/main/src/state/bootstrap_state.rs | 3 +- core/main/src/state/platform_state.rs | 2 +- 5 files changed, 99 insertions(+), 26 deletions(-) diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 92694bccd..31e475013 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -766,6 +766,7 @@ impl EndpointBrokerState { fn build_endpoint(&mut self, ps: Option, request: BrokerConnectRequest) { let endpoint = request.endpoint.clone(); let key = request.key.clone(); + info!("Building endpoint {:?} using key {}", endpoint, key); let (broker, cleaner) = match endpoint.protocol { RuleEndpointProtocol::Http => ( HttpBroker::get_broker(None, request, self.callback.clone(), self).get_sender(), @@ -793,8 +794,12 @@ impl EndpointBrokerState { None, ), RuleEndpointProtocol::Service => { - let service_broker = ServiceBroker::new(ps.clone()); - (service_broker.get_sender(), None) + let service_broker = + ServiceBroker::get_broker(ps, request, self.callback.clone(), self); + ( + service_broker.get_sender(), + Some(service_broker.get_cleaner()), + ) } }; self.add_endpoint(key, broker); @@ -899,16 +904,23 @@ impl EndpointBrokerState { .with_diagnostic_context_item("workflow", &workflow_callback.is_some().to_string()) .emit_debug(); - self.handle_brokerage_workflow( - rpc_request, - extn_message, - workflow_callback, - permissions, - session, - telemetry_response_listeners, - ) - .await - .is_ok() + match self + .handle_brokerage_workflow( + rpc_request, + extn_message, + workflow_callback, + permissions, + session, + telemetry_response_listeners, + ) + .await + { + Ok(yay) => true, + Err(e) => { + error!("Error in brokerage {:?}", e); + return false; + } + } } fn get_endpoint( diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index bc541f12b..4a1a0c225 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -1,31 +1,89 @@ +use std::sync::Arc; + +use futures_channel::oneshot; +use ripple_sdk::{ + api::rules_engine::RuleEngineProvider, + log::info, + tokio::{ + self, + sync::mpsc::{self, Sender}, + }, + utils::rpc_utils, +}; +use ssda_types::gateway::ServiceRequest; +use ssda_types::ServiceRequestId; +use tokio_tungstenite::tungstenite::http::request; + use crate::state::platform_state::{self, PlatformState}; -use super::endpoint_broker::{EndpointBroker, EndpointBrokerState}; +use super::endpoint_broker::{ + BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerRequest, BrokerSender, + EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, +}; pub struct ServiceBroker { platform_state: Option, + connect_request: BrokerConnectRequest, + broker_callback: BrokerCallback, + endpoint_broker_state: EndpointBrokerState, + broker_sender: BrokerSender, + cleaner: BrokerCleaner, } -impl ServiceBroker { - pub fn new(platform_state: Option) -> Self { - Self { platform_state } - } -} +impl ServiceBroker {} impl EndpointBroker for ServiceBroker { fn get_broker( ps: Option, - request: super::endpoint_broker::BrokerConnectRequest, - callback: super::endpoint_broker::BrokerCallback, + connect_request: super::endpoint_broker::BrokerConnectRequest, + broker_callback: super::endpoint_broker::BrokerCallback, endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, ) -> Self { - todo!() + //todo!(); + // let endpoint = request.endpoint.clone(); + let (tx, mut tr) = mpsc::channel(BROKER_CHANNEL_BUFFER_SIZE); + let broker_sender = BrokerSender { sender: tx }; + + if let Some(platform_state) = ps.clone() { + tokio::spawn(async move { + while let Some(request) = tr.recv().await { + let services_tx = platform_state + .services_gateway_api + .lock() + .await + .get_sender(); + use tokio::sync::oneshot; + let (tx, rx) = oneshot::channel(); + let service_request = ServiceRequest { + request_id: ServiceRequestId { + request_id: request.get_id(), + }, + payload: request.rpc.clone(), + respond_to: tx, + }; + + services_tx.send(service_request).await.unwrap(); + info!("ServiceBroker received request: {:?}", request); + } + }); + } else { + panic!("Platform state is required"); + }; + + Self { + platform_state: ps.clone(), + connect_request: connect_request, + broker_callback: broker_callback, + endpoint_broker_state: endpoint_broker.clone(), + broker_sender: broker_sender, + cleaner: BrokerCleaner { cleaner: None }, + } } fn get_sender(&self) -> super::endpoint_broker::BrokerSender { - todo!() + self.broker_sender.clone() } fn get_cleaner(&self) -> super::endpoint_broker::BrokerCleaner { - todo!() + BrokerCleaner::default() } } diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 2550216d2..294250982 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -52,7 +52,8 @@ use ripple_sdk::{ }; use ripple_sdk::{log::debug, tokio}; use ssda_service::ApiGateway; -use ssda_types::{APIGatewayServiceConnectionDisposition, ApiGatewayServer, ServiceId}; +use ssda_types::gateway::{APIGatewayServiceConnectionDisposition, ApiGatewayServer}; +use ssda_types::ServiceId; use tokio_tungstenite::{ tungstenite::{self, Message}, WebSocketStream, @@ -231,6 +232,7 @@ impl FireboltWs { //let c = send; let connection = service_connection_state.clone(); let service_connection_state = connection.lock().unwrap().clone(); + //let service_connections = service_connection_state.clone(); match service_connection_state { Some(service_connection) => { diff --git a/core/main/src/state/bootstrap_state.rs b/core/main/src/state/bootstrap_state.rs index 4a3f7e202..0814b39c3 100644 --- a/core/main/src/state/bootstrap_state.rs +++ b/core/main/src/state/bootstrap_state.rs @@ -33,7 +33,7 @@ use ripple_sdk::{ }, utils::error::RippleError, }; -use ssda_types::ApiGatewayServer; +use ssda_types::gateway::ApiGatewayServer; use crate::{ bootstrap::manifest::apps::LoadAppLibraryStep, @@ -135,6 +135,7 @@ impl BootstrapState { Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( &extn_manifest, )))); + tokio::spawn(async move {}); let api_gateway_state: Arc>> = Arc::new(tokio::sync::Mutex::new(Box::new( ssda_service::ApiGateway::new(rules_engine.clone()), diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index cbae6995d..a06553335 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -37,7 +37,7 @@ use ripple_sdk::{ utils::error::RippleError, uuid::Uuid, }; -use ssda_types::ApiGatewayServer; +use ssda_types::gateway::ApiGatewayServer; use std::{collections::HashMap, fmt, sync::Arc}; use crate::{ From 2371146d75087fe4c5e4ac46a667ebf304a02ac7 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Fri, 9 May 2025 14:27:21 -0700 Subject: [PATCH 04/46] feat: callback to broker --- core/main/src/broker/service_broker.rs | 27 +++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 4a1a0c225..ca676af04 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -3,14 +3,14 @@ use std::sync::Arc; use futures_channel::oneshot; use ripple_sdk::{ api::rules_engine::RuleEngineProvider, - log::info, + log::{error, info}, tokio::{ self, sync::mpsc::{self, Sender}, }, utils::rpc_utils, }; -use ssda_types::gateway::ServiceRequest; +use ssda_types::gateway::{ServiceRequest, ServiceResponse}; use ssda_types::ServiceRequestId; use tokio_tungstenite::tungstenite::http::request; @@ -52,16 +52,33 @@ impl EndpointBroker for ServiceBroker { .await .get_sender(); use tokio::sync::oneshot; - let (tx, rx) = oneshot::channel(); + let (oneshot_tx, mut oneshot_rx) = oneshot::channel::(); let service_request = ServiceRequest { request_id: ServiceRequestId { request_id: request.get_id(), }, payload: request.rpc.clone(), - respond_to: tx, + respond_to: oneshot_tx, }; - services_tx.send(service_request).await.unwrap(); + services_tx.try_send(service_request).unwrap(); + + match oneshot_rx.await { + Ok(response) => { + info!("ServiceBroker received response: {:?}", response); + //let _ = request.respond(response); + } + Err(e) => { + error!("ServiceBroker failed to receive response {}", e); + // let _ = request.respond(ripple_sdk::api::rpc_utils::ErrorResponse { + // error: ripple_sdk::api::rpc_utils::Error { + // code: -32603, + // message: "Failed to receive response".to_string(), + // data: None, + // }, + // }); + } + } info!("ServiceBroker received request: {:?}", request); } }); From 6447b01ced23d1b69d4c3fed727eed1d17d9ebd1 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Mon, 12 May 2025 13:11:16 -0700 Subject: [PATCH 05/46] checkpont --- core/main/src/broker/service_broker.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index ca676af04..0e13cca7b 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use futures_channel::oneshot; use ripple_sdk::{ - api::rules_engine::RuleEngineProvider, + api::{gateway::rpc_gateway_api::JsonRpcApiResponse, rules_engine::RuleEngineProvider}, log::{error, info}, tokio::{ self, @@ -17,8 +17,7 @@ use tokio_tungstenite::tungstenite::http::request; use crate::state::platform_state::{self, PlatformState}; use super::endpoint_broker::{ - BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerRequest, BrokerSender, - EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, + BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerOutputForwarder, BrokerRequest, BrokerSender, EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE }; pub struct ServiceBroker { @@ -29,6 +28,19 @@ pub struct ServiceBroker { broker_sender: BrokerSender, cleaner: BrokerCleaner, } +async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest, body: &[u8]) { + match BrokerOutputForwarder::handle_non_jsonrpc_response( + body, + callback.clone(), + request.clone(), + ) { + Ok(_) => {} + Err(e) => { + error!("Error message from http broker {:?}", e) + } + } +} + impl ServiceBroker {} impl EndpointBroker for ServiceBroker { @@ -42,7 +54,7 @@ impl EndpointBroker for ServiceBroker { // let endpoint = request.endpoint.clone(); let (tx, mut tr) = mpsc::channel(BROKER_CHANNEL_BUFFER_SIZE); let broker_sender = BrokerSender { sender: tx }; - + let callback = broker_callback.clone(); if let Some(platform_state) = ps.clone() { tokio::spawn(async move { while let Some(request) = tr.recv().await { @@ -66,7 +78,8 @@ impl EndpointBroker for ServiceBroker { match oneshot_rx.await { Ok(response) => { info!("ServiceBroker received response: {:?}", response); - //let _ = request.respond(response); + ::send_broker_success_response(&callback, response.into()); + } Err(e) => { error!("ServiceBroker failed to receive response {}", e); @@ -79,7 +92,7 @@ impl EndpointBroker for ServiceBroker { // }); } } - info!("ServiceBroker received request: {:?}", request); + } }); } else { From 67db56bbc434c7ac708c84cb3f15945b1dbf6f9c Mon Sep 17 00:00:00 2001 From: brendanobra Date: Mon, 19 May 2025 13:56:56 -0700 Subject: [PATCH 06/46] chore: ssda as submodules --- Cargo.lock | 1 + core/main/Cargo.toml | 4 +- core/main/src/bootstrap/start_ws_step.rs | 2 - core/main/src/broker/endpoint_broker.rs | 8 ++-- core/main/src/broker/service_broker.rs | 61 +++++++++++++----------- core/main/src/firebolt/firebolt_ws.rs | 24 ++-------- 6 files changed, 43 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c33c91096..7c6a7e0b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3893,6 +3893,7 @@ dependencies = [ "futures-util", "http 0.2.12", "mockall", + "ripple_sdk", "serde", "serde_json", "stream-tungstenite", diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index 99694eb35..b7e883c20 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -70,8 +70,8 @@ jaq-std = { version = "1.5.1", default-features = false } openrpc_validator = { path = "../../openrpc_validator" } proc-macro2.workspace = true -ssda_service = {path = "../../../../ssda/ssda_service/"} -ssda_types = {path = "../../../../ssda/ssda_types/"} +ssda_service = {path = "../../ssda/ssda_service/"} +ssda_types = {path = "../../ssda/ssda_types/"} diff --git a/core/main/src/bootstrap/start_ws_step.rs b/core/main/src/bootstrap/start_ws_step.rs index c5d90b22f..745ef752b 100644 --- a/core/main/src/bootstrap/start_ws_step.rs +++ b/core/main/src/bootstrap/start_ws_step.rs @@ -19,11 +19,9 @@ use ripple_sdk::{ async_trait::async_trait, framework::bootstrap::Bootstep, tokio, utils::error::RippleError, }; -use crate::firebolt::handlers::audio_description_rpc; use crate::state::bootstrap_state::BootstrapState; use crate::firebolt::firebolt_ws::FireboltWs; -use crate::state::openrpc_state::ApiSurface; pub struct StartWsStep; diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 31e475013..4982d3dc0 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -56,9 +56,7 @@ use crate::{ firebolt::firebolt_gateway::JsonRpcError, service::extn::ripple_client::RippleClient, state::{ - ops_metrics_state::OpMetricState, - platform_state::{self, PlatformState}, - session_state::Session, + ops_metrics_state::OpMetricState, platform_state::PlatformState, session_state::Session, }, utils::router_utils::{ add_telemetry_status_code, capture_stage, get_rpc_header, return_extn_response, @@ -915,10 +913,10 @@ impl EndpointBrokerState { ) .await { - Ok(yay) => true, + Ok(_yay) => true, Err(e) => { error!("Error in brokerage {:?}", e); - return false; + false } } } diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 0e13cca7b..af4ba345b 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -1,24 +1,18 @@ -use std::sync::Arc; - -use futures_channel::oneshot; use ripple_sdk::{ - api::{gateway::rpc_gateway_api::JsonRpcApiResponse, rules_engine::RuleEngineProvider}, + api::gateway::rpc_gateway_api::{JsonRpcApiError, JsonRpcApiResponse}, log::{error, info}, - tokio::{ - self, - sync::mpsc::{self, Sender}, - }, - utils::rpc_utils, + tokio::sync::mpsc, }; -use ssda_types::gateway::{ServiceRequest, ServiceResponse}; +use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; use ssda_types::ServiceRequestId; -use tokio_tungstenite::tungstenite::http::request; -use crate::state::platform_state::{self, PlatformState}; +use crate::state::platform_state::PlatformState; use super::endpoint_broker::{ - BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerOutputForwarder, BrokerRequest, BrokerSender, EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE + BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerOutputForwarder, BrokerRequest, + BrokerSender, EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, }; +use ripple_sdk::tokio; pub struct ServiceBroker { platform_state: Option, @@ -41,7 +35,6 @@ async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest } } - impl ServiceBroker {} impl EndpointBroker for ServiceBroker { fn get_broker( @@ -58,16 +51,18 @@ impl EndpointBroker for ServiceBroker { if let Some(platform_state) = ps.clone() { tokio::spawn(async move { while let Some(request) = tr.recv().await { + info!("ServiceBroker received request: {:?}", request); let services_tx = platform_state .services_gateway_api .lock() .await .get_sender(); use tokio::sync::oneshot; - let (oneshot_tx, mut oneshot_rx) = oneshot::channel::(); - let service_request = ServiceRequest { + + let (oneshot_tx, oneshot_rx) = oneshot::channel::(); + let service_request = ServiceRoutingRequest { request_id: ServiceRequestId { - request_id: request.get_id(), + request_id: request.rpc.ctx.call_id, }, payload: request.rpc.clone(), respond_to: oneshot_tx, @@ -78,21 +73,33 @@ impl EndpointBroker for ServiceBroker { match oneshot_rx.await { Ok(response) => { info!("ServiceBroker received response: {:?}", response); - ::send_broker_success_response(&callback, response.into()); - + match response { + ServiceRoutingResponse::Error(e) => { + error!("ServiceBroker received error response: {:?}", e); + let err = JsonRpcApiError::default() + .with_id(e.request_id.request_id) + .with_message(e.error) + .to_response(); + send_broker_response(&callback, &request, &err.as_bytes()) + .await; + } + ServiceRoutingResponse::Success(response) => { + info!( + "ServiceBroker received success response: {:?}", + response + ); + let win = JsonRpcApiResponse::default() + .with_id(response.request_id.request_id) + .with_result(Some(response.response)) + .as_bytes(); + send_broker_response(&callback, &request, &win).await; + } + } } Err(e) => { error!("ServiceBroker failed to receive response {}", e); - // let _ = request.respond(ripple_sdk::api::rpc_utils::ErrorResponse { - // error: ripple_sdk::api::rpc_utils::Error { - // code: -32603, - // message: "Failed to receive response".to_string(), - // data: None, - // }, - // }); } } - } }); } else { diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 294250982..f5b9024d4 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -28,12 +28,9 @@ use crate::{ session_state::Session, }, }; +use futures::SinkExt; use futures::StreamExt; -use futures::{ - stream::{SplitSink, SplitStream}, - SinkExt, -}; -use hyper::client::service; + use jsonrpsee::types::{error::INVALID_REQUEST_CODE, ErrorObject, ErrorResponse, Id}; use ripple_sdk::{ api::{ @@ -42,7 +39,7 @@ use ripple_sdk::{ }, observability::log_signal::LogSignal, }, - log::{error, info, trace}, + log::{error, info}, tokio::{ net::{TcpListener, TcpStream}, sync::{mpsc, oneshot, Mutex}, @@ -215,7 +212,6 @@ impl FireboltWs { let (connect_tx, connect_rx) = oneshot::channel::(); let service_manager_clone = Arc::clone(&service_manager); let service_connection_state = Arc::new(std::sync::Mutex::new(None)); - let service_manager_for_connection = service_manager_clone.clone(); let cfg = ConnectionCallbackConfig { next: connect_tx, app_state: app_state.clone(), @@ -240,17 +236,11 @@ impl FireboltWs { let service_id = service_connection.service_id.clone(); info!("Service connection for service_id={:?}", service_id); - let state_for_connection_c = state_for_connection.clone(); tokio::spawn(async move { FireboltWs::handle_service_connection( service_id, - // send, - // recv, service_manager_clone, ws_stream, - connect_rx, - state_for_connection_c.clone(), - secure, ) .await; }); @@ -275,20 +265,12 @@ impl FireboltWs { } async fn handle_service_connection( service_id: ServiceId, - //send: SplitSink, Message>, - //recv: SplitStream>, service_manager: Arc>>, ws_stream: WebSocketStream, - connect_rx: oneshot::Receiver, - state: PlatformState, - gateway_secure: bool, ) { info!("handle_service_connection"); - //let (mut send, mut recv) = ws_stream.split(); - let identity = connect_rx.await.unwrap(); { let mut guard = service_manager.lock().await; - let mut instance = guard.as_mut(); guard.service_connect(service_id, ws_stream).await.unwrap(); } } From 973692a65b1cbf22389d2ec119277b1870c07c7e Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 06:21:59 -0700 Subject: [PATCH 07/46] chore: adding ssda dirs --- ssda | 1 + 1 file changed, 1 insertion(+) create mode 160000 ssda diff --git a/ssda b/ssda new file mode 160000 index 000000000..c045f22f8 --- /dev/null +++ b/ssda @@ -0,0 +1 @@ +Subproject commit c045f22f8e5b1a906f3813f22e2ce1a806438601 From ca330d3d554f41d7d117a1fd2cfeea4fee715754 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 06:23:32 -0700 Subject: [PATCH 08/46] removing rules engine (moved to sdk) --- core/main/src/broker/rules_engine.rs | 708 --------------------------- 1 file changed, 708 deletions(-) delete mode 100644 core/main/src/broker/rules_engine.rs diff --git a/core/main/src/broker/rules_engine.rs b/core/main/src/broker/rules_engine.rs deleted file mode 100644 index 015682599..000000000 --- a/core/main/src/broker/rules_engine.rs +++ /dev/null @@ -1,708 +0,0 @@ -// // Copyright 2023 Comcast Cable Communications Management, LLC -// // -// // Licensed under the Apache License, Version 2.0 (the "License"); -// // you may not use this file except in compliance with the License. -// // You may obtain a copy of the License at -// // -// // http://www.apache.org/licenses/LICENSE-2.0 -// // -// // Unless required by applicable law or agreed to in writing, software -// // distributed under the License is distributed on an "AS IS" BASIS, -// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// // See the License for the specific language governing permissions and -// // limitations under the License. -// // -// // SPDX-License-Identifier: Apache-2.0 -// // -// use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val}; -// use ripple_sdk::api::{ -// gateway::rpc_gateway_api::RpcRequest, manifest::extn_manifest::ExtnManifest, -// }; - -// use ripple_sdk::{ -// chrono::Utc, -// log::{debug, error, info, trace, warn}, -// serde_json::Value, -// utils::error::RippleError, -// }; -// use serde::{Deserialize, Serialize}; -// use std::collections::HashMap; - -// use std::{fs, path::Path}; - -// #[derive(Debug, Deserialize, Default, Clone)] -// pub struct RuleSet { -// pub endpoints: HashMap, -// pub rules: HashMap, -// } - -// impl RuleSet { -// pub fn append(&mut self, rule_set: RuleSet) { -// self.endpoints.extend(rule_set.endpoints); -// let rules: HashMap = rule_set -// .rules -// .into_iter() -// .map(|(k, v)| { -// trace!("Loading JQ Rule for {}", k.to_lowercase()); -// (k.to_lowercase(), v) -// }) -// .collect(); -// self.rules.extend(rules); -// } -// pub fn get(&self, key: &str) -> Option<&Rule> { -// self.rules.get(key) -// } -// } -// #[derive(Debug, Deserialize, Clone, Default)] -// pub struct RuleEndpoint { -// pub protocol: RuleEndpointProtocol, -// pub url: String, -// #[serde(default = "default_autostart")] -// pub jsonrpc: bool, -// } - -// impl RuleEndpoint { -// pub fn get_url(&self) -> String { -// if cfg!(feature = "local_dev") { -// if let Ok(host_override) = std::env::var("DEVICE_HOST") { -// if !host_override.is_empty() { -// return self.url.replace("127.0.0.1", &host_override); -// } -// } -// } -// self.url.clone() -// } -// } - -// fn default_autostart() -> bool { -// true -// } - -// #[derive(Deserialize, Debug, Clone, Default)] -// #[serde(rename_all = "lowercase")] -// #[cfg_attr(test, derive(PartialEq))] -// pub enum RuleEndpointProtocol { -// #[default] -// Websocket, -// Http, -// Thunder, -// Workflow, -// Extn, -// } -// #[derive(Debug, Default, Clone, Serialize, Deserialize)] -// pub struct JsonDataSource { -// // configurable namespace to "stuff" an in individual result payload into -// pub namespace: Option, -// pub method: String, -// pub params: Option, -// } - -// #[derive(Debug, Default, Clone, Serialize, Deserialize)] -// pub struct Rule { -// pub alias: String, -// // Not every rule needs transform -// #[serde(default)] -// pub transform: RuleTransform, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub filter: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub event_handler: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub endpoint: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub sources: Option>, -// } -// impl std::fmt::Display for Rule { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// write!(f, "Rule {{ alias: {} }}", self.alias) -// } -// } -// /* -// war on dots -// */ -// #[derive(PartialEq)] -// pub enum RuleType { -// Static, -// Provider, -// Endpoint, -// } -// impl Rule { -// fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { -// self.transform.apply_context(rpc_request); -// self -// } -// pub fn rule_type(&self) -> RuleType { -// match self.alias.trim().to_ascii_lowercase().as_str() { -// "static" => RuleType::Static, -// "provided" => RuleType::Provider, -// /* -// maps to a sender that can be used to send a message to the endpoint, for instance: Thunder -// */ -// _ => RuleType::Endpoint, -// } -// } -// pub fn with_alias(&mut self, alias: String) -> &mut Self { -// self.alias = alias; -// self -// } -// pub fn with_rule_tranformt(&mut self, transform: RuleTransform) -> &mut Self { -// self.transform = transform; -// self -// } -// pub fn with_filter(&mut self, filter: String) -> &mut Self { -// self.filter = Some(filter); -// self -// } -// pub fn with_event_handler(&mut self, event_handler: String) -> &mut Self { -// self.event_handler = Some(event_handler); -// self -// } -// pub fn with_endpoint(&mut self, endpoint: String) -> &mut Self { -// self.endpoint = Some(endpoint); -// self -// } -// pub fn with_sources(&mut self, sources: Vec) -> &mut Self { -// self.sources = Some(sources); -// self -// } -// pub fn with_source(&mut self, source: JsonDataSource) -> &mut Self { -// if let Some(sources) = &mut self.sources { -// sources.push(source); -// } else { -// self.sources = Some(vec![source]); -// } -// self -// } -// } - -// #[derive(Debug, Default, Clone, Serialize, Deserialize)] -// pub struct RuleTransform { -// #[serde(skip_serializing_if = "Option::is_none")] -// pub request: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub response: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub event: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub rpcv2_event: Option, -// #[serde(skip_serializing_if = "Option::is_none")] -// pub event_decorator_method: Option, -// } - -// impl RuleTransform { -// fn check_and_replace(&self, input: &str, rpc_request: &RpcRequest) -> String { -// trace!( -// "check_and_replace: input: {}, rpc_request: {:?}", -// input, -// rpc_request -// ); - -// let mut output = input.replace("$context.appId", &rpc_request.ctx.app_id); - -// if let Some(event) = &self.event { -// output = output.replace("$event", event); -// } - -// output -// } - -// pub fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { -// if let Some(value) = self.request.take() { -// let _ = self -// .request -// .insert(self.check_and_replace(&value, rpc_request)); -// } - -// if let Some(value) = self.event.take() { -// let _ = self -// .event -// .insert(self.check_and_replace(&value, rpc_request)); -// } - -// if let Some(value) = self.rpcv2_event.take() { -// let _ = self -// .rpcv2_event -// .insert(self.check_and_replace(&value, rpc_request)); -// } -// self -// } - -// pub fn get_transform_data(&self, typ: RuleTransformType) -> Option { -// match typ { -// RuleTransformType::Request => self.request.clone(), -// RuleTransformType::Event(rpc_v2) => { -// if rpc_v2 { -// self.rpcv2_event.clone() -// } else { -// self.event.clone() -// } -// } -// RuleTransformType::Response => self.response.clone(), -// } -// } -// } - -// pub enum RuleTransformType { -// Request, -// Response, -// Event(bool), -// } - -// #[derive(Debug, Clone, Default)] -// pub struct RuleEngine { -// pub rules: RuleSet, -// } - -// impl RuleEngine { -// fn build_path(path: &str, default_path: &str) -> String { -// if path.starts_with('/') { -// path.to_owned() -// } else { -// format!("{}{}", default_path, path) -// } -// } - -// pub fn load(path: &str) -> Result { -// let path = Path::new(path); -// if path.exists() { -// let contents = fs::read_to_string(path).unwrap(); -// Self::load_from_string_literal(contents) -// } else { -// warn!("path for the rule is invalid {}", path.display()); -// Err(RippleError::InvalidInput) -// } -// } -// pub fn load_from_string_literal(contents: String) -> Result { -// let (_content, rule_set) = Self::load_from_content(contents)?; -// let mut rules_engine = RuleEngine::default(); -// rules_engine.rules.append(rule_set); -// Ok(rules_engine.clone()) -// } - -// pub fn build(extn_manifest: &ExtnManifest) -> Self { -// trace!("building rules engine {:?}", extn_manifest.rules_path); -// let mut engine = RuleEngine::default(); -// for path in extn_manifest.rules_path.iter() { -// let path_for_rule = Self::build_path(path, &extn_manifest.default_path); -// debug!("loading rules file {}", path_for_rule); -// if let Some(p) = Path::new(&path_for_rule).to_str() { -// if let Ok(contents) = fs::read_to_string(p) { -// info!("Rules content {}", contents); -// info!("loading rules from path {}", path); -// info!("loading rule {}", path_for_rule); -// if let Ok((_, rule_set)) = Self::load_from_content(contents) { -// engine.rules.append(rule_set) -// } else { -// warn!("invalid rule found in path {}", path) -// } -// } else { -// warn!("path for the rule is invalid {}", path) -// } -// } else { -// warn!("invalid rule path {}", path) -// } -// } -// engine -// } - -// pub fn load_from_content(contents: String) -> Result<(String, RuleSet), RippleError> { -// match serde_json::from_str::(&contents) { -// Ok(manifest) => Ok((contents, manifest)), -// Err(err) => { -// error!("{:?} could not load rule", err); -// Err(RippleError::InvalidInput) -// } -// } -// } -// pub fn add_rules(&mut self, rules: RuleSet) { -// self.rules.append(rules); -// } -// pub fn add_rule(&mut self, rule: Rule) { -// self.rules.rules.insert(rule.alias.clone(), rule); -// } - -// pub fn has_rule(&self, request: &str) -> bool { -// self.rules.rules.contains_key(&request.to_lowercase()) -// } -// fn wildcard_match(rule_name: &str, method: &str) -> bool { -// rule_name.ends_with(".*") && method.starts_with(&rule_name[..rule_name.len() - 2]) -// } -// fn find_wildcard_rule( -// rules: &HashMap, -// method: &str, -// ) -> Result { -// let filtered_rules: Vec<&Rule> = rules -// .iter() -// .filter(|(rule_name, _)| Self::wildcard_match(rule_name, method)) -// .map(|(_, rule)| rule) -// .collect(); - -// match filtered_rules.len() { -// 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), -// 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), -// _ => Err(RuleRetrievalError::TooManyWildcardMatches), -// } -// } - -// pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { -// let method = rpc_request.method.to_lowercase(); -// /* -// match directly from method name -// */ -// if let Some(mut rule) = self.rules.get(&method).cloned() { -// return Ok(RuleRetrieved::ExactMatch( -// rule.apply_context(rpc_request).to_owned(), -// )); -// } else { -// /* -// * match, for example api.v1.* as rule name and api.v1.get as method name -// */ -// Self::find_wildcard_rule(&self.rules.rules, &method) -// } -// } - -// pub fn get_rule_by_method(&self, method: &str) -> Option { -// self.rules.rules.get(&method.to_lowercase()).cloned() -// } -// } -// #[derive(Debug)] -// pub enum RuleRetrieved { -// ExactMatch(Rule), -// WildcardMatch(Rule), -// } -// impl From for Rule { -// fn from(rule_retrieved: RuleRetrieved) -> Self { -// match rule_retrieved { -// RuleRetrieved::ExactMatch(rule) => rule, -// RuleRetrieved::WildcardMatch(rule) => rule, -// } -// } -// } - -// #[derive(Debug)] -// pub enum RuleRetrievalError { -// RuleNotFound(String), -// RuleNotFoundAsWildcard, -// TooManyWildcardMatches, -// } - -// /// Compiles and executes a JQ filter on a given JSON input value. -// /// -// /// # Arguments -// /// -// /// * `input` - A `serde_json::Value` representing the JSON input to be processed. -// /// * `filter` - A string slice that holds the JQ filter to be applied. -// /// * `reference` - A string used for logging purposes to identify the rule being processed. -// /// -// /// # Returns -// /// -// /// * `Ok(Value)` - If the filter is successfully compiled and executed, returns the resulting JSON value. -// /// * `Err(RippleError)` - If there is an error during the compilation or execution of the filter, returns a `RippleError`. -// /// -// /// # Errors -// /// -// /// This function will return an error if: -// /// * The JQ filter contains syntax errors. -// /// * There are errors during the compilation of the filter. -// /// * The execution of the filter does not produce a valid output. -// /// -// /// # Example -// /// -// /// ``` -// /// use serde_json::json; -// /// use ripple_sdk::utils::error::RippleError; -// /// use crate::jq_compile; -// /// -// /// let filter = "if .success then .stbVersion else { code: -32100, message: \"couldn't get version\" } end"; -// /// let input = json!({ -// /// "stbVersion": "SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", -// /// "success": true -// /// }); -// /// let result = jq_compile(input, filter, String::new()); -// /// assert_eq!(result.unwrap(), json!("SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT")); -// /// ``` -// pub fn jq_compile(input: Value, filter: &str, reference: String) -> Result { -// info!( -// "Jq rule {} input {:?}, reference {}", -// filter, input, reference -// ); -// let start = Utc::now().timestamp_millis(); -// // start out only from core filters, -// // which do not include filters in the standard library -// // such as `map`, `select` etc. - -// let mut defs = ParseCtx::new(Vec::new()); -// defs.insert_natives(jaq_core::core()); -// defs.insert_defs(jaq_std::std()); -// // parse the filter -// let (f, errs) = jaq_parse::parse(filter, jaq_parse::main()); -// if !errs.is_empty() { -// error!("Error in rule {:?}", errs); -// return Err(RippleError::RuleError); -// } -// // compile the filter in the context of the given definitions -// let f = defs.compile(f.unwrap()); -// if !defs.errs.is_empty() { -// error!("Error in rule {}", reference); -// for (err, _) in defs.errs { -// error!("reference={} {}", reference, err); -// } -// return Err(RippleError::RuleError); -// } - -// let inputs = RcIter::new(core::iter::empty()); -// // iterator over the output values -// let mut out = f.run((Ctx::new([], &inputs), Val::from(input))); -// if let Some(Ok(v)) = out.next() { -// info!( -// "Ripple Gateway Rule Processing Time: {},{}", -// reference, -// Utc::now().timestamp_millis() - start -// ); -// return Ok(Value::from(v)); -// } - -// Err(RippleError::ParseError) -// } -// pub fn compose_json_values(values: Vec) -> Value { -// if values.len() == 1 { -// return values[0].clone(); -// } -// debug!("Composing values {:?}", values); - -// let mut composition_filter = ".[0]".to_string(); -// for v in 1..values.len() { -// composition_filter = format!("{} * .[{}]", composition_filter, v); -// } -// match jq_compile(Value::Array(values), &composition_filter, String::new()) { -// Ok(composed_value) => composed_value, -// Err(err) => { -// error!("Failed to compose JSON values with error: {:?}", err); -// Value::Null // Return a default value on failure -// } -// } -// } -// pub fn make_name_json_safe(name: &str) -> String { -// name.replace([' ', '.', ','], "_") -// } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; -// use ripple_sdk::serde_json::json; - -// #[test] -// fn test_jq_compile() { -// let filter = "if .success then ( .stbVersion | split(\"_\")[0] ) else { code: -32100, message: \"couldn't get version\" } end"; -// let input = json!({ -// "stbVersion":"SCXI11BEI_VBN_24Q2_sprint_20240620140024sdy_FG_GRT", -// "receiverVersion":"7.2.0.0", -// "stbTimestamp":"Thu 20 Jun 2024 14:00:24 UTC", -// "success":true -// }); -// let resp = jq_compile(input, filter, String::new()); -// assert_eq!(resp.unwrap(), "SCXI11BEI".to_string()); - -// let filter = "{ namespace: \"refui\", scope: .scope, key: .key, value: .value }"; -// let input = json!({ -// "key": "key3", -// "scope": "account", -// "value": "value2" -// }); -// let resp = jq_compile(input, filter, String::new()); -// let expected = json!({ -// "namespace": "refui", -// "key": "key3", -// "scope": "account", -// "value": "value2" -// }); -// assert_eq!(resp.unwrap(), expected); - -// let filter = "if .success and ( .supportedHDCPVersion | contains(\"2.2\")) then {\"hdcp2.2\": true} elif .success and ( .supportedHDCPVersion | contains(\"1.4\")) then {\"hdcp1.4\": true} else {\"code\": -32100, \"message\": \"couldn't get version\"} end"; -// let input = json!({ -// "supportedHDCPVersion":"2.2", -// "isHDCPSupported":true, -// "success":true -// }); -// let resp = jq_compile(input, filter, String::new()); -// let expected = json!({ -// "hdcp2.2": true -// }); -// assert_eq!(resp.unwrap(), expected); - -// let filter = "if .success then (.value | fromjson | .value) else { \"code\": -32100, \"message\": \"couldn't get language\" } end"; -// let input = json!({ -// "value": "{\"update_time\":\"2024-07-26T23:39:57.831726080Z\",\"value\":\"EN\"}", -// "success":true -// }); -// let resp = jq_compile(input, filter, String::new()); -// assert_eq!(resp.unwrap(), "EN".to_string()); -// } -// #[test] -// fn test_composed_jq_compile() { -// let a = json!({"asome": "avalue"}); -// let b = json!({"bsome": "bvalue"}); -// let c = json!({"csome": {"cvalue" : "nested"}}); -// let vals = vec![a, b, c]; -// let mut composition_filter = ".[0]".to_string(); -// for v in 1..vals.len() { -// composition_filter = format!("{} * .[{}]", composition_filter, v); -// } - -// assert!(jq_compile( -// jq_compile( -// Value::Array(vals.clone()), -// &composition_filter, -// String::new() -// ) -// .unwrap(), -// ".asome", -// String::new() -// ) -// .unwrap() -// .as_str() -// .unwrap() -// .contains("avalue")); -// assert!(jq_compile( -// jq_compile( -// Value::Array(vals.clone()), -// &composition_filter, -// String::new() -// ) -// .unwrap(), -// ".bsome", -// String::new() -// ) -// .unwrap() -// .as_str() -// .unwrap() -// .contains("bvalue")); -// assert!(jq_compile( -// jq_compile( -// Value::Array(vals.clone()), -// &composition_filter, -// String::new() -// ) -// .unwrap(), -// ".csome.cvalue", -// String::new() -// ) -// .unwrap() -// .as_str() -// .unwrap() -// .contains("nested")); -// } -// use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; - -// #[test] -// fn test_get_rule_exact_match() { -// let mut rule_set = RuleSet::default(); -// let rule = Rule { -// alias: "test_rule".to_string(), -// ..Default::default() -// }; -// rule_set -// .rules -// .insert("test.method".to_string(), rule.clone()); - -// let rule_engine = RuleEngine { rules: rule_set }; - -// let rpc_request = RpcRequest { -// method: "test.method".to_string(), -// ctx: CallContext { -// app_id: "test_app".to_string(), -// method: "test.method".to_string(), -// ..Default::default() -// }, -// ..Default::default() -// }; - -// let result = rule_engine.get_rule(&rpc_request); -// match result { -// Ok(RuleRetrieved::ExactMatch(retrieved_rule)) => { -// assert_eq!(retrieved_rule.alias, rule.alias); -// } -// _ => panic!("Expected exact match, but got {:?}", result), -// } -// } - -// #[test] -// fn test_get_rule_wildcard_match() { -// let mut rule_set = RuleSet::default(); -// let rule = Rule { -// alias: "wildcard_rule".to_string(), -// ..Default::default() -// }; -// rule_set.rules.insert("api.v1.*".to_string(), rule.clone()); - -// let rule_engine = RuleEngine { rules: rule_set }; - -// let rpc_request = RpcRequest { -// method: "api.v1.get".to_string(), -// ctx: CallContext { -// app_id: "test_app".to_string(), -// method: "api.v1.get".to_string(), -// ..Default::default() -// }, -// ..Default::default() -// }; - -// let result = rule_engine.get_rule(&rpc_request); -// match result { -// Ok(RuleRetrieved::WildcardMatch(retrieved_rule)) => { -// assert_eq!(retrieved_rule.alias, rule.alias); -// } -// _ => panic!("Expected wildcard match, but got {:?}", result), -// } -// } - -// #[test] -// fn test_get_rule_no_match() { -// let rule_set = RuleSet::default(); -// let rule_engine = RuleEngine { rules: rule_set }; - -// let rpc_request = RpcRequest { -// method: "nonexistent.method".to_string(), -// ctx: CallContext { -// app_id: "test_app".to_string(), -// method: "nonexistent.method".to_string(), -// ..Default::default() -// }, -// ..Default::default() -// }; - -// let result = rule_engine.get_rule(&rpc_request); -// assert!(matches!( -// result, -// Err(RuleRetrievalError::RuleNotFoundAsWildcard) -// )); -// } - -// #[test] -// fn test_get_rule_multiple_wildcard_matches() { -// let mut rule_set = RuleSet::default(); -// rule_set -// .rules -// .insert("api.v1.*".to_string(), Rule::default()); -// rule_set.rules.insert("api.*".to_string(), Rule::default()); - -// let rule_engine = RuleEngine { rules: rule_set }; - -// let rpc_request = RpcRequest { -// method: "api.v1.get".to_string(), -// ctx: CallContext { -// app_id: "test_app".to_string(), -// method: "api.v1.get".to_string(), -// ..Default::default() -// }, -// ..Default::default() -// }; - -// let result = rule_engine.get_rule(&rpc_request); -// assert!(matches!( -// result, -// Err(RuleRetrievalError::TooManyWildcardMatches) -// )); -// } -// } From e95307482c8556e261ba9d6d8d4212530da349ef Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 06:36:17 -0700 Subject: [PATCH 09/46] fix: move rules engine --- core/main/src/broker/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/main/src/broker/mod.rs b/core/main/src/broker/mod.rs index d4e44bce6..6728214c5 100644 --- a/core/main/src/broker/mod.rs +++ b/core/main/src/broker/mod.rs @@ -20,7 +20,7 @@ pub mod event_management_utility; pub mod extn_broker; pub mod http_broker; pub mod provider_broker_state; -pub mod rules_engine; + pub mod service_broker; #[cfg(test)] pub mod test; From f6954cce80816756346aaf4928ed0eb7b3d8dd4f Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 06:41:28 -0700 Subject: [PATCH 10/46] chore: ssda as directory --- ssda | 1 - ssda/.gitignore | 1 + ssda/Cargo.toml | 5 + ssda/bak/.gitignore | 1 + ssda/bak/Cargo.toml | 5 + ssda/bak/rust-toolchain.toml | 2 + ssda/example-service/Cargo.toml | 14 + ssda/example-service/src/main.rs | 85 +++ ssda/rust-toolchain.toml | 2 + ssda/ssda_client/Cargo.toml | 16 + ssda/ssda_client/src/lib.rs | 50 ++ ssda/ssda_service/Cargo.toml | 19 + ssda/ssda_service/src/lib.rs | 546 +++++++++++++++ ssda/ssda_tranports/Cargo.toml | 6 + ssda/ssda_tranports/src/main.rs | 3 + ssda/ssda_types/Cargo.toml | 23 + ssda/ssda_types/src/api_gateway_client.rs | 1 + ssda/ssda_types/src/api_gateway_server.rs | 1 + ssda/ssda_types/src/lib.rs | 771 ++++++++++++++++++++++ ssda/ssda_types/src/service_api.rs | 1 + 20 files changed, 1552 insertions(+), 1 deletion(-) delete mode 160000 ssda create mode 100644 ssda/.gitignore create mode 100644 ssda/Cargo.toml create mode 100644 ssda/bak/.gitignore create mode 100644 ssda/bak/Cargo.toml create mode 100644 ssda/bak/rust-toolchain.toml create mode 100644 ssda/example-service/Cargo.toml create mode 100644 ssda/example-service/src/main.rs create mode 100644 ssda/rust-toolchain.toml create mode 100644 ssda/ssda_client/Cargo.toml create mode 100644 ssda/ssda_client/src/lib.rs create mode 100644 ssda/ssda_service/Cargo.toml create mode 100644 ssda/ssda_service/src/lib.rs create mode 100644 ssda/ssda_tranports/Cargo.toml create mode 100644 ssda/ssda_tranports/src/main.rs create mode 100644 ssda/ssda_types/Cargo.toml create mode 100644 ssda/ssda_types/src/api_gateway_client.rs create mode 100644 ssda/ssda_types/src/api_gateway_server.rs create mode 100644 ssda/ssda_types/src/lib.rs create mode 100644 ssda/ssda_types/src/service_api.rs diff --git a/ssda b/ssda deleted file mode 160000 index c045f22f8..000000000 --- a/ssda +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c045f22f8e5b1a906f3813f22e2ce1a806438601 diff --git a/ssda/.gitignore b/ssda/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/ssda/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ssda/Cargo.toml b/ssda/Cargo.toml new file mode 100644 index 000000000..3106b8a15 --- /dev/null +++ b/ssda/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +resolver = "2" +members = [ "example-service", "ssda_client","ssda_service", "ssda_tranports", "ssda_types"] + + diff --git a/ssda/bak/.gitignore b/ssda/bak/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/ssda/bak/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ssda/bak/Cargo.toml b/ssda/bak/Cargo.toml new file mode 100644 index 000000000..3106b8a15 --- /dev/null +++ b/ssda/bak/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +resolver = "2" +members = [ "example-service", "ssda_client","ssda_service", "ssda_tranports", "ssda_types"] + + diff --git a/ssda/bak/rust-toolchain.toml b/ssda/bak/rust-toolchain.toml new file mode 100644 index 000000000..2e2b8c852 --- /dev/null +++ b/ssda/bak/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.82.0" diff --git a/ssda/example-service/Cargo.toml b/ssda/example-service/Cargo.toml new file mode 100644 index 000000000..caf0534bf --- /dev/null +++ b/ssda/example-service/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "example-service" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.88" +serde_json = "1.0.140" +ssda_types = {path="../ssda_types"} +ssda_client = {path = "../ssda_client"} +tokio = "1.44.2" +mockall = "0.13.1" +tokio-websockets = "0.11.4" +log = "0.4.27" diff --git a/ssda/example-service/src/main.rs b/ssda/example-service/src/main.rs new file mode 100644 index 000000000..8199f4992 --- /dev/null +++ b/ssda/example-service/src/main.rs @@ -0,0 +1,85 @@ +use std::{sync::Arc, vec}; + +use ssda_client::APIGatewayClientBuilder; +use ssda_types::client::ServiceRequestHandlerImpl; +use ssda_types::service::{ + FireboltMethodHandlerAPIRegistration, FireboltMethodHandlerRegistration, ServiceCall, + ServiceCallErrorResponse, ServiceCallSuccessResponse, ServiceRegistration, +}; +use ssda_types::{JqRule, ServiceId}; + +#[derive(Debug, Clone)] +pub struct ExampleService {} + +impl ExampleService { + pub fn new() -> Self { + ExampleService {} + } +} + +#[async_trait::async_trait] +impl ServiceRequestHandlerImpl for ExampleService { + fn register(&self) -> Vec { + vec![] + } + fn handle_request( + &self, + request: ServiceCall, + ) -> Result { + // Handle the request and return a response + println!("handle_request: handling request {:?}", request); + match request.method.as_str() { + "device.audio" => Ok(ServiceCallSuccessResponse { + request_id: request.request_id, + response: serde_json::json!({ "status": "success" }), + }), + bad_method => { + return Err(ServiceCallErrorResponse { + request_id: request.request_id, + error: format!("Unknown method: {}", bad_method), + }); + } + } + } + fn on_connected(&self) { + println!("example connected") + } + fn on_disconnected(&self) { + println!("disconnected") + } + fn healthy(&self) -> bool { + todo!() + } +} +#[tokio::main] +async fn main() { + let my_handler = ExampleService::new(); + let mut firebolt_handlers = Vec::new(); + firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { + firebolt_method: "device.audio".to_string(), + jq_rule: Some(JqRule { + alias: "device.audio".to_string(), + rule: "jq_type".to_string(), + }), + }); + firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { + firebolt_method: "device.make".to_string(), + jq_rule: Some(JqRule { + alias: "device.make".to_string(), + rule: "jq_type".to_string(), + }), + }); + + let registration = ServiceRegistration { + service_id: ServiceId { + service_id: "example".to_string(), + }, + firebolt_handlers: firebolt_handlers, + }; + + let _ = APIGatewayClientBuilder::new(registration) + .websocket() + .build(Arc::new(my_handler)) + .start() + .await; +} diff --git a/ssda/rust-toolchain.toml b/ssda/rust-toolchain.toml new file mode 100644 index 000000000..2e2b8c852 --- /dev/null +++ b/ssda/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.82.0" diff --git a/ssda/ssda_client/Cargo.toml b/ssda/ssda_client/Cargo.toml new file mode 100644 index 000000000..6fbe7f198 --- /dev/null +++ b/ssda/ssda_client/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ssda_client" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = { version = "1", features = ["full"] } +ws = "0.9.2" +log = "0.4" +serde = { version = "1.0", features = ["derive"] } +ssda_types = {path = "../ssda_types"} +async-trait = "0.1.88" +serde_json = "1.0.140" +tokio-tungstenite = "0.20.1" +tungstenite = "0.26.2" +url = "2.5.4" \ No newline at end of file diff --git a/ssda/ssda_client/src/lib.rs b/ssda/ssda_client/src/lib.rs new file mode 100644 index 000000000..08384c780 --- /dev/null +++ b/ssda/ssda_client/src/lib.rs @@ -0,0 +1,50 @@ +use std::sync::Arc; + +use ssda_types::{ + service::{ServiceRegistration, ServiceRequestHandler}, + APIGatewayClient, DBUSAPIGatewayClient, WebsocketAPIGatewayClient, +}; +pub enum APIGatewayClientTransport { + WebSocket, + Dbus, +} +pub struct APIGatewayClientBuilder { + transport: APIGatewayClientTransport, + service_registration: ServiceRegistration, +} + +impl APIGatewayClientBuilder { + pub fn new(service_registration: ServiceRegistration) -> Self { + APIGatewayClientBuilder { + transport: APIGatewayClientTransport::WebSocket, + service_registration, + } + } + pub fn with_service_registration( + &mut self, + service_registration: ServiceRegistration, + ) -> &mut Self { + self.service_registration = service_registration; + self + } + + pub fn websocket(&mut self) -> &mut Self { + // Initialize WebSocket client + self.transport = APIGatewayClientTransport::WebSocket; + self + } + pub fn dbus(&mut self) -> &mut Self { + // Initialize DBus client + self.transport = APIGatewayClientTransport::Dbus; + self + } + pub fn build(&self, handler: Arc) -> Box { + match self.transport { + APIGatewayClientTransport::WebSocket => Box::new(WebsocketAPIGatewayClient::new( + handler, + self.service_registration.clone(), + )), + APIGatewayClientTransport::Dbus => Box::new(DBUSAPIGatewayClient {}), + } + } +} diff --git a/ssda/ssda_service/Cargo.toml b/ssda/ssda_service/Cargo.toml new file mode 100644 index 000000000..3b7aed7d5 --- /dev/null +++ b/ssda/ssda_service/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "ssda_service" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.88" +serde_json = "1.0.140" +ssda_types = {path="../ssda_types"} +ssda_client = {path = "../ssda_client"} +ripple_sdk = {path = "../../core/sdk"} +tokio = "1.44.2" +mockall = "0.13.1" +tokio-tungstenite = "0.20.1" +http = "0.2.12" +url = "2.5.4" +log = "0.4.27" +futures-util = "0.3.31" +uuid = { version = "1.13.1", default-features = false, features = ["v4"] } \ No newline at end of file diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs new file mode 100644 index 000000000..4cd823963 --- /dev/null +++ b/ssda/ssda_service/src/lib.rs @@ -0,0 +1,546 @@ +/* +This is the API gateway, and it meant to be hosted in the main ripple process +*/ + +use std::{collections::HashMap, f32::consts::E, sync::Arc}; + +use futures_util::stream::SplitSink; +use futures_util::stream::StreamExt; +use futures_util::SinkExt; +use http::Uri; +use log::{error, info}; + +use ripple_sdk::api::rules_engine::{Rule, RuleEngineProvider, RuleTransform}; +use tokio::sync::{mpsc, RwLock}; +pub struct ServiceMap { + service_map: HashMap>, +} +impl ServiceMap { + fn new() -> Self { + Self { + service_map: HashMap::new(), + } + } + fn add_service( + &mut self, + service_id: ServiceId, + registrations: Vec, + ) { + self.service_map.insert(service_id, registrations); + } + fn remove_service(&mut self, service_id: &ServiceId) { + self.service_map.remove(service_id); + } + fn get_registrations( + &self, + service_id: &ServiceId, + ) -> Vec { + self.service_map.get(service_id).unwrap_or(&vec![]).clone() + } + fn get_service_for_method( + &self, + method: &str, + ) -> Option<(ServiceId, FireboltMethodHandlerAPIRegistration)> { + for (service_id, registrations) in self.service_map.iter() { + for registration in registrations.iter() { + if registration.firebolt_method == method { + return Some((service_id.clone(), registration.clone())); + } + } + } + None + } +} +pub struct WebSocketChannels { + pub tx: mpsc::Sender, + pub rx: mpsc::Receiver, +} +pub struct ApiGateway { + pub service_endpoints: Arc>>>, + pub rules_engine: Arc>>, + pub methods_2_services: Arc>, + pub broker_sender: mpsc::Sender, + pub services_2_rxs: + Arc>>>, + pub reply_to_tx: mpsc::Sender, +} +pub enum APIGatewayClientState { + Failed(String), + Connecting, + Registering(APIGatewayServiceRegistrationRequest), + Connected, + Closed, + Message(ServiceRequestId, Value), + ServiceCallFailed(ServiceRequestId, String), +} +//static service_map:HashMap = HashMap::; + +impl ApiGateway { + pub fn new( + rules_engine: Arc>>, + ) -> Self { + let (tx, rx) = mpsc::channel::(32); + let (reply_to_tx, _) = mpsc::channel::(32); + let services_2_rxs = Arc::new(tokio::sync::RwLock::new(HashMap::new())); + + let me = Self { + service_endpoints: Arc::new(tokio::sync::RwLock::new(HashMap::new())), + rules_engine: rules_engine, + methods_2_services: Arc::new(tokio::sync::RwLock::new(ServiceMap::new())), + broker_sender: tx.clone(), + services_2_rxs: services_2_rxs.clone(), + reply_to_tx: reply_to_tx, + }; + + me.start(rx, Arc::clone(&services_2_rxs)); + + me + } + /* + start the task that handles the service routing requests, and routes them to the appropriate service + */ + pub fn start( + &self, + mut rx: mpsc::Receiver, + services_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + ) { + let methods_2_services = self.methods_2_services.clone(); + let services_2_rxs = Arc::clone(&services_2_rxes); + tokio::spawn(async move { + while let Some(request) = rx.recv().await { + let methods_2_services = methods_2_services.read().await; + let method = request.payload.method.clone(); + match methods_2_services.get_service_for_method(method.as_str()) { + Some((service_id, _registration)) => { + /* + send the request to the websocket handler for the service + */ + if let Some(service) = services_2_rxs.read().await.get(&service_id) { + let (send, receive) = oneshot::channel::(); + let payload = request.payload.clone(); + let websocket_request = WebsocketServiceRequest { + method: payload.method.clone(), + request_id: request.request_id.clone(), + payload: serde_json::to_value(payload).unwrap(), + respond_to: send, + }; + let _ = service.send(websocket_request).await; + match receive.await { + Ok(response) => { + info!("start Received response from service: {:?}", response); + match response { + WebsocketServiceResponse::Success(request_id, result) => { + info!("Received success response: {:?}", result); + // Send the response back to the broker + let _ = request.respond_to.send( + ServiceRoutingResponse::Success( + ServiceRoutingSuccessResponse { + request_id: request_id, + response: result, + }, + ), + ); + } + WebsocketServiceResponse::Error(request_id, error) => { + info!("Received error response: {:?}", error); + // Send the error response back to the broker + let _ = request.respond_to.send( + ServiceRoutingResponse::Error( + ServiceRoutingErrorResponse { + request_id: request_id, + error: error, + }, + ), + ); + } + } + } + Err(e) => { + error!("Failed to receive response from service: {:?}", e); + } + } + } else { + error!( + "else No service sender found for method: {:?} in {:?} ", + method, + services_2_rxs.read().await + ); + } + } + + None => { + error!("None No service found for method: {:?}", method); + } + } + } + }); + } + /// This function is used to check if the given URI is a service URL + pub fn is_apigateway_connection( + uri: &http::Uri, + ) -> Result { + // Check if the URI is a service URL + // This is a placeholder implementation + if !uri.path().starts_with("/apigateway") { + return Err(APIGatewayServiceConnectionError::NotAService); + } + + if let Some(query) = uri.query() { + let query_pairs = form_urlencoded::parse(query.as_bytes()); + for (key, value) in query_pairs { + if key == "serviceId" { + return Ok(APIGatewayServiceConnectionDisposition::Accept( + ServiceId::new(value.to_string()), + )); + } + } + } + return Err(APIGatewayServiceConnectionError::NotAService); + } + pub fn classify_message(message: &Message) -> APIGatewayClientState { + // Classify the message based on its content + // This is a placeholder implementation + if let Message::Text(text) = message { + let parsed: Result = serde_json::from_str(text); + info!("Parsed message: {:?}", parsed); + if let Ok(msg) = parsed { + match msg { + APIClientMessages::Register(registration) => { + return APIGatewayClientState::Registering(registration); + } + + APIClientMessages::ServiceCallSuccessResponse(succcess) => { + return APIGatewayClientState::Message( + succcess.request_id, + succcess.response, + ) + } + APIClientMessages::ServiceCallErrorResponse(error) => { + return APIGatewayClientState::ServiceCallFailed( + error.request_id, + error.error, + ); + } + e => { + info!("Classified message: {:?}", e); + return APIGatewayClientState::Failed(format!( + "Unknown message type: {:?}", + e + )); + } + } + } + } else { + if let Message::Close(_) = message { + return APIGatewayClientState::Closed; + } + } + APIGatewayClientState::Failed(format!("Failed to parse message: {}", message)) + } + fn jq_rule_to_string(jq_rule: Option) -> Option { + if let Some(rule) = jq_rule { + return Some(rule.rule); + } + None + } + async fn handle_registration( + service_id: ServiceId, + rule_engine: Arc>>, + registration: &APIGatewayServiceRegistrationRequest, + methods_2_services: Arc>, + ) { + let rules = ®istration.firebolt_handlers; + + let mut rule_engine = rule_engine.write().await; + + for handle_rule in rules { + let rule = Rule { + alias: handle_rule.firebolt_method.clone(), + transform: RuleTransform::default(), + filter: Self::jq_rule_to_string(handle_rule.jq_rule.clone()), + event_handler: None, + endpoint: Some("service".to_string()), + sources: None, + }; + /* + todo, save off existing rule for rollback (if it exists) + */ + rule_engine.add_rule(rule); + } + methods_2_services + .write() + .await + .add_service(service_id.clone(), rules.clone()); + } + async fn handle_unregister( + service_id: &ServiceId, + methods_2_services: Arc>, + rule_engine: Arc>>, + ) { + let mut rule_engine = rule_engine.write().await; + let aliases = methods_2_services + .read() + .await + .get_registrations(service_id); + for handle_rule in aliases { + rule_engine.remove_rule(&handle_rule.firebolt_method); + } + methods_2_services.write().await.remove_service(service_id); + } + + async fn handle_message( + message: Result, + tx: &mut SplitSink, Message>, + service_id: &ServiceId, + rule_engine: Arc>>, + methods_2_services: Arc>, + services_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + bridge_tx: mpsc::Sender, + ) { + match message { + Ok(msg) => { + info!("gateway server received websocket message: {:?}", msg); + match Self::classify_message(&msg) { + APIGatewayClientState::Registering(registration) => { + info!("Registering service: {:?}", registration); + Self::handle_unregister( + service_id, + methods_2_services.clone(), + rule_engine.clone(), + ) + .await; + + Self::handle_registration( + service_id.clone(), + rule_engine.clone(), + ®istration, + methods_2_services.clone(), + ) + .await; + + let response: APIGatewayServiceRegistrationResponse = registration.into(); + let response = APIClientMessages::Registered(response); + let _ = tx + .send(Message::Text(serde_json::to_string(&response).unwrap())) + .await; + info!("Sent registration response: {:?}", response) + } + APIGatewayClientState::Failed(e) => { + error!("Failed to classify message {} err {},{}", msg, E, e); + + let _ = tx.send(Message::Close(None)).await; + tx.close().await.unwrap(); + } + APIGatewayClientState::Closed => { + info!("Client closed connection"); + Self::handle_unregister(service_id, methods_2_services, rule_engine).await; + tx.close().await.unwrap(); + } + APIGatewayClientState::Message(request_id, msg) => { + info!( + "got msg from websocket: {} for request {:?}", + msg, request_id + ); + bridge_tx + .send(WebsocketServiceResponse::Success(request_id, msg)) + .await + .unwrap(); + } + APIGatewayClientState::ServiceCallFailed(id, error) => { + info!("Service call failed: {:?}", error); + let fail = WebsocketServiceResponse::Error(id, error); + let _ = bridge_tx.send(fail).await; + } + + _ => { + info!("handle_message: Unknown message type: {:?}", msg); + let _ = tx.send(Message::Close(None)).await; + tx.close().await.unwrap(); + } + } + } + Err(e) => { + /* + for now, just treat all errors as fatal and cleanup, drop tx and let client reconnect + */ + info!("Client closed connection. Error: {:?}", e); + info!("Unregistering service: {:?}", service_id); + + Self::handle_unregister(&service_id, methods_2_services, rule_engine.clone()).await; + services_2_rxes.write().await.remove(&service_id).unwrap(); + + tx.close().await.unwrap(); + } + } + } + /* + Spawn a task to handle exactly one service connection over websocket (for now, maybe dbus later) + */ + + async fn handle_service_connection( + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + rule_engine: Arc>>, + methods_2_services: Arc>, + mut websocket_service_request_rx: mpsc::Receiver, + service_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + ) -> Result<(), APIGatewayServiceConnectionError> { + info!("Handling service connection: {:?}", service_id); + + let (mut websocket_tx, mut websocket_rx) = ws_stream.split(); + + let (bridge_tx, mut bridge_rx) = mpsc::channel::(32); + + let requests_2_requestors: Arc< + RwLock< + HashMap< + ServiceRequestId, + Arc>>>, + >, + >, + > = Arc::new(RwLock::new(HashMap::new())); + + loop { + tokio::select! { + // Handle incoming messages from the WebSocket stream + Some(message) = websocket_rx.next() => { + info!("gateway Received websocket message: {:?}", message); + Self::handle_message( + message, + &mut websocket_tx, + &service_id, + rule_engine.clone(), + methods_2_services.clone(), + service_2_rxes.clone(), + bridge_tx.clone(), + ).await + } + // this is a request from the main api gateway thread that needs to be sent to the service + //via the websocket + Some(request) = websocket_service_request_rx.recv() => { + let request_id = request.request_id.clone(); + let sender_entry = Arc::new(Mutex::new(Some(request.respond_to))); + requests_2_requestors.write().await.insert(request_id.clone(), sender_entry.clone()); + + let service_call = APIClientMessages::ServiceCall( + ServiceCall { + method: request.method.clone(), + request_id: request_id, + payload: request.payload.clone(), + } + ); + let service_call = serde_json::to_string(&service_call).unwrap(); + websocket_tx.send(Message::Text(service_call)).await.unwrap(); + + } + Some(bridge_message) = bridge_rx.recv() => { + info!("Received message from bridge: {:?}", bridge_message); + + let id = bridge_message.get_id(); + + if let Some(requestor) = requests_2_requestors.write().await.remove(&id) { + let mut requestor_lock = requestor.lock().await; + if let Some(sender) = requestor_lock.take() { + let _ = sender.send(bridge_message.clone()); + } + } + } + else => { + info!("Service connection closed: {:?}", service_id); + // Handle service disconnection + // Clean up resources, etc. + Self::handle_unregister( + &service_id, + methods_2_services.clone(), + rule_engine.clone(), + ).await; + service_2_rxes + .write() + .await + .remove(&service_id) + .unwrap(); + break Ok(()); + } + } + } + } +} +use serde_json::Value; +use ssda_types::gateway::{ + APIGatewayServiceConnectionDisposition, APIGatewayServiceConnectionError, ApiGatewayServer, + ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingResponse, + ServiceRoutingSuccessResponse, +}; +use ssda_types::service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, APIGatewayServiceRegistrationResponse, + FireboltMethodHandlerAPIRegistration, ServiceCall, WebsocketServiceRequest, + WebsocketServiceResponse, +}; +use ssda_types::{JqRule, ServiceId, ServiceRequestId}; +use tokio::net::TcpStream; +use tokio::sync::{oneshot, Mutex}; +use tokio_tungstenite::tungstenite::{Error, Message}; +use tokio_tungstenite::WebSocketStream; +use url::form_urlencoded; + +pub struct WebsocketHandler { + pub service_id: ServiceId, +} +#[async_trait::async_trait] +impl ApiGatewayServer for ApiGateway { + async fn is_service_connect( + &self, + uri: Uri, + ) -> Result { + Self::is_apigateway_connection(&uri) + } + async fn service_connect( + &mut self, + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + ) -> Result { + info!("new Service connected: {:?}", service_id); + + let spawn_service_id = service_id.clone(); + let rule_engine_for_service = self.rules_engine.clone(); + /* + The broker_rx is a channel that receives service routing requests from the broker. It is the responsibility + of this (APIGateway) to handle the service routing requests and send them to the appropriate service. + Each service connection will have its own broker_rx channel, and the APIGateway will handle the routing + */ + let (websocket_handler_sender, websocket_handler_receiver) = + mpsc::channel::(32); + + /* + map sender for the websocket handler to the service id for later use + */ + { + let mut updater = self.services_2_rxs.write().await; + updater.insert(service_id.clone(), websocket_handler_sender); + } + let methods_2_services = self.methods_2_services.clone(); + let services_2_rxs = Arc::clone(&self.services_2_rxs); + tokio::spawn(async move { + let _ = Self::handle_service_connection( + spawn_service_id, + ws_stream, + rule_engine_for_service, + methods_2_services.clone(), + websocket_handler_receiver, + services_2_rxs.clone(), + ) + .await; + }); + + Ok(APIGatewayServiceConnectionDisposition::Accept(service_id)) + } + fn get_sender(&self) -> tokio::sync::mpsc::Sender { + self.broker_sender.clone() + } +} diff --git a/ssda/ssda_tranports/Cargo.toml b/ssda/ssda_tranports/Cargo.toml new file mode 100644 index 000000000..3457b87cc --- /dev/null +++ b/ssda/ssda_tranports/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ssda_tranports" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/ssda/ssda_tranports/src/main.rs b/ssda/ssda_tranports/src/main.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/ssda/ssda_tranports/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/ssda/ssda_types/Cargo.toml b/ssda/ssda_types/Cargo.toml new file mode 100644 index 000000000..f2a9a77fb --- /dev/null +++ b/ssda/ssda_types/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ssda_types" +version = "0.1.0" +edition = "2021" + +[dependencies] +jsonrpsee = { version = "=0.16.3", default-features = false } + +ripple_sdk = {path = "../../core/sdk"} + +async-trait = "0.1.88" +mockall = "0.13.1" +serde = "1.0.219" +serde_json = "1.0.140" +tokio = { version = "1", features = ["full"] } +tokio-tungstenite = "0.20.1" +futures-util = "0.3" +url = "2.5" +uuid = "1.16.0" + +http = "0.2.12" +tokio-websockets = { version = "0.11.4", features=["client","openssl","rand"]} +stream-tungstenite = "0.4.5" diff --git a/ssda/ssda_types/src/api_gateway_client.rs b/ssda/ssda_types/src/api_gateway_client.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/api_gateway_client.rs @@ -0,0 +1 @@ + diff --git a/ssda/ssda_types/src/api_gateway_server.rs b/ssda/ssda_types/src/api_gateway_server.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/api_gateway_server.rs @@ -0,0 +1 @@ + diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs new file mode 100644 index 000000000..eba802f80 --- /dev/null +++ b/ssda/ssda_types/src/lib.rs @@ -0,0 +1,771 @@ +use std::sync::Arc; + +use futures_util::{SinkExt, StreamExt}; +use gateway::ServiceRoutingRequest; +use ripple_sdk::api::rules_engine::{Rule, RuleTransform}; +use serde::{Deserialize, Serialize}; + +use service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, ServiceRegistration, + ServiceRequestHandler, +}; + +/* +Who what why +# API Gateway +The API gateway is a standalone binary component +that listens for Firebolt requests on a websocket. Upon receiving a firebolt +request, the gateway will look up a handler service (based on the method name) in it's +runtime (dynamically created) registry, and (assumign a service is registered to for the method), +will wrap the request with metadata, and dispatch the request to the handler service. Upon receiving +a response from the service, the API Gateway will translate the service response (using the rules engine) +into a Firebolt compatible (success or failure) result. + +# Services +Services are standalone processes (programs) that service requests from the API gateway. Services +inform the API gateway about which firebolt methods the Service supports, allowing the API gateway +to know which method(s) to route to which services. Workflow rules can run across multiple services, +with the API Gateway orchestrating the workflow, and performing any composition of outputs +Services must implement ServiceRequestHandler, which is ssthe interface that the APIGatewayClient uses +to interact with services (request processing, state changes, etc. + +# API Gateway Client + +The API Gateway Client is responsible for abstracting the interaction between the Service and the API Gateway, +inclding: Transport, connection management, authentication, and calling the Service via the the Service's +ServiceRequestHandler. This design is motivated by the need to free the Service from as much connection oriented +detail and let the developer focus on business logic. The API Gateway client is instanced as a crate that can be +consumed by a service at the highest possible level of abstraction (and ease of use) - it should only requuire a bit of +bootstrapping, and a ServiceRequestHandler instance/implementation, and then it should manage all the details of the +interactions between the Service and the API gateway with the Service being as blissfully ignorant of the details +as possible. +*/ +/* + +register: Service -> API Gateway Client -> API Gateway + +*/ + +pub mod api_gateway_client; +pub mod api_gateway_server; +pub mod service_api; + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct JqRule { + pub alias: String, + pub rule: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct StaticRule { + pub alias: String, + pub rule: String, +} +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct HandlerId { + pub handler_id: String, +} +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct ServiceHandler { + pub handler_id: HandlerId, + pub handler_type: Handler, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Handler { + None, + JqRule(JqRule), + StaticRule(StaticRule), +} +impl std::fmt::Display for Handler { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Handler::None => write!(f, "none"), + Handler::JqRule(jq_rule) => write!(f, "{}", jq_rule.alias), + Handler::StaticRule(static_rule) => write!(f, "{}", static_rule.alias), + } + } +} + +impl Default for Handler { + fn default() -> Self { + Handler::None + } +} +impl From for ripple_sdk::api::rules_engine::Rule { + fn from(handler: Handler) -> Self { + match handler { + Handler::None => Rule { + alias: "none".to_string(), + filter: None, + transform: RuleTransform::default(), + event_handler: None, + endpoint: None, + sources: None, + }, + Handler::JqRule(jq_rule) => Rule { + alias: jq_rule.alias, + filter: Some(jq_rule.rule), + ..Default::default() + }, + Handler::StaticRule(static_rule) => Rule { + alias: static_rule.alias, + filter: Some(static_rule.rule), + ..Default::default() + }, + } + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ServiceId { + pub service_id: String, +} +impl ServiceId { + pub fn new(service_id: String) -> Self { + ServiceId { service_id } + } +} + +impl PartialEq for ServiceId { + fn eq(&self, other: &Self) -> bool { + self.service_id == other.service_id + } +} + +impl Eq for ServiceId {} + +impl std::hash::Hash for ServiceId { + fn hash(&self, state: &mut H) { + self.service_id.hash(state); + } +} +impl std::fmt::Display for ServiceId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.service_id) + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ServiceRequestId { + pub request_id: u64, +} +impl PartialEq for ServiceRequestId { + fn eq(&self, other: &Self) -> bool { + self.request_id == other.request_id + } +} + +impl Eq for ServiceRequestId {} + +impl std::hash::Hash for ServiceRequestId { + fn hash(&self, state: &mut H) { + self.request_id.hash(state); + } +} +impl ServiceRequestId { + pub fn new(request_id: u64) -> Self { + ServiceRequestId { request_id } + } +} + +/* +gateway messages: from endpoint broker to api gateway and back. +*/ +pub mod gateway { + use crate::ServiceId; + use http::Uri; + use ripple_sdk::api::gateway::rpc_gateway_api::{ + JsonRpcApiError, JsonRpcApiResponse, RpcRequest, + }; + use serde::{Deserialize, Serialize}; + use serde_json::Value; + use tokio::sync::oneshot::Sender; + + use crate::ServiceRequestId; + + /* + ServiceRequest is the request that is sent from the API Gateway to the service + */ + #[derive(Debug)] + pub struct ServiceRoutingRequest { + pub request_id: ServiceRequestId, + pub payload: RpcRequest, + pub respond_to: Sender, + } + #[derive(Debug, Default, Clone, Serialize, Deserialize)] + pub struct ServiceRoutingSuccessResponse { + pub request_id: ServiceRequestId, + pub response: Value, + } + impl From for JsonRpcApiResponse { + fn from(response: ServiceRoutingResponse) -> Self { + match response { + ServiceRoutingResponse::Error(_error) => JsonRpcApiError::default().into(), + ServiceRoutingResponse::Success(success) => JsonRpcApiResponse { + id: Some(success.request_id.request_id), + jsonrpc: "2.0".to_string(), + result: Some(success.response), + error: None, + method: None, + params: None, + }, + } + } + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRoutingErrorResponse { + pub request_id: ServiceRequestId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum ServiceRoutingResponse { + Success(ServiceRoutingSuccessResponse), + Error(ServiceRoutingErrorResponse), + } + #[derive(Debug)] + pub enum APIGatewayServiceConnectionDisposition { + Accept(ServiceId), + Connected(ServiceId), + } + #[derive(Debug)] + pub enum APIGatewayServiceConnectionError { + ConnectionError, + NotAService, + } + + /* + This is the API gateway, and it meant to be hosted in the main ripple process + */ + + #[async_trait::async_trait] + pub trait ApiGatewayServer: Send + Sync { + async fn is_service_connect( + &self, + uri: Uri, + ) -> Result; + async fn service_connect( + &mut self, + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + ) -> Result; + fn get_sender(&self) -> tokio::sync::mpsc::Sender; + } +} +/* +service message: from api gateawy to services and back (over websockets) +*/ +pub mod service { + + use serde::{Deserialize, Serialize}; + + use crate::{ + gateway::{ + ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingResponse, + ServiceRoutingSuccessResponse, + }, + Handler, JqRule, ServiceId, ServiceRequestId, StaticRule, + }; + + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct FireboltMethodHandlerRegistration { + pub firebolt_method: Handler, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct FireboltMethodHandlerAPIRegistration { + pub firebolt_method: String, + pub jq_rule: Option, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct APIGatewayServiceRegistrationRequest { + pub firebolt_handlers: Vec, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct APIGatewayServiceRegistrationResponse { + pub firebolt_handlers: Vec, + } + impl From for APIGatewayServiceRegistrationResponse { + fn from( + request: APIGatewayServiceRegistrationRequest, + ) -> APIGatewayServiceRegistrationResponse { + APIGatewayServiceRegistrationResponse { + firebolt_handlers: request.firebolt_handlers, + } + } + } + + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRequest { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub payload: serde_json::Value, + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceErrorResponse { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub error: String, + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceSuccessResponse { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub payload: serde_json::Value, + } + + /* + send by api client to the api gateway over websocket + + */ + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct APIClientRegistration { + pub firebolt_handlers: Vec, + } + /* + Sent during callback registration in service + */ + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRegistration { + pub service_id: ServiceId, + pub firebolt_handlers: Vec, + } + + impl ServiceRegistration { + pub fn new( + service_id: ServiceId, + firebolt_handlers: Vec, + ) -> Self { + ServiceRegistration { + service_id: service_id, + firebolt_handlers: firebolt_handlers, + } + } + pub fn get_rule_registrations(&self) -> Vec { + self.firebolt_handlers.clone() + } + } + + pub struct ServiceRegistrationBuilder { + service_id: ServiceId, + firebolt_handlers: Vec, + } + impl ServiceRegistrationBuilder { + pub fn new(service_id: ServiceId) -> Self { + ServiceRegistrationBuilder { + service_id: service_id, + firebolt_handlers: Vec::new(), + } + } + pub fn add_handler(&mut self, firebolt_method: Handler) -> &mut Self { + self.firebolt_handlers.push(match firebolt_method { + Handler::None => todo!(), + Handler::JqRule(jq_rule) => FireboltMethodHandlerAPIRegistration { + firebolt_method: jq_rule.alias.clone(), + jq_rule: Some(jq_rule), + }, + Handler::StaticRule(static_rule) => FireboltMethodHandlerAPIRegistration { + firebolt_method: static_rule.alias.clone(), + jq_rule: Some(JqRule { + alias: static_rule.alias, + rule: static_rule.rule, + }), + }, + }); + self + } + pub fn build(&self) -> ServiceRegistration { + ServiceRegistration { + service_id: self.service_id.clone(), + firebolt_handlers: self.firebolt_handlers.clone(), + } + } + } + /* + ServiceCall is the request that is presented to a callback handler. + */ + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCall { + pub request_id: ServiceRequestId, + pub method: String, + pub payload: serde_json::Value, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCallSuccessResponse { + pub request_id: ServiceRequestId, + pub response: serde_json::Value, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCallErrorResponse { + pub request_id: ServiceRequestId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum ServiceCallResponse { + Success(ServiceCallSuccessResponse), + Error(ServiceCallErrorResponse), + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum APIClientMessages { + Register(APIGatewayServiceRegistrationRequest), + Registered(APIGatewayServiceRegistrationResponse), + Error(String), + Unregister(ServiceId), + ServiceCall(ServiceCall), + ServiceCallSuccessResponse(ServiceCallSuccessResponse), + ServiceCallErrorResponse(ServiceCallErrorResponse), + } + impl Default for APIClientMessages { + fn default() -> Self { + APIClientMessages::Register(APIGatewayServiceRegistrationRequest::default()) + } + } + + pub struct ServiceRegistrationResponse { + pub service_id: ServiceId, + } + pub struct ServiceRegistrationFailure { + pub service_id: ServiceId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum WebsocketServiceResponse { + Success(ServiceRequestId, serde_json::Value), + Error(ServiceRequestId, String), + } + impl WebsocketServiceResponse { + pub fn get_id(&self) -> ServiceRequestId { + match self { + WebsocketServiceResponse::Success(id, _) => id.clone(), + WebsocketServiceResponse::Error(id, _) => id.clone(), + } + } + } + #[derive(Debug)] + pub struct WebsocketServiceRequest { + pub request_id: ServiceRequestId, + pub method: String, + pub payload: serde_json::Value, + pub respond_to: tokio::sync::oneshot::Sender, + } + + /* + individiual services implement this trait to handle requests from the API gateway + This trait should faciliate fun testing of actual implementations + */ + + pub trait ServiceRequestHandler: Send + Sync { + /* + called by the client to allow the ServiceRequestHander return a Vec + to be used by the client to route requests. This is a blocking call, and will be called + after the client `on_connect`s + **/ + fn register(&self) -> Vec; + fn handle_request( + &self, + request: ServiceCall, + ) -> Result; + fn on_connected(&self) -> (); + fn on_disconnected(&self) -> (); + fn healthy(&self) -> bool; + } +} +pub mod client { + use mockall::automock; + + use crate::gateway::{ + ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingSuccessResponse, + }; + use crate::{HandlerId, ServiceId}; + + use crate::service::{ + FireboltMethodHandlerRegistration, ServiceCall, ServiceCallErrorResponse, + ServiceCallSuccessResponse, ServiceErrorResponse, ServiceRegistration, + ServiceRegistrationFailure, ServiceRegistrationResponse, ServiceRequest, + ServiceRequestHandler, ServiceSuccessResponse, + }; + + #[async_trait::async_trait] + /* + this is a trait that is implemented by a service client. + There will probably only be 2 of these for the foreseeable future: + 1) a real, websocket client + 2) a mock, for unit/integration testing + the point of this trait , and it's implementers, is to abstract the details related to auth, connection, etc. from the service (business logic) + that needs it. + + the methods in the actual interface are concerned with what to do during lifecycle transition events. the graph/steps/etc. of the lifecyle and + when to call these methods (and any state needed to call them) is the responsiblity of the concrete implementation. + */ + #[automock] + pub trait ServiceClientTrait: Send + Sync { + // this is a request to the service to register itself with the API gateway + fn register( + &self, + registraton: Box, + ) -> Result; + fn set_handler(&mut self, handler: Box) -> (); + fn unregister_service(&mut self, service_id: ServiceId) -> Result<(), String>; + fn register_handler( + &mut self, + handler: FireboltMethodHandlerRegistration, + ) -> Result<(), String>; + fn unregister_handler(&mut self, handler_id: HandlerId) -> Result<(), String>; + async fn invoke_handler( + &mut self, + request: ServiceRequest, + ) -> Result; + } + impl ServiceRequestHandler for T + where + T: Send + Sync + Clone + 'static + ServiceRequestHandlerImpl, + { + fn register(&self) -> Vec { + self.register() + } + + fn handle_request( + &self, + request: ServiceCall, + ) -> Result { + self.handle_request(request) + } + + fn on_connected(&self) { + self.on_connected() + } + + fn on_disconnected(&self) { + self.on_disconnected() + } + + fn healthy(&self) -> bool { + self.healthy() + } + } + + pub trait ServiceRequestHandlerImpl: Send + Sync + Clone { + fn register(&self) -> Vec; + fn handle_request( + &self, + request: ServiceCall, + ) -> Result; + fn on_connected(&self); + fn on_disconnected(&self); + fn healthy(&self) -> bool; + } +} +/* +This is the alternative API surface that services can use to communicate with the API gateway. +Firebolt calls are bidirectional, so the API gateway can send messages to the service, and the service can send messages to the API gateway. +*/ +mod api_surface { + use serde::{Deserialize, Serialize}; + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct FireboltRequest { + pub request_id: String, + pub payload: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct FireboltResponse { + pub request_id: String, + pub payload: String, + } +} + +/* +This trait represents the layer that will actually "talk" to the API gateway. it handles transports, etc. +This is a trait to : +1) Enable testing +2) Abstract the details of the transport from the service +3) Allow for different transports (websocket, http, etc.)z +*/ +#[async_trait::async_trait] +pub trait APIGatewayClient { + fn connect(&self) -> (); + fn disconnect(&self) -> (); + fn dispatch(&self, request: gateway::ServiceRoutingRequest) -> (); + async fn start(&self) -> (); + async fn stop(&self) -> (); +} +pub struct WebsocketAPIGatewayClient { + handler: Arc, + registration: ServiceRegistration, +} + +use tokio_tungstenite::{connect_async, tungstenite::Message}; + +impl WebsocketAPIGatewayClient { + pub fn new(handler: Arc, registration: ServiceRegistration) -> Self { + WebsocketAPIGatewayClient { + handler, + registration, + } + } + pub async fn handle_messages( + stream: tokio_tungstenite::WebSocketStream< + tokio_tungstenite::MaybeTlsStream, + >, + handler: Arc, + registration: ServiceRegistration, + ) { + let (mut tx, mut rx) = stream.split(); + + let registration_request = APIGatewayServiceRegistrationRequest { + firebolt_handlers: registration.get_rule_registrations(), + }; + + tx.send(Message::Text( + serde_json::to_string(&APIClientMessages::Register(registration_request.clone())) + .unwrap(), + )) + .await + .unwrap(); + + while let Some(message) = rx.next().await { + match message { + Ok(msg) => { + /* + attempt to marshal the message into a ServiceRequest + if it fails, log the error and continue + */ + println!("websocket: Received message via websocket: {:?}", msg); + let msg = msg.into_text().unwrap_or_default(); + if let Ok(request) = serde_json::from_str::(&msg) { + match request { + APIClientMessages::Register(registration_request) => { + println!( + "Received registration request: {:?}", + registration_request + ); + } + APIClientMessages::Registered(registration_request) => { + println!( + "Received registered response: {:?}", + registration_request + ); + handler.on_connected(); + } + APIClientMessages::Error(error) => { + println!("Received error: {:?}", error); + } + APIClientMessages::Unregister(service_id) => { + println!("Received unregister request: {:?}", service_id); + } + APIClientMessages::ServiceCall(service_call) => { + println!("Received service call: {:?}", service_call); + match handler.handle_request(service_call) { + Ok(response) => { + let response = + APIClientMessages::ServiceCallSuccessResponse(response); + // Send the response back to the client + + if let Err(e) = tx + .send(Message::Text( + serde_json::to_string(&response).unwrap(), + )) + .await + { + eprintln!("Error sending message: {:?}", e); + } + } + Err(e) => { + // Handle error response + eprintln!("Error handling request: {:?}", e); + let error_response = + APIClientMessages::ServiceCallErrorResponse(e); + if let Err(e) = tx + .send(Message::Text( + serde_json::to_string(&error_response).unwrap(), + )) + .await + { + eprintln!("Error sending message: {:?}", e); + } + } + } + } + _ => {} + } + } else { + println!(" I don't understand this message: {:?}", msg); + } + } + Err(err) => { + eprintln!("Error receiving message: {:?}", err); + // Handle the error (e.g., log it, retry, etc.) + // You might want to break the loop or handle reconnection logic here + // break; + } + } + } + } + pub async fn connect(&self) -> Result<(), Box> { + /* + todo: refactor to use the backoff crate + */ + + match connect_async("ws://localhost:3474/apigateway?serviceId=tester").await { + Ok(yay) => { + let handler = self.handler.clone(); + /* + register serviced fb methods + */ + let registration = self.registration.clone(); + Self::handle_messages(yay.0, handler, registration).await; + } + Err(lame) => { + eprintln!("Error connecting to WebSocket: {:?}", lame); + } + } + Ok(()) + } +} + +#[async_trait::async_trait] +impl APIGatewayClient for WebsocketAPIGatewayClient { + fn connect(&self) -> () { + // connect to the API gateway + } + fn disconnect(&self) -> () { + // disconnect from the API gateway + } + fn dispatch(&self, _request: ServiceRoutingRequest) -> () { + // send a request to the API gateway + } + + async fn start(&self) -> () { + println!("starting websocket client"); + self.connect().await.unwrap(); + self.handler.on_connected(); + } + + async fn stop(&self) -> () { + todo!() + } +} +pub struct DBUSAPIGatewayClient { + // dbus client +} +#[async_trait::async_trait] +impl APIGatewayClient for DBUSAPIGatewayClient { + fn connect(&self) -> () { + // connect to the API gateway + } + fn disconnect(&self) -> () { + // disconnect from the API gateway + } + fn dispatch(&self, _request: ServiceRoutingRequest) -> () { + // send a request to the API gateway + } + + async fn start(&self) -> () { + todo!() + } + + async fn stop(&self) -> () { + todo!() + } +} diff --git a/ssda/ssda_types/src/service_api.rs b/ssda/ssda_types/src/service_api.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/service_api.rs @@ -0,0 +1 @@ + From 515eb5accc4145426ca3c613a45014c1659af3ba Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 07:00:39 -0700 Subject: [PATCH 11/46] chore: refactor based on feedback --- core/sdk/src/api/rules_engine/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index c4d415df6..dcf59d0ae 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -356,7 +356,10 @@ impl RuleEngine { } } - pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { + pub fn retrieve_rule( + &self, + rpc_request: &RpcRequest, + ) -> Result { let method = rpc_request.method.to_lowercase(); /* match directly from method name @@ -374,7 +377,7 @@ impl RuleEngine { } } - pub fn get_rule_by_method(&self, method: &str) -> Option { + pub fn retrieve_rule_by_method(&self, method: &str) -> Option { self.rules.rules.get(&method.to_lowercase()).cloned() } } @@ -553,10 +556,10 @@ impl RuleEngineProvider for RuleEngine { } } fn get_rule(&self, rpc_request: &RpcRequest) -> Result { - self.get_rule(rpc_request) + self.retrieve_rule(rpc_request) } fn get_rule_by_method(&self, method: &str) -> Option { - self.get_rule_by_method(method) + self.retrieve_rule_by_method(method) } fn get_rules(&self) -> RuleSet { self.rules.clone() From f622173ad13ca596bf527f78cd34532b78e4b913 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 09:46:54 -0700 Subject: [PATCH 12/46] chores: fix tests, satisfy clippy --- .../bootstrap/start_communication_broker.rs | 4 +- core/main/src/broker/endpoint_broker.rs | 247 ++++++++++-------- core/main/src/broker/extn_broker.rs | 15 +- core/main/src/broker/http_broker.rs | 10 +- core/main/src/broker/service_broker.rs | 29 +- .../broker/test/mock_thunder_lite_server.rs | 11 +- core/main/src/broker/thunder_broker.rs | 9 +- core/main/src/broker/websocket_broker.rs | 16 +- core/main/src/broker/workflow_broker.rs | 12 +- core/main/src/state/bootstrap_state.rs | 2 +- core/main/src/state/platform_state.rs | 14 +- core/sdk/src/api/rules_engine/mod.rs | 7 +- ssda/ssda_service/src/lib.rs | 40 ++- ssda/ssda_types/src/lib.rs | 62 ++--- 14 files changed, 253 insertions(+), 225 deletions(-) diff --git a/core/main/src/bootstrap/start_communication_broker.rs b/core/main/src/bootstrap/start_communication_broker.rs index cc7962bda..024485334 100644 --- a/core/main/src/bootstrap/start_communication_broker.rs +++ b/core/main/src/bootstrap/start_communication_broker.rs @@ -67,7 +67,9 @@ impl Bootstep for StartOtherBrokers { } // Setup the endpoints from the manifests let mut endpoint_state = ps.clone().endpoint_state; - endpoint_state.build_other_endpoints(ps.clone(), ps.session_state.get_account_session()); + endpoint_state + .build_other_endpoints(ps.clone(), ps.session_state.get_account_session()) + .await; Ok(()) } } diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 4982d3dc0..8f8e7a375 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -490,7 +490,7 @@ impl EndpointBrokerState { callback: BrokerCallback { sender: tx }, request_map: Arc::new(RwLock::new(HashMap::new())), extension_request_map: Arc::new(RwLock::new(HashMap::new())), - rule_engine: rule_engine, + rule_engine, cleaner_list: Arc::new(RwLock::new(Vec::new())), reconnect_tx, provider_broker_state: ProvideBrokerState::default(), @@ -508,13 +508,13 @@ impl EndpointBrokerState { self.rule_engine = rule_engine; self } - // pub fn add_rule(mut self, rule: Rule) -> Self { - // self.rule_engine.add_rule(rule); - // self - // } + pub async fn add_rule(self, rule: Rule) -> Self { + let rule_engine = self.rule_engine.clone(); + rule_engine.write().await.add_rule(rule); + self + } pub async fn has_rule(&self, rule: &str) -> bool { self.rule_engine.read().await.has_rule(rule) - //self.rule_engine.lock().has_rule(rule) } #[cfg(not(test))] fn reconnect_thread(&self, mut rx: Receiver, client: RippleClient) { @@ -1841,8 +1841,12 @@ fn apply_filter(broker_request: &BrokerRequest, result: &Value, rpc_request: &Rp #[cfg(test)] mod endpoint_broker_tests { use super::*; - use crate::broker::rules_engine::RuleTransform; - use ripple_sdk::{tokio::sync::mpsc::channel, Mockable}; + + use ripple_sdk::{ + api::rules_engine::{Rule, RuleTransform}, + tokio::sync::mpsc::channel, + Mockable, + }; #[tokio::test] async fn test_send_error() { @@ -1900,10 +1904,12 @@ mod endpoint_broker_tests { } mod endpoint_broker_state { - use ripple_sdk::{tokio, tokio::sync::mpsc::channel}; + use ripple_sdk::{ + api::rules_engine::{RuleEndpoint, RuleEndpointProtocol, RuleEngine, RuleSet}, + tokio::{self, sync::mpsc::channel}, + }; use crate::{ - broker::rules_engine::{RuleEngine, RuleSet}, service::extn::ripple_client::RippleClient, state::{bootstrap_state::ChannelsState, ops_metrics_state::OpMetricState}, }; @@ -1911,8 +1917,7 @@ mod endpoint_broker_tests { use super::EndpointBrokerState; use crate::broker::endpoint_broker::BrokerConnectRequest; use crate::broker::endpoint_broker::ATOMIC_ID; - use crate::broker::rules_engine::RuleEndpoint; - use crate::broker::rules_engine::RuleEndpointProtocol; + use ripple_sdk::api::session::AccountSession; use std::sync::atomic::Ordering; @@ -2042,9 +2047,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2072,9 +2077,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2102,9 +2107,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2132,9 +2137,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2162,9 +2167,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2192,9 +2197,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2222,9 +2227,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2254,9 +2259,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); @@ -2495,17 +2500,18 @@ mod endpoint_broker_tests { use crate::broker::endpoint_broker::BrokerConnectRequest; use crate::broker::endpoint_broker::BrokerOutput; use crate::broker::endpoint_broker::EndpointBrokerState; - use crate::broker::rules_engine::RuleEndpoint; - use crate::broker::rules_engine::RuleEndpointProtocol; - use crate::broker::rules_engine::RuleEngine; - use crate::broker::rules_engine::RuleSet; - use crate::broker::rules_engine::{Rule, RuleTransform}; use crate::service::extn::ripple_client::RippleClient; use crate::state::bootstrap_state::ChannelsState; use crate::state::ops_metrics_state::OpMetricState; use ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiResponse; use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; + use ripple_sdk::api::rules_engine::Rule; + use ripple_sdk::api::rules_engine::RuleEndpoint; + use ripple_sdk::api::rules_engine::RuleEndpointProtocol; + use ripple_sdk::api::rules_engine::RuleEngine; + use ripple_sdk::api::rules_engine::RuleSet; + use ripple_sdk::api::rules_engine::RuleTransform; use ripple_sdk::tokio; use ripple_sdk::tokio::sync::mpsc::channel; use ripple_sdk::Mockable; @@ -2522,9 +2528,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); let endpoint = RuleEndpoint { @@ -2567,9 +2573,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); let endpoint = RuleEndpoint { @@ -2614,9 +2620,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); let endpoint = RuleEndpoint { @@ -2660,9 +2666,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); let endpoint = RuleEndpoint { @@ -2705,9 +2711,9 @@ mod endpoint_broker_tests { let mut state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); let endpoint = RuleEndpoint { @@ -2745,15 +2751,17 @@ mod endpoint_broker_tests { mod provided_request { use crate::{ - broker::{ - endpoint_broker::{EndpointBrokerState, RenderedRequest}, - rules_engine::{Rule, RuleEngine, RuleSet}, - }, + broker::endpoint_broker::{EndpointBrokerState, RenderedRequest}, service::extn::ripple_client::RippleClient, state::{bootstrap_state::ChannelsState, ops_metrics_state::OpMetricState}, }; use ripple_sdk::{ - api::gateway::rpc_gateway_api::RpcRequest, tokio::sync::mpsc::channel, Mockable, + api::{ + gateway::rpc_gateway_api::RpcRequest, + rules_engine::{Rule, RuleEngine, RuleSet}, + }, + tokio::sync::mpsc::channel, + Mockable, }; #[test] fn test_basic() { @@ -2773,7 +2781,12 @@ mod endpoint_broker_tests { }; engine.add_rule(r); - let under_test = EndpointBrokerState::new(OpMetricState::default(), tx, engine, client); + let under_test = EndpointBrokerState::new( + OpMetricState::default(), + tx, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(engine))), + client, + ); let f = under_test.handle_provided_request( &RpcRequest::mock(), @@ -2798,9 +2811,9 @@ mod endpoint_broker_tests { let mut endpoint_broker = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(RuleEngine { rules: RuleSet::default(), - }, + }))), client, ); for endpoint in endpoints { @@ -2811,17 +2824,17 @@ mod endpoint_broker_tests { endpoint_broker } use crate::{ - broker::{ - endpoint_broker::{ - BrokerRequest, BrokerSender, EndpointBrokerState, HandleBrokerageError, - }, - rules_engine::{Rule, RuleEngine, RuleSet}, + broker::endpoint_broker::{ + BrokerRequest, BrokerSender, EndpointBrokerState, HandleBrokerageError, }, service::extn::ripple_client::RippleClient, state::{bootstrap_state::ChannelsState, ops_metrics_state::OpMetricState}, }; use ripple_sdk::{ - api::gateway::rpc_gateway_api::RpcRequest, + api::{ + gateway::rpc_gateway_api::RpcRequest, + rules_engine::{Rule, RuleEngine, RuleSet}, + }, extn::extn_client_message::ExtnMessage, tokio::{ self, @@ -2838,7 +2851,8 @@ mod endpoint_broker_tests { .with_alias("static".to_string()) .with_endpoint("thunder".to_string()) .to_owned(), - ); + ) + .await; let broker_request = BrokerRequest::default(); assert!( under_test @@ -2859,11 +2873,13 @@ mod endpoint_broker_tests { #[tokio::test] async fn test_dispatch_brokerage_provided_rule() { let (bs, _) = channel(2); - let mut under_test = endpoint_broker_state_under_test(vec![]).add_rule( - Rule::default() - .with_alias("provided".to_string()) - .to_owned(), - ); + let mut under_test = endpoint_broker_state_under_test(vec![]) + .add_rule( + Rule::default() + .with_alias("provided".to_string()) + .to_owned(), + ) + .await; let under_test = under_test.add_endpoint("thunder".to_string(), BrokerSender { sender: bs }); let broker_request = BrokerRequest::default(); @@ -2912,8 +2928,12 @@ mod endpoint_broker_tests { sources: None, }; engine.add_rule(rule); - let mut under_test = - EndpointBrokerState::new(OpMetricState::default(), tx, engine, client); + let mut under_test = EndpointBrokerState::new( + OpMetricState::default(), + tx, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(engine))), + client, + ); let (tx, _) = mpsc::channel::(10); under_test.add_endpoint("thunder".to_string(), BrokerSender { sender: tx }); @@ -2921,8 +2941,9 @@ mod endpoint_broker_tests { let mut request = RpcRequest::mock(); request.method = "endpoint".to_string(); - let result = - under_test.handle_brokerage_workflow(request, None, None, vec![], None, vec![]); + let result = under_test + .handle_brokerage_workflow(request, None, None, vec![], None, vec![]) + .await; assert!(result.is_ok(), "Expected Ok but got: {:?}", result); } @@ -2933,13 +2954,19 @@ mod endpoint_broker_tests { let engine = RuleEngine { rules: RuleSet::default(), }; - let under_test = EndpointBrokerState::new(OpMetricState::default(), tx, engine, client); + let under_test = EndpointBrokerState::new( + OpMetricState::default(), + tx, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(engine))), + client, + ); let mut request = RpcRequest::mock(); request.method = "nonexistent".to_string(); - let result = - under_test.handle_brokerage_workflow(request, None, None, vec![], None, vec![]); + let result = under_test + .handle_brokerage_workflow(request, None, None, vec![], None, vec![]) + .await; assert!( matches!(result, Err(HandleBrokerageError::RuleNotFound(_))), "Expected RuleNotFound error but got: {:?}", @@ -2963,13 +2990,19 @@ mod endpoint_broker_tests { sources: None, }; engine.add_rule(rule); - let under_test = EndpointBrokerState::new(OpMetricState::default(), tx, engine, client); + let under_test = EndpointBrokerState::new( + OpMetricState::default(), + tx, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new(engine))), + client, + ); let mut request = RpcRequest::mock(); request.method = "endpoint".to_string(); - let result = - under_test.handle_brokerage_workflow(request, None, None, vec![], None, vec![]); + let result = under_test + .handle_brokerage_workflow(request, None, None, vec![], None, vec![]) + .await; assert!( matches!(result, Err(HandleBrokerageError::BrokerNotFound(_))), "Expected BrokerNotFound error but got: {:?}", @@ -2978,14 +3011,13 @@ mod endpoint_broker_tests { } #[cfg(test)] mod update_request { - use ripple_sdk::{api::gateway::rpc_gateway_api::RpcRequest, tokio}; + use ripple_sdk::{ + api::{gateway::rpc_gateway_api::RpcRequest, rules_engine::RuleTransform}, + tokio, + }; use crate::{ - broker::{ - endpoint_broker::BrokerCallback, - rules_engine::{Rule, RuleSet, RuleTransform}, - }, - state::ops_metrics_state::OpMetricState, + broker::endpoint_broker::BrokerCallback, state::ops_metrics_state::OpMetricState, }; use super::*; @@ -2998,9 +3030,11 @@ mod endpoint_broker_tests { let state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { - rules: RuleSet::default(), - }, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new( + RuleEngine { + rules: RuleSet::default(), + }, + ))), client, ); @@ -3026,9 +3060,11 @@ mod endpoint_broker_tests { let state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { - rules: RuleSet::default(), - }, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new( + RuleEngine { + rules: RuleSet::default(), + }, + ))), client, ); @@ -3056,9 +3092,11 @@ mod endpoint_broker_tests { let state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { - rules: RuleSet::default(), - }, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new( + RuleEngine { + rules: RuleSet::default(), + }, + ))), client, ); @@ -3092,9 +3130,11 @@ mod endpoint_broker_tests { let state = EndpointBrokerState::new( OpMetricState::default(), tx, - RuleEngine { - rules: RuleSet::default(), - }, + std::sync::Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new( + RuleEngine { + rules: RuleSet::default(), + }, + ))), client, ); @@ -3149,29 +3189,4 @@ mod endpoint_broker_tests { assert!(cleaner.cleanup_session("test_app").await.is_err()); } } - #[cfg(test)] - mod workflow { - // fn test_workflow() { - // let (tx, _) = channel(2); - // let client = RippleClient::new(ChannelsState::new()); - // let mut state = EndpointBrokerState::new( - // MetricsState::default(), - // tx, - // RuleEngine { - // rules: RuleSet::default(), - // }, - // client, - // ); - // let endpoint = RuleEndpoint { - // protocol: RuleEndpointProtocol::Http, - // ..Default::default() - // }; - // let request = BrokerConnectRequest::new( - // "http_endpoint".to_string(), - // endpoint.clone(), - // state.reconnect_tx.clone(), - // ); - // state.build_endpoint(None, request); - // } - } } diff --git a/core/main/src/broker/extn_broker.rs b/core/main/src/broker/extn_broker.rs index 4a9b74ba1..9137d8fab 100644 --- a/core/main/src/broker/extn_broker.rs +++ b/core/main/src/broker/extn_broker.rs @@ -171,15 +171,19 @@ impl EndpointBroker for ExtnBroker { #[cfg(test)] mod tests { + use std::sync::Arc; + use super::*; use crate::broker::endpoint_broker::BrokerOutput; - use crate::broker::rules_engine::Rule; + use crate::service::extn::ripple_client::RippleClient; use crate::state::bootstrap_state::ChannelsState; use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; use ripple_sdk::api::manifest::device_manifest::DeviceManifest; use ripple_sdk::api::manifest::extn_manifest::ExtnManifest; + use ripple_sdk::api::rules_engine::{Rule, RuleEngine, RuleEngineProvider}; use ripple_sdk::Mockable; + use ssda_types::gateway::ApiGatewayServer; #[tokio::test] pub async fn test_log_error_and_send_broker_failure_response() { @@ -286,6 +290,13 @@ mod tests { workflow_callback: Some(callback.clone()), telemetry_response_listeners: vec![], }; + let rules_engine: Arc>> = + Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::default()))); + + let api_gateway_state: Arc>> = + Arc::new(tokio::sync::Mutex::new(Box::new( + ssda_service::ApiGateway::new(rules_engine.clone()), + ))); let platform_state = PlatformState::new( ExtnManifest::default(), @@ -293,6 +304,8 @@ mod tests { RippleClient::new(ChannelsState::default()), Vec::new(), None, + api_gateway_state.clone(), + rules_engine.clone(), ); let sender = ExtnBroker::start( Some(platform_state), diff --git a/core/main/src/broker/http_broker.rs b/core/main/src/broker/http_broker.rs index 72a03ec9f..6d396bec7 100644 --- a/core/main/src/broker/http_broker.rs +++ b/core/main/src/broker/http_broker.rs @@ -201,15 +201,15 @@ mod tests { use serde_json::{json, Value}; use std::time::Duration; - use crate::broker::{ - endpoint_broker::BrokerOutput, - rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol}, - }; + use crate::broker::endpoint_broker::BrokerOutput; use super::*; use ripple_sdk::{ - api::gateway::rpc_gateway_api::{JsonRpcApiResponse, RpcRequest}, + api::{ + gateway::rpc_gateway_api::{JsonRpcApiResponse, RpcRequest}, + rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol}, + }, tokio::{runtime::Runtime, task::JoinHandle, time::timeout}, Mockable, }; diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index af4ba345b..2eea7bf1a 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -6,21 +6,14 @@ use ripple_sdk::{ use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; use ssda_types::ServiceRequestId; -use crate::state::platform_state::PlatformState; - use super::endpoint_broker::{ - BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerOutputForwarder, BrokerRequest, - BrokerSender, EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, + BrokerCallback, BrokerCleaner, BrokerOutputForwarder, BrokerRequest, BrokerSender, + EndpointBroker, BROKER_CHANNEL_BUFFER_SIZE, }; use ripple_sdk::tokio; pub struct ServiceBroker { - platform_state: Option, - connect_request: BrokerConnectRequest, - broker_callback: BrokerCallback, - endpoint_broker_state: EndpointBrokerState, broker_sender: BrokerSender, - cleaner: BrokerCleaner, } async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest, body: &[u8]) { match BrokerOutputForwarder::handle_non_jsonrpc_response( @@ -30,7 +23,7 @@ async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest ) { Ok(_) => {} Err(e) => { - error!("Error message from http broker {:?}", e) + error!("Error message from service broker {:?}", e) } } } @@ -39,9 +32,9 @@ impl ServiceBroker {} impl EndpointBroker for ServiceBroker { fn get_broker( ps: Option, - connect_request: super::endpoint_broker::BrokerConnectRequest, + _connect_request: super::endpoint_broker::BrokerConnectRequest, broker_callback: super::endpoint_broker::BrokerCallback, - endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, + _endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, ) -> Self { //todo!(); // let endpoint = request.endpoint.clone(); @@ -107,12 +100,12 @@ impl EndpointBroker for ServiceBroker { }; Self { - platform_state: ps.clone(), - connect_request: connect_request, - broker_callback: broker_callback, - endpoint_broker_state: endpoint_broker.clone(), - broker_sender: broker_sender, - cleaner: BrokerCleaner { cleaner: None }, + // platform_state: ps.clone(), + // connect_request, + // broker_callback, + // endpoint_broker_state: endpoint_broker.clone(), + broker_sender, + //cleaner: BrokerCleaner { cleaner: None }, } } diff --git a/core/main/src/broker/test/mock_thunder_lite_server.rs b/core/main/src/broker/test/mock_thunder_lite_server.rs index 070750d35..7ab3899e3 100644 --- a/core/main/src/broker/test/mock_thunder_lite_server.rs +++ b/core/main/src/broker/test/mock_thunder_lite_server.rs @@ -372,7 +372,7 @@ macro_rules! process_broker_output { .clone() .rule .transform - .get_transform_data(rules_engine::RuleTransformType::Response) + .get_transform_data(ripple_sdk::api::rules_engine::RuleTransformType::Response) { apply_response(filter, &rule_context_name, &mut response); } else if response.result.is_none() && response.error.is_none() { @@ -394,12 +394,9 @@ macro_rules! process_broker_output_event_resposne { // Apply the jq transform to the response - if let Some(filter) = $broker_request - .clone() - .rule - .transform - .get_transform_data(rules_engine::RuleTransformType::Event(false)) - { + if let Some(filter) = $broker_request.clone().rule.transform.get_transform_data( + ripple_sdk::api::rules_engine::RuleTransformType::Event(false), + ) { let broker_request_clone = $broker_request.clone(); let result = response.clone().result.unwrap(); let rpc = $broker_request.rpc.clone(); diff --git a/core/main/src/broker/thunder_broker.rs b/core/main/src/broker/thunder_broker.rs index bcb0dcf03..0c8df2348 100644 --- a/core/main/src/broker/thunder_broker.rs +++ b/core/main/src/broker/thunder_broker.rs @@ -686,7 +686,6 @@ mod tests { apply_response, apply_rule_for_event, BrokerCallback, BrokerConnectRequest, BrokerOutput, BrokerRequest, EndpointBroker, }, - rules_engine::{self, Rule, RuleEndpoint, RuleEndpointProtocol, RuleTransform}, test::mock_thunder_lite_server::MockThunderLiteServer, }, create_and_send_broker_request, create_and_send_broker_request_with_jq_transform, @@ -695,7 +694,11 @@ mod tests { utils::test_utils::{MockWebsocket, WSMockData}, }; use ripple_sdk::{ - api::gateway::rpc_gateway_api::{ApiProtocol, CallContext, RpcRequest}, + api::rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol}, + api::{ + gateway::rpc_gateway_api::{ApiProtocol, CallContext, RpcRequest}, + rules_engine::RuleTransform, + }, uuid::Uuid, }; use serde_json::json; @@ -791,7 +794,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let (tx, _) = mpsc::channel(1); diff --git a/core/main/src/broker/websocket_broker.rs b/core/main/src/broker/websocket_broker.rs index 6cd00de71..a741bbdae 100644 --- a/core/main/src/broker/websocket_broker.rs +++ b/core/main/src/broker/websocket_broker.rs @@ -229,13 +229,13 @@ mod tests { use std::time::Duration; use crate::{ - broker::{ - endpoint_broker::{BrokerOutput, BrokerRequest}, - rules_engine::{Rule, RuleEndpoint, RuleTransform}, - }, + broker::endpoint_broker::{BrokerOutput, BrokerRequest}, utils::test_utils::{MockWebsocket, WSMockData}, }; - use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; + use ripple_sdk::api::{ + gateway::rpc_gateway_api::RpcRequest, + rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol, RuleTransform}, + }; use serde_json::json; use super::*; @@ -251,7 +251,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let (tx, _) = mpsc::channel(1); @@ -380,7 +380,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; @@ -479,7 +479,7 @@ mod tests { let port: u32 = 34743; let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let sender = WSNotificationBroker::start(request, callback, endpoint.get_url().clone()); diff --git a/core/main/src/broker/workflow_broker.rs b/core/main/src/broker/workflow_broker.rs index 9c45723c7..5b28d5988 100644 --- a/core/main/src/broker/workflow_broker.rs +++ b/core/main/src/broker/workflow_broker.rs @@ -312,7 +312,7 @@ pub mod tests { use ripple_sdk::{ api::{ gateway::rpc_gateway_api::RpcRequest, - rules_engine::{JsonDataSource, Rule, RuleEngine}, + rules_engine::{JsonDataSource, Rule, RuleEngine, RuleEngineProvider}, }, tokio, Mockable, }; @@ -371,7 +371,15 @@ pub mod tests { engine.unwrap() } pub fn endppoint_broker_state() -> EndpointBrokerState { - EndpointBrokerState::default().with_rules_engine(rule_engine()) + use ripple_sdk::tokio::sync::RwLock as TokioRwLock; + use std::sync::Arc; + + let rule_engine = rule_engine(); + let boxed: Box = Box::new(rule_engine); + let rw_locked = TokioRwLock::new(boxed); + let arc = Arc::new(rw_locked); + + EndpointBrokerState::default().with_rules_engine(arc) } #[tokio::test] diff --git a/core/main/src/state/bootstrap_state.rs b/core/main/src/state/bootstrap_state.rs index 0814b39c3..359be6e45 100644 --- a/core/main/src/state/bootstrap_state.rs +++ b/core/main/src/state/bootstrap_state.rs @@ -135,7 +135,7 @@ impl BootstrapState { Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( &extn_manifest, )))); - tokio::spawn(async move {}); + let api_gateway_state: Arc>> = Arc::new(tokio::sync::Mutex::new(Box::new( ssda_service::ApiGateway::new(rules_engine.clone()), diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index 3588d1aa3..df3229df4 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -261,7 +261,7 @@ impl PlatformState { #[cfg(test)] mod tests { use super::*; - use ripple_sdk::api::manifest::extn_manifest::default_providers; + use ripple_sdk::api::{manifest::extn_manifest::default_providers, rules_engine::RuleEngine}; use ripple_tdk::utils::test_utils::Mockable; impl Mockable for PlatformState { @@ -279,12 +279,24 @@ mod tests { ) .unwrap(); extn_manifest.provider_registrations = default_providers(); + let rules_engine: Arc>> = + Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( + &extn_manifest, + )))); + + let api_gateway_state: Arc< + tokio::sync::Mutex>, + > = Arc::new(tokio::sync::Mutex::new(Box::new( + ssda_service::ApiGateway::new(rules_engine.clone()), + ))); Self::new( extn_manifest, manifest, RippleClient::new(ChannelsState::new()), vec![], None, + api_gateway_state.clone(), + rules_engine.clone(), ) } } diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index dcf59d0ae..49992286a 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -427,7 +427,7 @@ pub enum RuleRetrievalError { /// ``` /// use serde_json::json; /// use ripple_sdk::utils::error::RippleError; -/// use crate::jq_compile; +/// use ripple_sdk::api::rules_engine::jq_compile; /// /// let filter = "if .success then .stbVersion else { code: -32100, message: \"couldn't get version\" } end"; /// let input = json!({ @@ -568,8 +568,10 @@ impl RuleEngineProvider for RuleEngine { #[cfg(test)] mod tests { + use crate::api::gateway::rpc_gateway_api::CallContext; + use super::*; - use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; + use ripple_sdk::serde_json::json; #[test] @@ -673,7 +675,6 @@ mod tests { .unwrap() .contains("nested")); } - use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; #[test] fn test_get_rule_exact_match() { diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs index 4cd823963..012f228fb 100644 --- a/ssda/ssda_service/src/lib.rs +++ b/ssda/ssda_service/src/lib.rs @@ -73,7 +73,11 @@ pub enum APIGatewayClientState { Message(ServiceRequestId, Value), ServiceCallFailed(ServiceRequestId, String), } -//static service_map:HashMap = HashMap::; +type RequestIds2SendersType = Arc< + RwLock< + HashMap>>>>, + >, +>; impl ApiGateway { pub fn new( @@ -85,11 +89,11 @@ impl ApiGateway { let me = Self { service_endpoints: Arc::new(tokio::sync::RwLock::new(HashMap::new())), - rules_engine: rules_engine, + rules_engine, methods_2_services: Arc::new(tokio::sync::RwLock::new(ServiceMap::new())), broker_sender: tx.clone(), services_2_rxs: services_2_rxs.clone(), - reply_to_tx: reply_to_tx, + reply_to_tx, }; me.start(rx, Arc::clone(&services_2_rxs)); @@ -137,7 +141,7 @@ impl ApiGateway { let _ = request.respond_to.send( ServiceRoutingResponse::Success( ServiceRoutingSuccessResponse { - request_id: request_id, + request_id, response: result, }, ), @@ -149,8 +153,8 @@ impl ApiGateway { let _ = request.respond_to.send( ServiceRoutingResponse::Error( ServiceRoutingErrorResponse { - request_id: request_id, - error: error, + request_id, + error, }, ), ); @@ -197,7 +201,7 @@ impl ApiGateway { } } } - return Err(APIGatewayServiceConnectionError::NotAService); + Err(APIGatewayServiceConnectionError::NotAService) } pub fn classify_message(message: &Message) -> APIGatewayClientState { // Classify the message based on its content @@ -232,11 +236,10 @@ impl ApiGateway { } } } - } else { - if let Message::Close(_) = message { - return APIGatewayClientState::Closed; - } + } else if let Message::Close(_) = message { + return APIGatewayClientState::Closed; } + APIGatewayClientState::Failed(format!("Failed to parse message: {}", message)) } fn jq_rule_to_string(jq_rule: Option) -> Option { @@ -370,8 +373,8 @@ impl ApiGateway { info!("Client closed connection. Error: {:?}", e); info!("Unregistering service: {:?}", service_id); - Self::handle_unregister(&service_id, methods_2_services, rule_engine.clone()).await; - services_2_rxes.write().await.remove(&service_id).unwrap(); + Self::handle_unregister(service_id, methods_2_services, rule_engine.clone()).await; + services_2_rxes.write().await.remove(service_id).unwrap(); tx.close().await.unwrap(); } @@ -397,14 +400,7 @@ impl ApiGateway { let (bridge_tx, mut bridge_rx) = mpsc::channel::(32); - let requests_2_requestors: Arc< - RwLock< - HashMap< - ServiceRequestId, - Arc>>>, - >, - >, - > = Arc::new(RwLock::new(HashMap::new())); + let requests_2_requestors: RequestIds2SendersType = Arc::new(RwLock::new(HashMap::new())); loop { tokio::select! { @@ -431,7 +427,7 @@ impl ApiGateway { let service_call = APIClientMessages::ServiceCall( ServiceCall { method: request.method.clone(), - request_id: request_id, + request_id, payload: request.payload.clone(), } ); diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index eba802f80..a3f639a73 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -74,8 +74,9 @@ pub struct ServiceHandler { pub handler_type: Handler, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub enum Handler { + #[default] None, JqRule(JqRule), StaticRule(StaticRule), @@ -90,11 +91,6 @@ impl std::fmt::Display for Handler { } } -impl Default for Handler { - fn default() -> Self { - Handler::None - } -} impl From for ripple_sdk::api::rules_engine::Rule { fn from(handler: Handler) -> Self { match handler { @@ -262,13 +258,7 @@ pub mod service { use serde::{Deserialize, Serialize}; - use crate::{ - gateway::{ - ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingResponse, - ServiceRoutingSuccessResponse, - }, - Handler, JqRule, ServiceId, ServiceRequestId, StaticRule, - }; + use crate::{Handler, JqRule, ServiceId, ServiceRequestId}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct FireboltMethodHandlerRegistration { @@ -339,8 +329,8 @@ pub mod service { firebolt_handlers: Vec, ) -> Self { ServiceRegistration { - service_id: service_id, - firebolt_handlers: firebolt_handlers, + service_id, + firebolt_handlers, } } pub fn get_rule_registrations(&self) -> Vec { @@ -355,7 +345,7 @@ pub mod service { impl ServiceRegistrationBuilder { pub fn new(service_id: ServiceId) -> Self { ServiceRegistrationBuilder { - service_id: service_id, + service_id, firebolt_handlers: Vec::new(), } } @@ -467,17 +457,14 @@ pub mod service { &self, request: ServiceCall, ) -> Result; - fn on_connected(&self) -> (); - fn on_disconnected(&self) -> (); + fn on_connected(&self); + fn on_disconnected(&self); fn healthy(&self) -> bool; } } pub mod client { use mockall::automock; - use crate::gateway::{ - ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingSuccessResponse, - }; use crate::{HandlerId, ServiceId}; use crate::service::{ @@ -506,7 +493,7 @@ pub mod client { &self, registraton: Box, ) -> Result; - fn set_handler(&mut self, handler: Box) -> (); + fn set_handler(&mut self, handler: Box); fn unregister_service(&mut self, service_id: ServiceId) -> Result<(), String>; fn register_handler( &mut self, @@ -584,11 +571,11 @@ This is a trait to : */ #[async_trait::async_trait] pub trait APIGatewayClient { - fn connect(&self) -> (); - fn disconnect(&self) -> (); - fn dispatch(&self, request: gateway::ServiceRoutingRequest) -> (); - async fn start(&self) -> (); - async fn stop(&self) -> (); + fn connect(&self); + fn disconnect(&self); + fn dispatch(&self, request: gateway::ServiceRoutingRequest); + async fn start(&self); + async fn stop(&self); } pub struct WebsocketAPIGatewayClient { handler: Arc, @@ -726,46 +713,47 @@ impl WebsocketAPIGatewayClient { #[async_trait::async_trait] impl APIGatewayClient for WebsocketAPIGatewayClient { - fn connect(&self) -> () { + fn connect(&self) { // connect to the API gateway } - fn disconnect(&self) -> () { + fn disconnect(&self) { // disconnect from the API gateway } - fn dispatch(&self, _request: ServiceRoutingRequest) -> () { + fn dispatch(&self, _request: ServiceRoutingRequest) { // send a request to the API gateway } - async fn start(&self) -> () { + async fn start(&self) { println!("starting websocket client"); self.connect().await.unwrap(); self.handler.on_connected(); } - async fn stop(&self) -> () { + async fn stop(&self) { todo!() } } + pub struct DBUSAPIGatewayClient { // dbus client } #[async_trait::async_trait] impl APIGatewayClient for DBUSAPIGatewayClient { - fn connect(&self) -> () { + fn connect(&self) { // connect to the API gateway } - fn disconnect(&self) -> () { + fn disconnect(&self) { // disconnect from the API gateway } - fn dispatch(&self, _request: ServiceRoutingRequest) -> () { + fn dispatch(&self, _request: ServiceRoutingRequest) { // send a request to the API gateway } - async fn start(&self) -> () { + async fn start(&self) { todo!() } - async fn stop(&self) -> () { + async fn stop(&self) { todo!() } } From eaf1c22bd84906475a337a00ad4d5f455f8c9059 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 10:19:27 -0700 Subject: [PATCH 13/46] chore: cleanup unwraps + printlns --- ssda/ssda_service/src/lib.rs | 60 +++++++++++++++++--------- ssda/ssda_types/src/lib.rs | 81 +++++++++++++----------------------- 2 files changed, 70 insertions(+), 71 deletions(-) diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs index 012f228fb..fb99aadfa 100644 --- a/ssda/ssda_service/src/lib.rs +++ b/ssda/ssda_service/src/lib.rs @@ -123,11 +123,17 @@ impl ApiGateway { */ if let Some(service) = services_2_rxs.read().await.get(&service_id) { let (send, receive) = oneshot::channel::(); - let payload = request.payload.clone(); + let method = request.payload.method.clone(); + let payload = serde_json::to_value(request.payload.clone()); + if payload.is_err() { + error!("Failed to serialize payload: {:?}", payload); + continue; + } + let payload = payload.unwrap(); let websocket_request = WebsocketServiceRequest { - method: payload.method.clone(), + method, request_id: request.request_id.clone(), - payload: serde_json::to_value(payload).unwrap(), + payload, respond_to: send, }; let _ = service.send(websocket_request).await; @@ -327,31 +333,38 @@ impl ApiGateway { let response: APIGatewayServiceRegistrationResponse = registration.into(); let response = APIClientMessages::Registered(response); - let _ = tx - .send(Message::Text(serde_json::to_string(&response).unwrap())) - .await; + let msg = serde_json::to_string(&response); + match msg { + Ok(msg) => { + let _ = tx.send(Message::Text(msg.clone())).await; + info!("Sending registration response: {:?}", msg); + } + Err(e) => { + error!("Failed to serialize registration response: {:?}", e); + } + } + info!("Sent registration response: {:?}", response) } APIGatewayClientState::Failed(e) => { error!("Failed to classify message {} err {},{}", msg, E, e); let _ = tx.send(Message::Close(None)).await; - tx.close().await.unwrap(); + let _ = tx.close().await; } APIGatewayClientState::Closed => { info!("Client closed connection"); Self::handle_unregister(service_id, methods_2_services, rule_engine).await; - tx.close().await.unwrap(); + let _ = tx.close().await; } APIGatewayClientState::Message(request_id, msg) => { info!( "got msg from websocket: {} for request {:?}", msg, request_id ); - bridge_tx + let _ = bridge_tx .send(WebsocketServiceResponse::Success(request_id, msg)) - .await - .unwrap(); + .await; } APIGatewayClientState::ServiceCallFailed(id, error) => { info!("Service call failed: {:?}", error); @@ -362,7 +375,7 @@ impl ApiGateway { _ => { info!("handle_message: Unknown message type: {:?}", msg); let _ = tx.send(Message::Close(None)).await; - tx.close().await.unwrap(); + let _ = tx.close().await; } } } @@ -374,9 +387,9 @@ impl ApiGateway { info!("Unregistering service: {:?}", service_id); Self::handle_unregister(service_id, methods_2_services, rule_engine.clone()).await; - services_2_rxes.write().await.remove(service_id).unwrap(); + let _ = services_2_rxes.write().await.remove(service_id); - tx.close().await.unwrap(); + let _ = tx.close().await; } } } @@ -431,9 +444,17 @@ impl ApiGateway { payload: request.payload.clone(), } ); - let service_call = serde_json::to_string(&service_call).unwrap(); - websocket_tx.send(Message::Text(service_call)).await.unwrap(); - + match serde_json::to_string(&service_call) { + Ok(service_call) => { + let _ = websocket_tx.send(Message::Text(service_call)).await; + } + Err(e) => { + error!("Failed to serialize service call: {:?}", e); + let fail = WebsocketServiceResponse::Error(request.request_id, e.to_string()); + let _ = bridge_tx.send(fail).await; + continue; + } + } } Some(bridge_message) = bridge_rx.recv() => { info!("Received message from bridge: {:?}", bridge_message); @@ -456,11 +477,10 @@ impl ApiGateway { methods_2_services.clone(), rule_engine.clone(), ).await; - service_2_rxes + let _ = service_2_rxes .write() .await - .remove(&service_id) - .unwrap(); + .remove(&service_id); break Ok(()); } } diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index a3f639a73..6f749b915 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use futures_util::{SinkExt, StreamExt}; use gateway::ServiceRoutingRequest; use ripple_sdk::api::rules_engine::{Rule, RuleTransform}; +use ripple_sdk::log::{debug, error, info}; use serde::{Deserialize, Serialize}; use service::{ @@ -21,18 +22,7 @@ will wrap the request with metadata, and dispatch the request to the handler ser a response from the service, the API Gateway will translate the service response (using the rules engine) into a Firebolt compatible (success or failure) result. -# Services -Services are standalone processes (programs) that service requests from the API gateway. Services -inform the API gateway about which firebolt methods the Service supports, allowing the API gateway -to know which method(s) to route to which services. Workflow rules can run across multiple services, -with the API Gateway orchestrating the workflow, and performing any composition of outputs -Services must implement ServiceRequestHandler, which is ssthe interface that the APIGatewayClient uses -to interact with services (request processing, state changes, etc. - -# API Gateway Client - -The API Gateway Client is responsible for abstracting the interaction between the Service and the API Gateway, -inclding: Transport, connection management, authentication, and calling the Service via the the Service's +# Servicesprintln ServiceRequestHandler. This design is motivated by the need to free the Service from as much connection oriented detail and let the developer focus on business logic. The API Gateway client is instanced as a crate that can be consumed by a service at the highest possible level of abstraction (and ease of use) - it should only requuire a bit of @@ -603,13 +593,12 @@ impl WebsocketAPIGatewayClient { let registration_request = APIGatewayServiceRegistrationRequest { firebolt_handlers: registration.get_rule_registrations(), }; - - tx.send(Message::Text( - serde_json::to_string(&APIClientMessages::Register(registration_request.clone())) - .unwrap(), - )) - .await - .unwrap(); + let msg = serde_json::to_string(&APIClientMessages::Register(registration_request.clone())); + if let Ok(msg) = msg { + let _ = tx.send(Message::Text(msg)).await; + } else { + error!("websocket: Failed to serialize registration request"); + } while let Some(message) = rx.next().await { match message { @@ -618,58 +607,48 @@ impl WebsocketAPIGatewayClient { attempt to marshal the message into a ServiceRequest if it fails, log the error and continue */ - println!("websocket: Received message via websocket: {:?}", msg); + info!("websocket: Received message via websocket: {:?}", msg); let msg = msg.into_text().unwrap_or_default(); if let Ok(request) = serde_json::from_str::(&msg) { match request { APIClientMessages::Register(registration_request) => { - println!( - "Received registration request: {:?}", - registration_request - ); + info!("Received registration request: {:?}", registration_request); } APIClientMessages::Registered(registration_request) => { - println!( - "Received registered response: {:?}", - registration_request - ); + info!("Received registered response: {:?}", registration_request); handler.on_connected(); } APIClientMessages::Error(error) => { - println!("Received error: {:?}", error); + info!("Received error: {:?}", error); } APIClientMessages::Unregister(service_id) => { - println!("Received unregister request: {:?}", service_id); + info!("Received unregister request: {:?}", service_id); } APIClientMessages::ServiceCall(service_call) => { - println!("Received service call: {:?}", service_call); + info!("Received service call: {:?}", service_call); match handler.handle_request(service_call) { Ok(response) => { let response = APIClientMessages::ServiceCallSuccessResponse(response); // Send the response back to the client - - if let Err(e) = tx - .send(Message::Text( - serde_json::to_string(&response).unwrap(), - )) - .await - { - eprintln!("Error sending message: {:?}", e); + let response = serde_json::to_string(&response); + if let Ok(response) = response { + let _ = tx.send(Message::Text(response.clone())).await; + debug!("Sending response: {:?}", response); + } else { + error!("Failed to serialize response"); } } Err(e) => { // Handle error response - eprintln!("Error handling request: {:?}", e); + error!("Error handling request: {:?}", e); let error_response = APIClientMessages::ServiceCallErrorResponse(e); - if let Err(e) = tx - .send(Message::Text( - serde_json::to_string(&error_response).unwrap(), - )) - .await - { - eprintln!("Error sending message: {:?}", e); + let error_response = serde_json::to_string(&error_response); + if let Ok(error_response) = error_response { + let _ = tx + .send(Message::Text(error_response.clone())) + .await; } } } @@ -677,11 +656,11 @@ impl WebsocketAPIGatewayClient { _ => {} } } else { - println!(" I don't understand this message: {:?}", msg); + error!(" I don't understand this message: {:?}", msg); } } Err(err) => { - eprintln!("Error receiving message: {:?}", err); + error!("Error receiving message: {:?}", err); // Handle the error (e.g., log it, retry, etc.) // You might want to break the loop or handle reconnection logic here // break; @@ -704,7 +683,7 @@ impl WebsocketAPIGatewayClient { Self::handle_messages(yay.0, handler, registration).await; } Err(lame) => { - eprintln!("Error connecting to WebSocket: {:?}", lame); + error!("Error connecting to WebSocket: {:?}", lame); } } Ok(()) @@ -724,7 +703,7 @@ impl APIGatewayClient for WebsocketAPIGatewayClient { } async fn start(&self) { - println!("starting websocket client"); + info!("starting websocket client"); self.connect().await.unwrap(); self.handler.on_connected(); } From 2d21eb87380b7c2cb5f1d7aebc20f6ff73ad0bae Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 11:56:13 -0700 Subject: [PATCH 14/46] feat: adding a few tests --- Cargo.lock | 1 + core/sdk/Cargo.toml | 1 + core/sdk/src/api/rules_engine/mod.rs | 9 +- ssda/ssda_service/src/lib.rs | 158 +++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 354facaee..092a96239 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3618,6 +3618,7 @@ dependencies = [ "libloading", "log", "mock_app_gw", + "mockall", "regex", "ripple_sdk", "rstest", diff --git a/core/sdk/Cargo.toml b/core/sdk/Cargo.toml index d0fa07de1..9d0027fa4 100644 --- a/core/sdk/Cargo.toml +++ b/core/sdk/Cargo.toml @@ -75,6 +75,7 @@ jaq-interpret = { version = "1.5.0", default-features = false } jaq-parse = { version = "1.0.2", default-features = false } jaq-core = "1.5.0" jaq-std = { version = "1.5.1", default-features = false } +mockall = "0.13.1" [dev-dependencies] ripple_sdk = { path = ".", features=["tdk"]} diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index 49992286a..220fe5fce 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -101,7 +101,7 @@ pub enum RuleEndpointProtocol { Extn, Service, } -#[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct JsonDataSource { // configurable namespace to "stuff" an in individual result payload into pub namespace: Option, @@ -109,7 +109,7 @@ pub struct JsonDataSource { pub params: Option, } -#[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Rule { pub alias: String, // Not every rule needs transform @@ -187,7 +187,7 @@ impl Rule { } } -#[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct RuleTransform { #[serde(skip_serializing_if = "Option::is_none")] pub request: Option, @@ -501,7 +501,8 @@ pub fn compose_json_values(values: Vec) -> Value { pub fn make_name_json_safe(name: &str) -> String { name.replace([' ', '.', ','], "_") } - +use mockall::automock; +#[automock] #[async_trait::async_trait] pub trait RuleEngineProvider: Send + Sync { fn add_rules(&mut self, rules: RuleSet); diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs index fb99aadfa..d8026c4e1 100644 --- a/ssda/ssda_service/src/lib.rs +++ b/ssda/ssda_service/src/lib.rs @@ -560,3 +560,161 @@ impl ApiGatewayServer for ApiGateway { self.broker_sender.clone() } } +/* +write unit tests for ApiGateway +*/ +#[cfg(test)] +mod tests { + use super::*; + + use mockall::predicate::eq; + + use std::sync::Arc; + + use ripple_sdk::api::rules_engine::MockRuleEngineProvider; + + use ssda_types::service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, + FireboltMethodHandlerAPIRegistration, + }; + use ssda_types::{JqRule, ServiceId}; + use tokio::sync::RwLock; + + fn make_registration(method: &str) -> APIGatewayServiceRegistrationRequest { + APIGatewayServiceRegistrationRequest { + firebolt_handlers: vec![FireboltMethodHandlerAPIRegistration { + firebolt_method: method.to_string(), + jq_rule: Some(JqRule { + alias: "foo".to_string(), + rule: ".foo".to_string(), + }), + }], + } + } + + #[tokio::test] + async fn test_service_map_add_and_get() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc1".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.bar".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg.clone()]); + let regs = map.get_registrations(&service_id); + assert_eq!(regs.len(), 1); + assert_eq!(regs[0].firebolt_method, "foo.bar"); + } + + #[tokio::test] + async fn test_service_map_remove() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc2".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.baz".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg]); + map.remove_service(&service_id); + let regs = map.get_registrations(&service_id); + assert!(regs.is_empty()); + } + + #[tokio::test] + async fn test_service_map_get_service_for_method() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc3".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.qux".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg.clone()]); + let found = map.get_service_for_method("foo.qux"); + assert!(found.is_some()); + let (sid, r) = found.unwrap(); + assert_eq!(sid, service_id); + assert_eq!(r.firebolt_method, "foo.qux"); + } + + #[tokio::test] + async fn test_is_apigateway_connection_accept() { + let uri: http::Uri = "/apigateway?serviceId=testsvc".parse().unwrap(); + let res = ApiGateway::is_apigateway_connection(&uri); + assert!(matches!( + res, + Ok(APIGatewayServiceConnectionDisposition::Accept(_)) + )); + } + + #[tokio::test] + async fn test_is_apigateway_connection_reject() { + let uri: http::Uri = "/notgateway".parse().unwrap(); + let res = ApiGateway::is_apigateway_connection(&uri); + assert!(matches!( + res, + Err(APIGatewayServiceConnectionError::NotAService) + )); + } + + #[tokio::test] + async fn test_classify_message_register() { + let reg = APIClientMessages::Register(make_registration("foo.bar")); + let msg = Message::Text(serde_json::to_string(®).unwrap()); + let state = ApiGateway::classify_message(&msg); + match state { + APIGatewayClientState::Registering(_) => {} + _ => panic!("Expected Registering"), + } + } + + #[tokio::test] + async fn test_classify_message_close() { + let msg = Message::Close(None); + let state = ApiGateway::classify_message(&msg); + assert!(matches!(state, APIGatewayClientState::Closed)); + } + + #[tokio::test] + async fn test_handle_registration_and_unregister() { + let service_id = ServiceId::new("svc4".to_string()); + let mut mock = MockRuleEngineProvider::new(); + let r = Rule { + alias: "foo.bar".to_string(), + filter: Some(".foo".to_string()), + endpoint: Some("service".to_string()), + ..Default::default() + }; + mock.expect_add_rule() + .with(eq(r.clone())) + .times(1) + .return_const(()); + mock.expect_remove_rule().times(1).return_const(()); + + let rule_engine: Arc< + RwLock>, + > = Arc::new(RwLock::new(Box::new(mock))); + + let methods_2_services = Arc::new(RwLock::new(ServiceMap::new())); + let registration = make_registration("foo.bar"); + ApiGateway::handle_registration( + service_id.clone(), + rule_engine.clone(), + ®istration, + methods_2_services.clone(), + ) + .await; + let regs = methods_2_services + .read() + .await + .get_registrations(&service_id); + assert_eq!(regs.len(), 1); + + ApiGateway::handle_unregister(&service_id, methods_2_services.clone(), rule_engine.clone()) + .await; + let regs = methods_2_services + .read() + .await + .get_registrations(&service_id); + assert!(regs.is_empty()); + } +} From f53906becab56b8a953b72061625d7775b715920 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 20 May 2025 16:02:48 -0700 Subject: [PATCH 15/46] feat: client backoff --- ssda/ssda_types/src/lib.rs | 53 +++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index 6f749b915..390cabfdd 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::time::Duration; use futures_util::{SinkExt, StreamExt}; use gateway::ServiceRoutingRequest; @@ -573,6 +574,7 @@ pub struct WebsocketAPIGatewayClient { } use tokio_tungstenite::{connect_async, tungstenite::Message}; +use url::Url; impl WebsocketAPIGatewayClient { pub fn new(handler: Arc, registration: ServiceRegistration) -> Self { @@ -668,25 +670,40 @@ impl WebsocketAPIGatewayClient { } } } - pub async fn connect(&self) -> Result<(), Box> { - /* - todo: refactor to use the backoff crate - */ - - match connect_async("ws://localhost:3474/apigateway?serviceId=tester").await { - Ok(yay) => { - let handler = self.handler.clone(); - /* - register serviced fb methods - */ - let registration = self.registration.clone(); - Self::handle_messages(yay.0, handler, registration).await; - } - Err(lame) => { - error!("Error connecting to WebSocket: {:?}", lame); + pub async fn connect( + &self, + endpoint_url: Option, + ) -> Result<(), Box> { + let url = Url::parse( + &endpoint_url + .unwrap_or_else(|| "ws://localhost:3474/apigateway?serviceId=tester".to_string()), + )?; + let mut backoff = Duration::from_secs(1); + + loop { + match connect_async(url.clone()).await { + Ok((ws_stream, _)) => { + let handler = self.handler.clone(); + let registration = self.registration.clone(); + + info!("✅ Connected to WebSocket"); + + // Reset backoff after successful connection + backoff = Duration::from_secs(1); + + // This handles the message loop and returns on disconnect + Self::handle_messages(ws_stream, handler, registration).await; + info!("🔌 Disconnected, retrying..."); + } + Err(err) => { + error!("Error connecting to WebSocket: {:?}", err); + + // Exponential backoff (up to 1 minute) + tokio::time::sleep(backoff).await; + backoff = std::cmp::min(backoff * 2, Duration::from_secs(60)); + } } } - Ok(()) } } @@ -704,7 +721,7 @@ impl APIGatewayClient for WebsocketAPIGatewayClient { async fn start(&self) { info!("starting websocket client"); - self.connect().await.unwrap(); + self.connect(None).await.unwrap(); self.handler.on_connected(); } From 9ab765b9386071494317c6bdea59f9a6f7896d39 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Wed, 4 Jun 2025 15:09:48 -0700 Subject: [PATCH 16/46] feat: local_dev load from etc, checkpoint before merge from main --- core/main/Cargo.toml | 2 +- core/sdk/src/manifest/device.rs | 2 +- core/sdk/src/manifest/extn.rs | 2 +- device/thunder_ripple_sdk/Cargo.toml | 1 + ssda/example-service/src/main.rs | 6 ++---- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index ff65095ff..8e50885a1 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -45,7 +45,7 @@ contract_tests = [ tdk=[] [dependencies] base64.workspace = true -ripple_sdk = { workspace = true, features = ["full"] } +ripple_sdk = { workspace = true, features = ["full","local_dev"] } jsonrpsee = { workspace = true, features = ["macros"] } futures-channel.workspace = true futures.workspace = true diff --git a/core/sdk/src/manifest/device.rs b/core/sdk/src/manifest/device.rs index 4ecc3e20d..abf1aca61 100644 --- a/core/sdk/src/manifest/device.rs +++ b/core/sdk/src/manifest/device.rs @@ -33,7 +33,7 @@ type DeviceManifestLoader = Vec Result<(String, DeviceManifest), RippleE fn try_manifest_files() -> Result { let dm_arr: DeviceManifestLoader = if cfg!(feature = "local_dev") { - vec![load_from_env, load_from_home] + vec![load_from_env, load_from_home, load_from_etc] } else if cfg!(any(test, feature = "test")) { vec![load_from_env] } else { diff --git a/core/sdk/src/manifest/extn.rs b/core/sdk/src/manifest/extn.rs index b845f43ff..1040926c4 100644 --- a/core/sdk/src/manifest/extn.rs +++ b/core/sdk/src/manifest/extn.rs @@ -29,7 +29,7 @@ type ExtnManifestLoader = Vec Result<(String, ExtnManifest), RippleError fn try_manifest_files() -> Result { let dm_arr: ExtnManifestLoader = if cfg!(feature = "local_dev") { - vec![load_from_env, load_from_home] + vec![load_from_env, load_from_home, load_from_etc] } else if cfg!(any(test, feature = "test")) { vec![load_from_env] } else { diff --git a/device/thunder_ripple_sdk/Cargo.toml b/device/thunder_ripple_sdk/Cargo.toml index 62fd747e9..fd1d54109 100644 --- a/device/thunder_ripple_sdk/Cargo.toml +++ b/device/thunder_ripple_sdk/Cargo.toml @@ -54,6 +54,7 @@ contract_tests = [ local_dev=[] mock=[] + [dependencies] tokio-tungstenite = { workspace = true, features = ["native-tls"] } base64 = { workspace = true, default-features = false, features=["alloc"] } diff --git a/ssda/example-service/src/main.rs b/ssda/example-service/src/main.rs index 8199f4992..3fcfc25c6 100644 --- a/ssda/example-service/src/main.rs +++ b/ssda/example-service/src/main.rs @@ -12,10 +12,8 @@ use ssda_types::{JqRule, ServiceId}; pub struct ExampleService {} impl ExampleService { - pub fn new() -> Self { - ExampleService {} - } -} + pub fn new() -> Self {let dm_arr = vec![load_from_etc]; + #[async_trait::async_trait] impl ServiceRequestHandlerImpl for ExampleService { From caf27fc51e692891ddbef00f2de572f5e53dcc3a Mon Sep 17 00:00:00 2001 From: brendanobra Date: Mon, 9 Jun 2025 13:30:20 -0700 Subject: [PATCH 17/46] chore: merge from main --- Cargo.lock | 6478 ++--------------- Cargo.toml | 1 + core/main/src/broker/endpoint_broker.rs | 3 +- core/main/src/broker/http_broker.rs | 16 +- .../broker/test/mock_thunder_lite_server.rs | 1 - core/main/src/broker/thunder_broker.rs | 7 +- core/main/src/broker/websocket_broker.rs | 17 +- core/main/src/broker/workflow_broker.rs | 30 +- core/main/src/firebolt/firebolt_ws.rs | 18 +- core/main/src/state/bootstrap_state.rs | 14 +- core/main/src/state/platform_state.rs | 4 +- core/sdk/src/api/rules_engine/mod.rs | 109 +- device/thunder_ripple_sdk/Cargo.toml | 5 +- examples/tm_extn/src/tm_ffi.rs | 2 +- ssda/example-service/src/main.rs | 7 +- 15 files changed, 542 insertions(+), 6170 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02aefc02b..072ca3e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,12 +30,12 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.15", + "getrandom 0.3.3", "once_cell", "serde", "version_check", @@ -83,15 +83,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anyhow" -version = "1.0.96" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "ariadne" @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.18" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" dependencies = [ "flate2", "futures-core", @@ -176,14 +176,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", + "pin-project-lite", "slab", ] @@ -204,9 +205,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock 3.4.0", "cfg-if 1.0.0", @@ -215,7 +216,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix", + "rustix 1.0.7", "slab", "tracing", "windows-sys 0.59.0", @@ -252,9 +253,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" dependencies = [ "async-channel 2.3.1", "async-io", @@ -265,15 +266,15 @@ dependencies = [ "cfg-if 1.0.0", "event-listener 5.4.0", "futures-lite", - "rustix", + "rustix 1.0.7", "tracing", ] [[package]] name = "async-signal" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" dependencies = [ "async-io", "async-lock 3.4.0", @@ -281,7 +282,7 @@ dependencies = [ "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix", + "rustix 1.0.7", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -289,9 +290,9 @@ dependencies = [ [[package]] name = "async-std" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ "async-attributes", "async-channel 1.9.0", @@ -329,7 +330,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -353,7 +354,7 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes 1.10.0", + "bytes 1.10.1", "futures-util", "http 0.2.12", "http-body", @@ -379,7 +380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes 1.10.0", + "bytes 1.10.1", "futures-util", "http 0.2.12", "http-body", @@ -391,9 +392,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -424,9 +425,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "basic-cookies" @@ -471,9 +472,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -529,9 +530,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "serde", @@ -539,9 +540,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byte-tools" @@ -551,9 +552,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "byteorder" @@ -573,9 +574,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -592,20 +593,19 @@ dependencies = [ [[package]] name = "bzip2-sys" -version = "0.1.12+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ebc2f1a417f01e1da30ef264ee86ae31d2dcd2d603ea283d3c244a883ca2a9" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] [[package]] name = "cc" -version = "1.2.14" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -626,9 +626,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -636,7 +636,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -710,9 +710,9 @@ dependencies = [ [[package]] name = "console" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", "libc", @@ -825,15 +825,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -902,16 +902,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", -] - -[[package]] -name = "distributor_general" -version = "1.1.0" -dependencies = [ - "ripple_sdk", - "serde", - "serde_json", + "syn 2.0.101", ] [[package]] @@ -922,15 +913,15 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dyn-clone" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "ena" @@ -973,9 +964,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1010,9 +1001,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.4.0", "pin-project-lite", @@ -1094,9 +1085,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -1243,7 +1234,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -1323,9 +1314,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1336,14 +1327,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -1360,9 +1351,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "globset" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" dependencies = [ "aho-corasick", "bstr", @@ -1398,13 +1389,13 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.1", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -1429,9 +1420,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "hashers" @@ -1456,9 +1447,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1496,7 +1487,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "fnv", "itoa", ] @@ -1507,7 +1498,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "fnv", "itoa", ] @@ -1518,16 +1509,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "http 0.2.12", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -1569,7 +1560,7 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "futures-channel", "futures-core", "futures-util", @@ -1617,14 +1608,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1640,21 +1632,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -1663,31 +1656,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -1695,67 +1668,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - [[package]] name = "idna" version = "1.0.3" @@ -1769,9 +1729,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1795,36 +1755,36 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] [[package]] name = "indextree" -version = "4.7.3" +version = "4.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f3e68a01402c3404bfb739079f38858325bc7ad775b07922278a8a415b1a3f" +checksum = "cb9e21e48c85fa6643a38caca564645a3bbc9211edf506fc8ed690c7e7b4d3c7" dependencies = [ "indextree-macros", ] [[package]] name = "indextree-macros" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" +checksum = "f85dac6c239acc85fd61934c572292d93adfd2de459d9c032aa22b553506e915" dependencies = [ "either", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", - "strum 0.26.3", - "syn 2.0.98", - "thiserror 1.0.69", + "strum 0.27.1", + "syn 2.0.101", + "thiserror 2.0.12", ] [[package]] @@ -1842,9 +1802,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array 0.14.7", ] @@ -1866,9 +1826,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iso8601" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5c177cff824ab21a6f41079a4c401241c4e8be14f316c4c6b07d5fca351c98d" +checksum = "e1082f0c48f143442a1ac6122f67e360ceee130b967af4d50996e5154a45df46" dependencies = [ "nom 8.0.0", ] @@ -1902,18 +1862,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jaq-core" @@ -1941,7 +1901,7 @@ dependencies = [ "ahash", "dyn-clone", "hifijson", - "indexmap 2.7.1", + "indexmap 2.9.0", "jaq-syn", "once_cell", "serde_json", @@ -1977,10 +1937,11 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] @@ -2130,7 +2091,7 @@ dependencies = [ "bytecount", "fancy-regex", "fraction", - "getrandom 0.2.15", + "getrandom 0.2.16", "iso8601", "itoa", "memchr", @@ -2245,9 +2206,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" @@ -2261,9 +2222,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -2271,7 +2232,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "libc", "redox_syscall", ] @@ -2282,17 +2243,23 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -2327,7 +2294,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -2373,7 +2340,6 @@ dependencies = [ "ssda_types", "strum 0.24.1", "strum_macros 0.24.3", - "tokio-tungstenite 0.20.1", "url", "vergen", ] @@ -2416,9 +2382,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -2444,13 +2410,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2500,7 +2466,6 @@ dependencies = [ "ripple_tdk", "serde", "serde_json", - "tokio-tungstenite 0.20.1", "url", ] @@ -2527,7 +2492,7 @@ dependencies = [ "cfg-if 1.0.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -2536,7 +2501,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "encoding_rs", "futures-util", "http 0.2.12", @@ -2558,11 +2523,10 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2721,17 +2685,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "onig" -version = "6.4.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "libc", "once_cell", "onig_sys", @@ -2739,9 +2703,9 @@ dependencies = [ [[package]] name = "onig_sys" -version = "69.8.1" +version = "69.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" dependencies = [ "cc", "pkg-config", @@ -2771,11 +2735,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "cfg-if 1.0.0", "foreign-types", "libc", @@ -2792,7 +2756,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -2803,9 +2767,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -2815,11 +2779,12 @@ dependencies = [ [[package]] name = "os_info" -version = "3.10.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" +checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" dependencies = [ "log", + "plist", "serde", "windows-sys 0.52.0", ] @@ -2839,7 +2804,7 @@ dependencies = [ "anyhow", "async-trait", "backtrace", - "bytes 1.10.0", + "bytes 1.10.1", "chrono", "flate2", "futures-util", @@ -2874,13 +2839,13 @@ dependencies = [ [[package]] name = "pact_consumer" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdff329c97c39ffbc78640c83d33cd1d28f2ea8ecb7f0d9e48cbfcce95960b96" +checksum = "016334b4a70ecb22f448267fd817003f7c09ffda5165aa31e9fe4ede5091aa07" dependencies = [ "anyhow", "async-trait", - "bytes 1.10.0", + "bytes 1.10.1", "futures", "itertools 0.10.5", "lazy_static", @@ -2907,7 +2872,7 @@ dependencies = [ "ansi_term", "anyhow", "base64 0.21.7", - "bytes 1.10.0", + "bytes 1.10.1", "chrono", "difference", "futures", @@ -2940,12 +2905,12 @@ dependencies = [ [[package]] name = "pact_mock_server" -version = "1.2.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb13cec89b68677e5701d4861a24335bf614b103bb9328bbf605276f758c506" +checksum = "daaea27b75fbc1bf7740562518a77933f8bb2ba5b0d4115f61f52691553fbabd" dependencies = [ "anyhow", - "bytes 1.10.0", + "bytes 1.10.1", "futures", "hyper", "hyper-rustls", @@ -2977,7 +2942,7 @@ dependencies = [ "anyhow", "ariadne", "base64 0.21.7", - "bytes 1.10.0", + "bytes 1.10.1", "chrono", "chrono-tz", "fs2", @@ -3015,9 +2980,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -3025,9 +2990,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if 1.0.0", "libc", @@ -3087,7 +3052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.1", + "indexmap 2.9.0", ] [[package]] @@ -3136,22 +3101,22 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -3179,30 +3144,52 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plist" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d" +dependencies = [ + "base64 0.22.1", + "indexmap 2.9.0", + "quick-xml", + "serde", + "time", +] [[package]] name = "polling" -version = "3.7.4" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix", + "rustix 1.0.7", "tracing", "windows-sys 0.59.0", ] [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -3212,9 +3199,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -3273,9 +3260,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -3286,7 +3273,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "prost-derive", ] @@ -3296,7 +3283,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "heck 0.4.1", "itertools 0.10.5", "lazy_static", @@ -3340,15 +3327,30 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9318ead08c799aad12a55a3e78b82e0b6167271ffd1f627b758891282f739187" +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.7.3" @@ -3428,7 +3430,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -3437,7 +3439,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", ] [[package]] @@ -3481,11 +3483,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] [[package]] @@ -3494,7 +3496,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] @@ -3548,7 +3550,7 @@ checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", - "bytes 1.10.0", + "bytes 1.10.1", "encoding_rs", "futures-core", "futures-util", @@ -3586,13 +3588,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.9" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if 1.0.0", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -3602,13 +3604,13 @@ dependencies = [ name = "ripple_sdk" version = "1.1.0" dependencies = [ - "async-channel 2.3.1", "async-std", "async-trait", "chrono", "fern", "futures", "futures-channel", + "futures-util", "jaq-core", "jaq-interpret", "jaq-parse", @@ -3629,7 +3631,9 @@ dependencies = [ "serde_yaml", "testing_logger", "tokio", + "tokio-tungstenite 0.20.1", "tree_magic_mini", + "url", "uuid", ] @@ -3641,16 +3645,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rpc_extn" -version = "1.1.0" -dependencies = [ - "jsonrpsee", - "ripple_sdk", - "serde", - "serde_json", -] - [[package]] name = "rstest" version = "0.18.2" @@ -3676,7 +3670,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.98", + "syn 2.0.101", "unicode-ident", ] @@ -3707,10 +3701,23 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -3759,15 +3766,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -3780,9 +3787,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" +checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" dependencies = [ "sdd", ] @@ -3833,7 +3840,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "core-foundation", "core-foundation-sys", "libc", @@ -3852,9 +3859,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" @@ -3873,7 +3880,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -3909,9 +3916,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3934,7 +3941,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.9.0", "itoa", "ryu", "serde", @@ -3963,7 +3970,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -4010,9 +4017,9 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4027,9 +4034,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -4063,9 +4070,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" @@ -4079,9 +4086,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4094,7 +4101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes 1.10.0", + "bytes 1.10.1", "futures", "http 0.2.12", "httparse", @@ -4172,9 +4179,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stream-tungstenite" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a1faabcaf0ade00ed119bec2bbde8a1b687ee67f608ac51d6a19ca730285cb" +checksum = "99193254746dac7d4dd50211ae4dbb7a95ab7024dda4251782c4ad42c852d2fa" dependencies = [ "async-trait", "eyre", @@ -4209,11 +4216,11 @@ checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" dependencies = [ - "strum_macros 0.26.4", + "strum_macros 0.27.1", ] [[package]] @@ -4231,15 +4238,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -4271,9 +4278,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -4294,7 +4301,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -4335,9 +4342,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" dependencies = [ "filetime", "libc", @@ -4346,15 +4353,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.17.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if 1.0.0", "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.3", "once_cell", - "rustix", + "rustix 1.0.7", "windows-sys 0.59.0", ] @@ -4421,7 +4427,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -4432,15 +4438,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", -] - -[[package]] -name = "thunder" -version = "1.1.0" -dependencies = [ - "serde", - "thunder_ripple_sdk", + "syn 2.0.101", ] [[package]] @@ -4448,6 +4446,7 @@ name = "thunder_ripple_sdk" version = "1.1.0" dependencies = [ "base64 0.22.1", + "base64ct", "csv", "expectest", "futures", @@ -4467,18 +4466,18 @@ dependencies = [ "strum 0.24.1", "strum_macros 0.24.3", "test-log", - "tokio-tungstenite 0.20.1", "tree_magic_mini", "url", ] [[package]] name = "time" -version = "0.3.37" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -4488,15 +4487,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -4513,39 +4512,28 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", ] -[[package]] -name = "tm_extn" -version = "1.1.0" -dependencies = [ - "ripple_sdk", - "serde", - "serde_json", - "tokio-tungstenite 0.20.1", - "url", -] - [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", - "bytes 1.10.0", + "bytes 1.10.1", "libc", - "mio 1.0.3", + "mio 1.0.4", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.8", + "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", ] @@ -4568,7 +4556,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -4611,9 +4599,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", - "native-tls", "tokio", - "tokio-native-tls", "tungstenite 0.20.1", ] @@ -4633,11 +4619,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "futures-core", "futures-io", "futures-sink", @@ -4652,7 +4638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fcaf159b4e7a376b05b5bfd77bfd38f3324f5fce751b4213bfc7eaa47affb4e" dependencies = [ "base64 0.22.1", - "bytes 1.10.0", + "bytes 1.10.1", "futures-core", "futures-sink", "http 1.3.1", @@ -4666,21 +4652,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.24", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -4691,24 +4677,31 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.9.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.7.3", + "toml_write", + "winnow 0.7.10", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tonic" version = "0.9.2" @@ -4718,7 +4711,7 @@ dependencies = [ "async-trait", "axum", "base64 0.21.7", - "bytes 1.10.0", + "bytes 1.10.1", "futures-core", "futures-util", "h2", @@ -4796,20 +4789,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -4842,12 +4835,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", - "bytes 1.10.0", + "bytes 1.10.1", "data-encoding", "http 0.2.12", "httparse", "log", - "native-tls", "rand 0.8.5", "sha1", "thiserror 1.0.69", @@ -4861,7 +4853,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "bytes 1.10.0", + "bytes 1.10.1", "data-encoding", "http 1.3.1", "httparse", @@ -4887,9 +4879,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" @@ -4944,12 +4936,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -4958,13 +4944,15 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", + "js-sys", "serde", "sha1_smol", + "wasm-bindgen", ] [[package]] @@ -4975,9 +4963,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" @@ -5035,9 +5023,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -5064,7 +5052,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -5099,7 +5087,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5161,7 +5149,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -5209,11 +5197,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", ] [[package]] @@ -5375,9 +5413,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -5394,24 +5432,18 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "ws" @@ -5443,13 +5475,12 @@ dependencies = [ [[package]] name = "xattr" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" +checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" dependencies = [ "libc", - "linux-raw-sys", - "rustix", + "rustix 1.0.7", ] [[package]] @@ -5460,9 +5491,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -5472,35 +5503,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -5520,5610 +5550,26 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", "synstructure", ] [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ + "displaydoc", "yoke", "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" -dependencies = [ - "cc", - "pkg-config", -]# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if 1.0.0", - "cipher", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if 1.0.0", - "getrandom 0.2.15", - "once_cell", - "serde", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anyhow" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" - -[[package]] -name = "ariadne" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72fe02fc62033df9ba41cba57ee19acf5e742511a140c7dbc3a873e19a19a1bd" -dependencies = [ - "unicode-width 0.1.14", - "yansi", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "assert-json-diff" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-compression" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" -dependencies = [ - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "async-executor" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io", - "async-lock 3.4.0", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" -dependencies = [ - "async-lock 3.4.0", - "cfg-if 1.0.0", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener 5.4.0", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-object-pool" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333c456b97c3f2d50604e8b2624253b7f787208cb72eb75e64b0ad11b221652c" -dependencies = [ - "async-std", -] - -[[package]] -name = "async-process" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" -dependencies = [ - "async-channel 2.3.1", - "async-io", - "async-lock 3.4.0", - "async-signal", - "async-task", - "blocking", - "cfg-if 1.0.0", - "event-listener 5.4.0", - "futures-lite", - "rustix", - "tracing", -] - -[[package]] -name = "async-signal" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" -dependencies = [ - "async-io", - "async-lock 3.4.0", - "atomic-waker", - "cfg-if 1.0.0", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-std" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" -dependencies = [ - "async-attributes", - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock 3.4.0", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[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 1.10.0", - "futures-util", - "http 0.2.12", - "http-body", - "hyper", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "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 1.10.0", - "futures-util", - "http 0.2.12", - "http-body", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "basic-cookies" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" -dependencies = [ - "lalrpop", - "lalrpop-util", - "regex", -] - -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel 2.3.1", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - -[[package]] -name = "bstr" -version = "1.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "bytecount" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - -[[package]] -name = "bytes" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" -dependencies = [ - "serde", -] - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.12+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ebc2f1a417f01e1da30ef264ee86ae31d2dcd2d603ea283d3c244a883ca2a9" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "cc" -version = "1.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - -[[package]] -name = "chrono-tz" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf", -] - -[[package]] -name = "chrono-tz-build" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" -dependencies = [ - "parse-zoneinfo", - "phf", - "phf_codegen", -] - -[[package]] -name = "chumsky" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clap" -version = "4.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" -dependencies = [ - "bitflags 1.3.2", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "console" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" -dependencies = [ - "encode_unicode", - "libc", - "once_cell", - "unicode-width 0.2.0", - "windows-sys 0.59.0", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array 0.14.7", - "typenum", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" -dependencies = [ - "memchr", -] - -[[package]] -name = "data-encoding" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "distributor_general" -version = "1.1.0" -dependencies = [ - "ripple_sdk", - "serde", - "serde_json", -] - -[[package]] -name = "downcast" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" - -[[package]] -name = "dyn-clone" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35" - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "ena" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" -dependencies = [ - "log", -] - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "env-file-reader" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00bb0c3f782b0967b28b4fd608ad3ce331817bdd120bbb193b3958a7a4a87b1" -dependencies = [ - "regex", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "backtrace", - "version_check", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" -dependencies = [ - "event-listener 5.4.0", - "pin-project-lite", -] - -[[package]] -name = "exitcode" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" - -[[package]] -name = "expectest" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78817c0b64aab8153fbd7532339fbac1a54e43c715802715a288163ca6024978" -dependencies = [ - "num-traits", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fancy-regex" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" -dependencies = [ - "bit-set", - "regex", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fern" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" -dependencies = [ - "log", -] - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "libredox", - "windows-sys 0.59.0", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fraction" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3027ae1df8d41b4bed2241c8fdad4acc1e7af60c8e17743534b545e77182d678" -dependencies = [ - "lazy_static", - "num", -] - -[[package]] -name = "fragile" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" - -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-lite" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "globset" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax 0.8.5", -] - -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "gregorian" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18888aec42cda8438d991d59b05e5ffa1a9799b1df634346672b1fac7eb02354" -dependencies = [ - "libc", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes 1.10.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.7.1", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "hashers" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" -dependencies = [ - "fxhash", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hifijson" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9958ab3ce3170c061a27679916bd9b969eceeb5e8b120438e6751d0987655c42" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes 1.10.0", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes 1.10.0", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes 1.10.0", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "httpmock" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ec9586ee0910472dec1a1f0f8acf52f0fdde93aea74d70d4a3107b4be0fd5b" -dependencies = [ - "assert-json-diff", - "async-object-pool", - "async-std", - "async-trait", - "base64 0.21.7", - "basic-cookies", - "crossbeam-utils", - "form_urlencoded", - "futures-util", - "hyper", - "lazy_static", - "levenshtein", - "log", - "regex", - "serde", - "serde_json", - "serde_regex", - "similar", - "tokio", - "url", -] - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes 1.10.0", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper", - "log", - "rustls", - "rustls-native-certs", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", -] - -[[package]] -name = "indextree" -version = "4.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f3e68a01402c3404bfb739079f38858325bc7ad775b07922278a8a415b1a3f" -dependencies = [ - "indextree-macros", -] - -[[package]] -name = "indextree-macros" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "477e2e7ec7379407656293ff74902caea786a1dda427ca1f84b923c4fdeb7659" -dependencies = [ - "either", - "itertools 0.13.0", - "proc-macro2", - "quote", - "strum 0.26.3", - "syn 2.0.98", - "thiserror 1.0.69", -] - -[[package]] -name = "indicatif" -version = "0.17.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" -dependencies = [ - "console", - "number_prefix", - "portable-atomic", - "unicode-width 0.2.0", - "web-time", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iso8601" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5c177cff824ab21a6f41079a4c401241c4e8be14f316c4c6b07d5fca351c98d" -dependencies = [ - "nom 8.0.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "jaq-core" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6fda09ee08c84c81293fdf811d9ebaa87b327557b5391f290c926d728c2ddd4" -dependencies = [ - "aho-corasick", - "base64 0.22.1", - "chrono", - "hifijson", - "jaq-interpret", - "libm", - "log", - "regex", - "urlencoding", -] - -[[package]] -name = "jaq-interpret" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe95ec3c24af3fd9f3dd1091593f5e49b003a66c496a8aa39d764d0a06ae17b" -dependencies = [ - "ahash", - "dyn-clone", - "hifijson", - "indexmap 2.7.1", - "jaq-syn", - "once_cell", - "serde_json", -] - -[[package]] -name = "jaq-parse" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0346d7d3146cdda8acd929581f3d6626a332356c74d5c95aeaffaac2eb6dee82" -dependencies = [ - "chumsky", - "jaq-syn", -] - -[[package]] -name = "jaq-std" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfbaa55578fd3b70433b594a370741e0c364e4afff92cc0099623fce87311bc1" -dependencies = [ - "jaq-syn", -] - -[[package]] -name = "jaq-syn" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba44fe4428c71304604261ecbae047ee9cfb60c4f1a6bd222ebbb31726d3948" -dependencies = [ - "serde", -] - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "jsonrpsee" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" -dependencies = [ - "jsonrpsee-core", - "jsonrpsee-proc-macros", - "jsonrpsee-server", - "jsonrpsee-types", - "jsonrpsee-ws-client", - "tracing", -] - -[[package]] -name = "jsonrpsee-client-transport" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a" -dependencies = [ - "futures-util", - "http 0.2.12", - "jsonrpsee-core", - "jsonrpsee-types", - "pin-project", - "rustls-native-certs", - "soketto", - "thiserror 1.0.69", - "tokio", - "tokio-rustls", - "tokio-util", - "tracing", - "webpki-roots", -] - -[[package]] -name = "jsonrpsee-core" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803" -dependencies = [ - "anyhow", - "arrayvec", - "async-lock 2.8.0", - "async-trait", - "beef", - "futures-channel", - "futures-timer", - "futures-util", - "globset", - "hyper", - "jsonrpsee-types", - "parking_lot", - "rand 0.8.5", - "rustc-hash", - "serde", - "serde_json", - "soketto", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-proc-macros" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "jsonrpsee-server" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" -dependencies = [ - "futures-channel", - "futures-util", - "http 0.2.12", - "hyper", - "jsonrpsee-core", - "jsonrpsee-types", - "serde", - "serde_json", - "soketto", - "tokio", - "tokio-stream", - "tokio-util", - "tower", - "tracing", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245ba8e5aa633dd1c1e4fae72bce06e71f42d34c14a2767c6b4d173b57bee5e5" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "jsonrpsee-ws-client" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1b3975ed5d73f456478681a417128597acd6a2487855fdb7b4a3d4d195bf5e" -dependencies = [ - "http 0.2.12", - "jsonrpsee-client-transport", - "jsonrpsee-core", - "jsonrpsee-types", -] - -[[package]] -name = "jsonschema" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978" -dependencies = [ - "ahash", - "anyhow", - "base64 0.21.7", - "bytecount", - "fancy-regex", - "fraction", - "getrandom 0.2.15", - "iso8601", - "itoa", - "memchr", - "num-cmp", - "once_cell", - "parking_lot", - "percent-encoding", - "regex", - "serde", - "serde_json", - "time", - "url", - "uuid", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax 0.8.5", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lenient_semver" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de8de3f4f3754c280ce1c8c42ed8dd26a9c8385c2e5ad4ec5a77e774cea9c1ec" -dependencies = [ - "lenient_semver_parser", - "semver", -] - -[[package]] -name = "lenient_semver_parser" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f650c1d024ddc26b4bb79c3076b30030f2cf2b18292af698c81f7337a64d7d6" -dependencies = [ - "lenient_semver_version_builder", - "semver", -] - -[[package]] -name = "lenient_semver_version_builder" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9049f8ff49f75b946f95557148e70230499c8a642bf2d6528246afc7d0282d17" -dependencies = [ - "semver", -] - -[[package]] -name = "levenshtein" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.8.0", - "libc", - "redox_syscall", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -dependencies = [ - "value-bag", -] - -[[package]] -name = "logos" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-codegen" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax 0.6.29", - "syn 2.0.98", -] - -[[package]] -name = "logos-derive" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" -dependencies = [ - "logos-codegen", -] - -[[package]] -name = "main" -version = "1.1.0" -dependencies = [ - "arrayvec", - "base64 0.22.1", - "env-file-reader", - "exitcode", - "futures", - "futures-channel", - "futures-util", - "httpmock", - "hyper", - "jaq-core", - "jaq-interpret", - "jaq-parse", - "jaq-std", - "jsonrpsee", - "openrpc_validator", - "proc-macro2", - "querystring", - "rand 0.8.5", - "regex", - "ripple_sdk", - "ripple_tdk", - "rstest", - "sd-notify", - "serde", - "serde_json", - "serial_test", - "ssda_service", - "ssda_types", - "strum 0.24.1", - "strum_macros 0.24.3", - "tokio-tungstenite 0.20.1", - "url", - "vergen", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio 0.6.23", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "mock_app_gw" -version = "0.1.0" -dependencies = [ - "async-trait", - "futures-util", - "serde", - "serde_json", - "tokio", - "tokio-tungstenite 0.20.1", - "uuid", -] - -[[package]] -name = "mock_device" -version = "1.0.0" -dependencies = [ - "http 0.2.12", - "jsonrpsee", - "ripple_sdk", - "ripple_tdk", - "serde", - "serde_json", - "tokio-tungstenite 0.20.1", - "url", -] - -[[package]] -name = "mockall" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" -dependencies = [ - "cfg-if 1.0.0", - "downcast", - "fragile", - "mockall_derive", - "predicates", - "predicates-tree", -] - -[[package]] -name = "mockall_derive" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" -dependencies = [ - "cfg-if 1.0.0", - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "multer" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" -dependencies = [ - "bytes 1.10.0", - "encoding_rs", - "futures-util", - "http 0.2.12", - "httparse", - "log", - "memchr", - "mime", - "serde", - "serde_json", - "spin", - "version_check", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "native-tls" -version = "0.2.11" -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", -] - -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-cmp" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" - -[[package]] -name = "onig" -version = "6.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" -dependencies = [ - "bitflags 1.3.2", - "libc", - "once_cell", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openrpc_validator" -version = "0.1.0" -dependencies = [ - "clap", - "jsonschema", - "serde", - "serde_json", -] - -[[package]] -name = "openssl" -version = "0.10.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" -dependencies = [ - "bitflags 2.8.0", - "cfg-if 1.0.0", - "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.98", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os_info" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" -dependencies = [ - "log", - "serde", - "windows-sys 0.52.0", -] - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "pact-plugin-driver" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cead6a8c9f5e0de8f13cdf00d2fd684d00b79d70baa10c3f74b9d0b211dfdcd6" -dependencies = [ - "anyhow", - "async-trait", - "backtrace", - "bytes 1.10.0", - "chrono", - "flate2", - "futures-util", - "home", - "indicatif", - "itertools 0.12.1", - "lazy_static", - "log", - "maplit", - "md5", - "os_info", - "pact_models", - "prost", - "prost-types", - "regex", - "reqwest", - "semver", - "serde", - "serde_json", - "sha2", - "sysinfo", - "tar", - "tokio", - "toml", - "tonic", - "tonic-build", - "tracing", - "tracing-core", - "uuid", - "zip", -] - -[[package]] -name = "pact_consumer" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdff329c97c39ffbc78640c83d33cd1d28f2ea8ecb7f0d9e48cbfcce95960b96" -dependencies = [ - "anyhow", - "async-trait", - "bytes 1.10.0", - "futures", - "itertools 0.10.5", - "lazy_static", - "maplit", - "pact-plugin-driver", - "pact_matching", - "pact_mock_server", - "pact_models", - "regex", - "serde_json", - "tokio", - "tracing", - "tracing-core", - "url", - "uuid", -] - -[[package]] -name = "pact_matching" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1385b48819e86b65e6ea094366b4e5da717691993704a8387cf0957fb7301dd" -dependencies = [ - "ansi_term", - "anyhow", - "base64 0.21.7", - "bytes 1.10.0", - "chrono", - "difference", - "futures", - "hex", - "http 0.2.12", - "itertools 0.10.5", - "lazy_static", - "lenient_semver", - "maplit", - "md5", - "mime", - "multer", - "nom 7.1.3", - "onig", - "pact-plugin-driver", - "pact_models", - "rand 0.8.5", - "reqwest", - "semver", - "serde", - "serde_json", - "serde_urlencoded", - "sxd-document", - "tokio", - "tracing", - "tracing-core", - "tree_magic_mini", - "uuid", -] - -[[package]] -name = "pact_mock_server" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb13cec89b68677e5701d4861a24335bf614b103bb9328bbf605276f758c506" -dependencies = [ - "anyhow", - "bytes 1.10.0", - "futures", - "hyper", - "hyper-rustls", - "itertools 0.10.5", - "lazy_static", - "maplit", - "pact-plugin-driver", - "pact_matching", - "pact_models", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-rustls", - "tracing", - "tracing-core", - "url", - "uuid", -] - -[[package]] -name = "pact_models" -version = "1.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac0a22137e661623246c4da170f3123ff9ead87644d1d16ceb6604c5752440" -dependencies = [ - "anyhow", - "ariadne", - "base64 0.21.7", - "bytes 1.10.0", - "chrono", - "chrono-tz", - "fs2", - "gregorian", - "hashers", - "hex", - "indextree", - "itertools 0.10.5", - "lazy_static", - "lenient_semver", - "logos", - "maplit", - "mime", - "nom 7.1.3", - "onig", - "parse-zoneinfo", - "rand 0.8.5", - "rand_regex", - "regex", - "regex-syntax 0.6.29", - "reqwest", - "semver", - "serde", - "serde_json", - "sxd-document", - "tracing", - "uuid", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "parse-zoneinfo" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" -dependencies = [ - "regex", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac", - "password-hash", - "sha2", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "peresil" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" - -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap 2.7.1", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - -[[package]] -name = "pin-project" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "polling" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" -dependencies = [ - "cfg-if 1.0.0", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "portable-atomic" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "predicates" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" -dependencies = [ - "anstyle", - "predicates-core", -] - -[[package]] -name = "predicates-core" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" - -[[package]] -name = "predicates-tree" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro2" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes 1.10.0", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" -dependencies = [ - "bytes 1.10.0", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn 1.0.109", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost", -] - -[[package]] -name = "querystring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9318ead08c799aad12a55a3e78b82e0b6167271ffd1f627b758891282f739187" - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.1", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_regex" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a9fe2d7d9eeaf3279d1780452a5bbd26b31b27938787ef1c3e930d1e9cfbd" -dependencies = [ - "rand 0.8.5", - "regex-syntax 0.6.29", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" -dependencies = [ - "bitflags 2.8.0", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.15", - "libredox", - "thiserror 1.0.69", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "async-compression", - "base64 0.21.7", - "bytes 1.10.0", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body", - "hyper", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-rustls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" -dependencies = [ - "cc", - "cfg-if 1.0.0", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ripple_sdk" -version = "1.1.0" -dependencies = [ - "async-channel 2.3.1", - "async-std", - "async-trait", - "chrono", - "fern", - "futures", - "futures-channel", - "jaq-core", - "jaq-interpret", - "jaq-parse", - "jaq-std", - "jsonrpsee", - "lazy_static", - "libloading", - "log", - "mock_app_gw", - "mockall", - "regex", - "ripple_sdk", - "rstest", - "semver", - "serde", - "serde_json", - "serde_millis", - "serde_yaml", - "testing_logger", - "tokio", - "tree_magic_mini", - "uuid", -] - -[[package]] -name = "ripple_tdk" -version = "1.1.0" -dependencies = [ - "ripple_sdk", - "serde_json", -] - -[[package]] -name = "rpc_extn" -version = "1.1.0" -dependencies = [ - "jsonrpsee", - "ripple_sdk", - "serde", - "serde_json", -] - -[[package]] -name = "rstest" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" -dependencies = [ - "cfg-if 1.0.0", - "glob", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.98", - "unicode-ident", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.8.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" - -[[package]] -name = "ryu" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scc" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" -dependencies = [ - "sdd", -] - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sd-notify" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b943eadf71d8b69e661330cb0e2656e31040acf21ee7708e2c238a0ec6af2bf4" -dependencies = [ - "libc", -] - -[[package]] -name = "sdd" -version = "3.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.8.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_millis" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e2dc780ca5ee2c369d1d01d100270203c4ff923d2a4264812d723766434d00" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_regex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" -dependencies = [ - "regex", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.7.1", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "serial_test" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" -dependencies = [ - "futures", - "log", - "once_cell", - "parking_lot", - "scc", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.1", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "similar" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "socket2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.1", - "bytes 1.10.0", - "futures", - "http 0.2.12", - "httparse", - "log", - "rand 0.8.5", - "sha-1 0.9.8", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "ssda_client" -version = "0.1.0" -dependencies = [ - "async-trait", - "log", - "serde", - "serde_json", - "ssda_types", - "tokio", - "tokio-tungstenite 0.20.1", - "tungstenite 0.26.2", - "url", - "ws", -] - -[[package]] -name = "ssda_service" -version = "0.1.0" -dependencies = [ - "async-trait", - "futures-util", - "http 0.2.12", - "log", - "mockall", - "ripple_sdk", - "serde_json", - "ssda_client", - "ssda_types", - "tokio", - "tokio-tungstenite 0.20.1", - "url", - "uuid", -] - -[[package]] -name = "ssda_types" -version = "0.1.0" -dependencies = [ - "async-trait", - "futures-util", - "http 0.2.12", - "jsonrpsee", - "mockall", - "ripple_sdk", - "serde", - "serde_json", - "stream-tungstenite", - "tokio", - "tokio-tungstenite 0.20.1", - "tokio-websockets", - "url", - "uuid", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stream-tungstenite" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a1faabcaf0ade00ed119bec2bbde8a1b687ee67f608ac51d6a19ca730285cb" -dependencies = [ - "async-trait", - "eyre", - "futures", - "futures-util", - "rand 0.9.1", - "thiserror 2.0.12", - "tokio", - "tokio-stream", - "tokio-tungstenite 0.26.2", - "tracing", - "tungstenite 0.26.2", -] - -[[package]] -name = "string_cache" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" -dependencies = [ - "new_debug_unreachable", - "parking_lot", - "phf_shared", - "precomputed-hash", -] - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.98", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "sxd-document" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078" -dependencies = [ - "peresil", - "typed-arena", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "sysinfo" -version = "0.29.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" -dependencies = [ - "cfg-if 1.0.0", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi 0.3.9", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tar" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tempfile" -version = "3.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "getrandom 0.3.1", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi 0.3.9", -] - -[[package]] -name = "termtree" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" - -[[package]] -name = "test-log" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f0c854faeb68a048f0f2dc410c5ddae3bf83854ef0e4977d58306a5edef50e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "testing_logger" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d92b727cb45d33ae956f7f46b966b25f1bc712092aeef9dba5ac798fc89f720" -dependencies = [ - "log", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "thunder" -version = "1.1.0" -dependencies = [ - "serde", - "thunder_ripple_sdk", -] - -[[package]] -name = "thunder_ripple_sdk" -version = "1.1.0" -dependencies = [ - "base64 0.22.1", - "csv", - "expectest", - "futures", - "futures-channel", - "futures-util", - "home", - "jsonrpsee", - "maplit", - "pact_consumer", - "regex", - "reqwest", - "ripple_sdk", - "ripple_tdk", - "rstest", - "serde", - "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", - "test-log", - "tokio-tungstenite 0.20.1", - "tree_magic_mini", - "url", -] - -[[package]] -name = "time" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tm_extn" -version = "1.1.0" -dependencies = [ - "ripple_sdk", - "serde", - "serde_json", - "tokio-tungstenite 0.20.1", - "url", -] - -[[package]] -name = "tokio" -version = "1.44.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" -dependencies = [ - "backtrace", - "bytes 1.10.0", - "libc", - "mio 1.0.3", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.8", - "tokio-macros", - "windows-sys 0.52.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.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[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-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.20.1", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.26.2", -] - -[[package]] -name = "tokio-util" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" -dependencies = [ - "bytes 1.10.0", - "futures-core", - "futures-io", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-websockets" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fcaf159b4e7a376b05b5bfd77bfd38f3324f5fce751b4213bfc7eaa47affb4e" -dependencies = [ - "base64 0.22.1", - "bytes 1.10.0", - "futures-core", - "futures-sink", - "http 1.3.1", - "httparse", - "openssl", - "rand 0.9.1", - "simdutf8", - "tokio", - "tokio-util", -] - -[[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.24", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.7.1", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" -dependencies = [ - "indexmap 2.7.1", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.7.3", -] - -[[package]] -name = "tonic" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" -dependencies = [ - "async-trait", - "axum", - "base64 0.21.7", - "bytes 1.10.0", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "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.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "quote", - "syn 1.0.109", -] - -[[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 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tree_magic_mini" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91adfd0607cacf6e4babdb870e9bec4037c1c4b151cfd279ccefc5e0c7feaa6d" -dependencies = [ - "bytecount", - "fnv", - "lazy_static", - "nom 7.1.3", - "once_cell", - "petgraph", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes 1.10.0", - "data-encoding", - "http 0.2.12", - "httparse", - "log", - "native-tls", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" -dependencies = [ - "bytes 1.10.0", - "data-encoding", - "http 1.3.1", - "httparse", - "log", - "native-tls", - "rand 0.9.1", - "sha1", - "thiserror 2.0.12", - "utf-8", -] - -[[package]] -name = "typed-arena" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicode-ident" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" -dependencies = [ - "getrandom 0.3.1", - "serde", - "sha1_smol", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "value-bag" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vergen" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b909197472c3dd2f369ee49659c5b9499b9465aebcf11239814d1bae149bd3" -dependencies = [ - "bitflags 1.3.2", - "chrono", - "error-chain", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.98", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags 2.8.0", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "ws" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "httparse", - "log", - "mio 0.6.23", - "mio-extras", - "rand 0.7.3", - "sha-1 0.8.2", - "slab", - "url", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "xattr" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", - "synstructure", ] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -11132,13 +5578,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.101", ] [[package]] @@ -11182,9 +5628,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 7bfa7c7bf..2451dfb84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ members = [ version = "1.1.0" [workspace.dependencies] +base64ct= {version = "=1.7.3"} base64 = { version = "0.22.1", default-features = false, features=["alloc"] } chrono = { version = "0.4", default-features = false, features = ["clock"] } futures = { version = "0.3.21", default-features = false } diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 8f8e7a375..0df6cc57f 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -1546,7 +1546,8 @@ impl BrokerOutputForwarder { ) .await; } else { - return_extn_response(message, extn_message) + let client = platform_state.get_client().get_extn_client(); + return_extn_response(message, extn_message, client); } } } else if let Some(session) = platform_state diff --git a/core/main/src/broker/http_broker.rs b/core/main/src/broker/http_broker.rs index 11d1637ff..e0ead7a75 100644 --- a/core/main/src/broker/http_broker.rs +++ b/core/main/src/broker/http_broker.rs @@ -19,7 +19,11 @@ use std::vec; use hyper::{client::HttpConnector, Body, Client, Method, Request, Response, Uri}; use ripple_sdk::{ - api::{gateway::rpc_gateway_api::JsonRpcApiError, observability::log_signal::LogSignal}, + api::{ + gateway::rpc_gateway_api::JsonRpcApiError, + observability::log_signal::LogSignal, + rules_engine::{jq_compile, RuleTransformType}, + }, log::{debug, error}, tokio::{self, sync::mpsc}, utils::error::RippleError, @@ -31,10 +35,7 @@ use super::endpoint_broker::{ BrokerSender, EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, }; -use crate::{ - broker::rules::rules_engine::{jq_compile, RuleTransformType}, - state::platform_state::PlatformState, -}; +use crate::state::platform_state::PlatformState; use ripple_sdk::tokio_tungstenite::tungstenite::http::uri::InvalidUri; @@ -225,10 +226,7 @@ mod tests { use serde_json::{json, Value}; use std::time::Duration; - use crate::broker::{ - endpoint_broker::BrokerOutput, - rules::rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol}, - }; + use crate::broker::endpoint_broker::BrokerOutput; use super::*; diff --git a/core/main/src/broker/test/mock_thunder_lite_server.rs b/core/main/src/broker/test/mock_thunder_lite_server.rs index 3a5089012..84802ea49 100644 --- a/core/main/src/broker/test/mock_thunder_lite_server.rs +++ b/core/main/src/broker/test/mock_thunder_lite_server.rs @@ -15,7 +15,6 @@ use std::collections::HashMap; use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; -use tokio_tungstenite::{accept_async, tungstenite::protocol::Message}; use ripple_sdk::api::gateway::rpc_gateway_api::{JsonRpcApiRequest, JsonRpcApiResponse}; diff --git a/core/main/src/broker/thunder_broker.rs b/core/main/src/broker/thunder_broker.rs index 9e0ddc34b..d1e883620 100644 --- a/core/main/src/broker/thunder_broker.rs +++ b/core/main/src/broker/thunder_broker.rs @@ -23,7 +23,7 @@ use super::{ thunder::thunder_plugins_status_mgr::StatusManager, thunder::user_data_migrator::UserDataMigrator, }; -use crate::{broker::broker_utils::BrokerUtils, state::platform_state::PlatformState}; +use crate::state::platform_state::PlatformState; use futures_util::{SinkExt, StreamExt}; use ripple_sdk::{ api::{ @@ -685,14 +685,13 @@ impl EndpointBroker for ThunderBroker { #[cfg(test)] mod tests { use super::*; - use crate::broker::thunder_broker::tests::rules_engine::RuleTransformType; + use crate::{ broker::{ endpoint_broker::{ apply_response, apply_rule_for_event, BrokerCallback, BrokerConnectRequest, BrokerOutput, BrokerRequest, EndpointBroker, }, - rules::rules_engine::{self, Rule, RuleEndpoint, RuleEndpointProtocol, RuleTransform}, test::mock_thunder_lite_server::MockThunderLiteServer, }, create_and_send_broker_request, create_and_send_broker_request_with_jq_transform, @@ -807,7 +806,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let (tx, _) = mpsc::channel(1); diff --git a/core/main/src/broker/websocket_broker.rs b/core/main/src/broker/websocket_broker.rs index 7e7c0131c..8442dd60b 100644 --- a/core/main/src/broker/websocket_broker.rs +++ b/core/main/src/broker/websocket_broker.rs @@ -15,8 +15,6 @@ // SPDX-License-Identifier: Apache-2.0 // -use crate::broker::broker_utils::BrokerUtils; - use super::endpoint_broker::{ BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerOutputForwarder, BrokerRequest, BrokerSender, EndpointBroker, @@ -253,9 +251,12 @@ mod tests { broker::endpoint_broker::{BrokerOutput, BrokerRequest}, utils::test_utils::{MockWebsocket, WSMockData}, }; - use ripple_sdk::api::{ - gateway::rpc_gateway_api::RpcRequest, - rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol, RuleTransform}, + use ripple_sdk::{ + api::{ + gateway::rpc_gateway_api::RpcRequest, + rules_engine::{Rule, RuleEndpoint, RuleEndpointProtocol, RuleTransform}, + }, + utils::logger::init_logger, }; use serde_json::json; @@ -278,7 +279,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let (tx, _) = mpsc::channel(1); @@ -415,7 +416,7 @@ mod tests { let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; @@ -515,7 +516,7 @@ mod tests { let port: u32 = 34743; let endpoint = RuleEndpoint { url: format!("ws://127.0.0.1:{}", port), - protocol: crate::broker::rules::rules_engine::RuleEndpointProtocol::Websocket, + protocol: RuleEndpointProtocol::Websocket, jsonrpc: false, }; let _ = WSNotificationBroker::start(request, callback, endpoint.get_url().clone()); diff --git a/core/main/src/broker/workflow_broker.rs b/core/main/src/broker/workflow_broker.rs index d4a21f4ed..4f9776ab4 100644 --- a/core/main/src/broker/workflow_broker.rs +++ b/core/main/src/broker/workflow_broker.rs @@ -2,9 +2,8 @@ use super::endpoint_broker::{ BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerRequest, BrokerSender, EndpointBroker, HandleBrokerageError, BROKER_CHANNEL_BUFFER_SIZE, }; -use super::rules::rules_engine::JsonDataSource; + use crate::broker::endpoint_broker::{BrokerOutput, EndpointBrokerState}; -use crate::broker::rules::rules_engine::{compose_json_values, make_name_json_safe}; use crate::state::platform_state::PlatformState; use futures::future::{join_all, BoxFuture}; use futures::FutureExt; @@ -56,16 +55,18 @@ async fn subbroker_call( source: JsonDataSource, ) -> Result { let (brokered_tx, mut brokered_rx) = mpsc::channel::(BROKER_CHANNEL_BUFFER_SIZE); - endpoint_broker.handle_brokerage( - rpc_request, - None, - Some(BrokerCallback { - sender: brokered_tx, - }), - Vec::new(), - None, - vec![], - ); + let _ = endpoint_broker + .handle_brokerage( + rpc_request, + None, + Some(BrokerCallback { + sender: brokered_tx, + }), + Vec::new(), + None, + vec![], + ) + .await; match brokered_rx.recv().await { Some(msg) => { @@ -317,10 +318,7 @@ pub mod tests { }; use serde_json::json; - use crate::broker::{ - endpoint_broker::{BrokerCallback, BrokerRequest, EndpointBrokerState}, - rules::rules_engine::{JsonDataSource, Rule, RuleEngine}, - }; + use crate::broker::endpoint_broker::{BrokerCallback, BrokerRequest, EndpointBrokerState}; pub fn broker_request(callback: BrokerCallback) -> BrokerRequest { let mut rule = Rule { alias: "module.method".to_string(), diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index ecc1245b9..d3a842965 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -38,6 +38,7 @@ use ripple_sdk::{ extn_id::ExtnId, }, framework::ripple_contract::RippleContract, + log::trace, tokio_tungstenite::{ tungstenite::{self, Message}, WebSocketStream, @@ -63,10 +64,7 @@ use ripple_sdk::{log::debug, tokio}; use ssda_service::ApiGateway; use ssda_types::gateway::{APIGatewayServiceConnectionDisposition, ApiGatewayServer}; use ssda_types::ServiceId; -use tokio_tungstenite::{ - tungstenite::{self, Message}, - WebSocketStream, -}; + #[allow(dead_code)] pub struct FireboltWs {} @@ -87,8 +85,19 @@ struct ConnectionCallbackConfig { pub app_state: AppManagerState, pub secure: bool, pub internal_app_id: Option, + pub extns: Vec, pub service_connection: Arc>>, } +impl ConnectionCallbackConfig { + fn get_extn(&self, id: &str) -> Option { + for extn in &self.extns { + if extn.id.eq(id) { + return Some(extn.clone()); + } + } + None + } +} pub struct ConnectionCallback(ConnectionCallbackConfig); /** @@ -263,6 +272,7 @@ impl FireboltWs { secure, internal_app_id: internal_app_id.clone(), extns: extns.clone(), + service_connection: service_connection_state.clone(), }; match ripple_sdk::tokio_tungstenite::accept_hdr_async(stream, ConnectionCallback(cfg)) .await diff --git a/core/main/src/state/bootstrap_state.rs b/core/main/src/state/bootstrap_state.rs index cfb292615..db0f2b00b 100644 --- a/core/main/src/state/bootstrap_state.rs +++ b/core/main/src/state/bootstrap_state.rs @@ -23,8 +23,8 @@ use ripple_sdk::{ manifest::ripple_manifest_loader::RippleManifestLoader, rules_engine::{RuleEngine, RuleEngineProvider}, }, - async_channel::{unbounded, Receiver as CReceiver, Sender as CSender}, - extn::ffi::ffi_message::CExtnMessage, + // async_channel::{unbounded, Receiver as CReceiver, Sender as CSender}, + // extn::ffi::ffi_message::CExtnMessage, framework::bootstrap::TransientChannel, log::{error, info, warn}, tokio::{ @@ -36,13 +36,12 @@ use ripple_sdk::{ use ssda_types::gateway::ApiGatewayServer; use crate::{ - bootstrap::manifest::apps::LoadAppLibraryStep, - broker::endpoint_broker::{BrokerOutput, BROKER_CHANNEL_BUFFER_SIZE}, - firebolt::firebolt_gateway::FireboltGatewayCommand, - service::extn::ripple_client::RippleClient, + bootstrap::manifest::apps::LoadAppLibraryStep, broker::endpoint_broker::BrokerOutput, + firebolt::firebolt_gateway::FireboltGatewayCommand, service::extn::ripple_client::RippleClient, + state::platform_state::PlatformState, }; -use super::{extn_state::ExtnState, platform_state::PlatformState}; +//use super::{extn_state::ExtnState, platform_state::PlatformState}; use env_file_reader::read_file; #[derive(Debug, Clone)] @@ -112,7 +111,6 @@ impl BootstrapState { return Err(RippleError::BootstrapError); }; let app_manifest_result = LoadAppLibraryStep::load_app_library(); - let extn_state = ExtnState::new(channels_state.clone(), extn_manifest.clone()); let rules_engine: Arc>> = Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( &extn_manifest, diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index 41a32194d..a300d078d 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -106,7 +106,7 @@ impl From for DeviceSessionIdentifier { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct PlatformState { pub extn_manifest: ExtnManifest, device_manifest: DeviceManifest, @@ -261,7 +261,7 @@ impl PlatformState { #[cfg(test)] mod tests { use super::*; - use ripple_sdk::api::manifest::extn_manifest::default_providers; + use ripple_sdk::api::{manifest::extn_manifest::default_providers, rules_engine::RuleEngine}; use ripple_tdk::utils::test_utils::Mockable; impl Mockable for PlatformState { diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index afeb70492..220fe5fce 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -41,24 +41,14 @@ use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val}; use std::{fs, path::Path}; -use super::rules_functions::{apply_functions, RulesFunction, RulesImport}; - #[derive(Debug, Deserialize, Default, Clone)] pub struct RuleSet { - #[serde(default)] - pub imports: Vec, pub endpoints: HashMap, pub rules: HashMap, } impl RuleSet { pub fn append(&mut self, rule_set: RuleSet) { - for import in rule_set.imports { - if !self.imports.contains(&import) { - self.imports.push(import); - } - } - self.endpoints.extend(rule_set.endpoints); let rules: HashMap = rule_set .rules @@ -149,6 +139,10 @@ pub enum RuleType { Endpoint, } impl Rule { + fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { + self.transform.apply_context(rpc_request); + self + } pub fn rule_type(&self) -> RuleType { match self.alias.trim().to_ascii_lowercase().as_str() { "static" => RuleType::Static, @@ -224,33 +218,13 @@ impl RuleTransform { output } - pub fn apply_functions(&mut self, imports: &HashMap) { - if let Some(transform) = self.request.take() { - if let Ok(transformed) = apply_functions(&transform, imports) { - let _ = self.request.insert(transformed); - } - } - - if let Some(transform) = self.response.take() { - if let Ok(transformed) = apply_functions(&transform, imports) { - let _ = self.response.insert(transformed); - } - } - } - - pub fn apply_variables(&mut self, rpc_request: &RpcRequest) -> &mut Self { + pub fn apply_context(&mut self, rpc_request: &RpcRequest) -> &mut Self { if let Some(value) = self.request.take() { let _ = self .request .insert(self.check_and_replace(&value, rpc_request)); } - if let Some(value) = self.response.take() { - let _ = self - .response - .insert(self.check_and_replace(&value, rpc_request)); - } - if let Some(value) = self.event.take() { let _ = self .event @@ -289,7 +263,6 @@ pub enum RuleTransformType { #[derive(Debug, Clone, Default)] pub struct RuleEngine { pub rules: RuleSet, - pub functions: HashMap, } impl RuleEngine { @@ -330,7 +303,7 @@ impl RuleEngine { info!("loading rules from path {}", path); info!("loading rule {}", path_for_rule); if let Ok((_, rule_set)) = Self::load_from_content(contents) { - engine.add_rules(rule_set, &extn_manifest.default_path); + engine.rules.append(rule_set) } else { warn!("invalid rule found in path {}", path) } @@ -344,37 +317,6 @@ impl RuleEngine { engine } - fn load_imports(&mut self, imports: &Vec, default_path: &str) { - for import in imports { - let path_to_import = Self::build_path(import, default_path); - match fs::read_to_string(&path_to_import) { - Ok(import_contents) => { - match serde_json::from_str::(&import_contents) { - Ok(import) => { - for (function_name, function) in import.functions { - // Last loaded import file will overwrite any pre-exsting functions to allow overriding. - self.functions - .insert(function_name.clone(), function.clone()); - } - } - Err(e) => { - error!( - "load_imports: Invalid import: path_to_import={}, e={:?}", - path_to_import, e - ) - } - } - } - Err(e) => { - error!( - "load_imports: Invalid path: path_to_import={}, e={:?}", - path_to_import, e - ); - } - } - } - } - pub fn load_from_content(contents: String) -> Result<(String, RuleSet), RippleError> { match serde_json::from_str::(&contents) { Ok(manifest) => Ok((contents, manifest)), @@ -384,9 +326,8 @@ impl RuleEngine { } } } - pub fn add_rules(&mut self, rules: RuleSet, default_path: &str) { - self.rules.append(rules.clone()); - self.load_imports(&rules.imports, default_path); + pub fn add_rules(&mut self, rules: RuleSet) { + self.rules.append(rules); } pub fn add_rule(&mut self, rule: Rule) { self.rules.rules.insert(rule.alias.clone(), rule); @@ -415,32 +356,19 @@ impl RuleEngine { } } -<<<<<<<< HEAD:core/sdk/src/api/rules_engine/mod.rs pub fn retrieve_rule( &self, rpc_request: &RpcRequest, ) -> Result { -======== - fn apply_functions(&self, rule: &mut Rule) { - rule.transform.apply_functions(&self.functions); - } - - fn apply_variables(&self, rule: &mut Rule, rpc_request: &RpcRequest) { - rule.transform.apply_variables(rpc_request); - } - - pub fn get_rule(&self, rpc_request: &RpcRequest) -> Result { ->>>>>>>> 188f56be833a3b7cb390e7c3f9fcb57605ec8a7c:core/main/src/broker/rules/rules_engine.rs let method = rpc_request.method.to_lowercase(); - /* match directly from method name */ if let Some(mut rule) = self.rules.get(&method).cloned() { - self.apply_functions(&mut rule); - self.apply_variables(&mut rule, rpc_request); - Ok(RuleRetrieved::ExactMatch(rule.to_owned())) + return Ok(RuleRetrieved::ExactMatch( + rule.apply_context(rpc_request).to_owned(), + )); } else { /* * match, for example api.v1.* as rule name and api.v1.get as method name @@ -760,10 +688,7 @@ mod tests { .rules .insert("test.method".to_string(), rule.clone()); - let rule_engine = RuleEngine { - rules: rule_set, - functions: HashMap::default(), - }; + let rule_engine = RuleEngine { rules: rule_set }; let rpc_request = RpcRequest { method: "test.method".to_string(), @@ -793,10 +718,7 @@ mod tests { }; rule_set.rules.insert("api.v1.*".to_string(), rule.clone()); - let rule_engine = RuleEngine { - rules: rule_set, - functions: HashMap::default(), - }; + let rule_engine = RuleEngine { rules: rule_set }; let rpc_request = RpcRequest { method: "api.v1.get".to_string(), @@ -820,10 +742,7 @@ mod tests { #[test] fn test_get_rule_no_match() { let rule_set = RuleSet::default(); - let rule_engine = RuleEngine { - rules: rule_set, - functions: HashMap::default(), - }; + let rule_engine = RuleEngine { rules: rule_set }; let rpc_request = RpcRequest { method: "nonexistent.method".to_string(), diff --git a/device/thunder_ripple_sdk/Cargo.toml b/device/thunder_ripple_sdk/Cargo.toml index 82c062c78..171940856 100644 --- a/device/thunder_ripple_sdk/Cargo.toml +++ b/device/thunder_ripple_sdk/Cargo.toml @@ -57,6 +57,7 @@ mock=[] [dependencies] base64 = { workspace = true, default-features = false, features=["alloc"] } +base64ct = {version = "=1.7.3"} ripple_tdk = { path = "../../core/tdk" } ripple_sdk.workspace = true regex.workspace = true @@ -69,7 +70,7 @@ futures.workspace = true strum = { version = "0.24", default-features = false } strum_macros = "0.24" -pact_consumer = { version = "1.0.0", optional = true } +pact_consumer = { version = "=1.0.0", optional = true } reqwest = { version = "0.11", optional = true, default-features = false } expectest = { version = "0.12.0", optional = true } maplit = { version = "1.0.2", optional = true } @@ -83,4 +84,4 @@ futures-util = { version = "0.3.28", features = ["sink", "std"], default-feature [dev-dependencies] ripple_sdk = { path = "../../core/sdk", features = ["tdk"] } -rstest = "0.18.2" \ No newline at end of file +rstest = "0.18.2" diff --git a/examples/tm_extn/src/tm_ffi.rs b/examples/tm_extn/src/tm_ffi.rs index 9a27b0fde..1e20f023a 100644 --- a/examples/tm_extn/src/tm_ffi.rs +++ b/examples/tm_extn/src/tm_ffi.rs @@ -61,7 +61,7 @@ export_extn_metadata!(CExtnMetadata, init_library); fn start_launcher(sender: ExtnSender, receiver: CReceiver) { let _ = init_logger("tm".into()); info!("Starting tm channel"); - let mut client = ExtnClient::new(receiver, sender); + let mut client = ExtnClient::new_extn(receiver); if !client.check_contract_permitted(RippleContract::OperationalMetricListener) { let _ = client.event(ExtnStatus::Error); diff --git a/ssda/example-service/src/main.rs b/ssda/example-service/src/main.rs index 3fcfc25c6..fc2ab6ef2 100644 --- a/ssda/example-service/src/main.rs +++ b/ssda/example-service/src/main.rs @@ -12,9 +12,10 @@ use ssda_types::{JqRule, ServiceId}; pub struct ExampleService {} impl ExampleService { - pub fn new() -> Self {let dm_arr = vec![load_from_etc]; - - + pub fn new() -> Self { + Self {} + } +} #[async_trait::async_trait] impl ServiceRequestHandlerImpl for ExampleService { fn register(&self) -> Vec { From 5a15a998e0e36b27cfaacc8f6702524d422a2dcf Mon Sep 17 00:00:00 2001 From: bobra200 Date: Fri, 13 Jun 2025 13:41:52 -0700 Subject: [PATCH 18/46] feat: ripple_sdk as standalone crate --- core/sdk/Cargo.toml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/sdk/Cargo.toml b/core/sdk/Cargo.toml index b5fe656a3..98701a9d7 100644 --- a/core/sdk/Cargo.toml +++ b/core/sdk/Cargo.toml @@ -22,7 +22,7 @@ repository = "https://github.com/rdkcentral/Ripple" [features] local_dev = ["jsonrpsee"] -default = [] +default = ["jsonrpsee"] rpc = ["jsonrpsee"] tdk = [] full = ["rpc"] @@ -44,8 +44,7 @@ contract_tests = [ #dependencies inherited from workspace futures-channel.workspace = true -serde.workspace = true -serde_json.workspace = true + chrono.workspace = true tokio = { workspace = true, features = [ "macros", @@ -55,7 +54,7 @@ tokio = { workspace = true, features = [ "time", ] } futures.workspace = true -jsonrpsee = { workspace = true, features=["server"], optional = true } + regex.workspace = true uuid = { workspace = true, features = ["serde", "v5", "v4"] } @@ -78,6 +77,9 @@ jaq-parse = { version = "1.0.2", default-features = false } jaq-core = "1.5.0" jaq-std = { version = "1.5.1", default-features = false } mockall = "0.13.1" +jsonrpsee = { version = "=0.16.3", default-features = false,features = ["macros", "jsonrpsee-core","server"] ,optional = true } +serde_json = { version = "1.0", default-features = false} +serde = { version = "1.0", features = ["derive"], default-features = false } [dev-dependencies] ripple_sdk = { path = ".", features=["tdk"]} From 8a474dcec0dffa058e89baf95eb7c7ad3a9d6b39 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Sat, 14 Jun 2025 07:20:31 -0700 Subject: [PATCH 19/46] chore: export jsonrpsee --- core/sdk/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sdk/src/lib.rs b/core/sdk/src/lib.rs index 6d475476b..cbad1f597 100644 --- a/core/sdk/src/lib.rs +++ b/core/sdk/src/lib.rs @@ -28,6 +28,7 @@ pub mod utils; pub extern crate async_trait; pub extern crate chrono; pub extern crate futures; +pub extern crate jsonrpsee; pub extern crate libloading; pub extern crate log; pub extern crate semver; From 9ff3f5f6bc94b88ae869d39d6b86f101020e9849 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 16 Jun 2025 08:29:46 -0700 Subject: [PATCH 20/46] latest --- core/sdk/Cargo.toml | 2 ++ core/sdk/src/lib.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/sdk/Cargo.toml b/core/sdk/Cargo.toml index 98701a9d7..36b72c9c3 100644 --- a/core/sdk/Cargo.toml +++ b/core/sdk/Cargo.toml @@ -24,12 +24,14 @@ repository = "https://github.com/rdkcentral/Ripple" local_dev = ["jsonrpsee"] default = ["jsonrpsee"] rpc = ["jsonrpsee"] +jsonrpsee-server = ["jsonrpsee"] tdk = [] full = ["rpc"] sysd = [] test = ["jsonrpsee", "mock"] mock_service = ["mock_app_gw/mock_service"] mock = [] +sdk = ["jsonrpsee-server"] http_contract_tests = [ ] diff --git a/core/sdk/src/lib.rs b/core/sdk/src/lib.rs index cbad1f597..03114586a 100644 --- a/core/sdk/src/lib.rs +++ b/core/sdk/src/lib.rs @@ -42,6 +42,8 @@ pub extern crate uuid; pub trait Mockable { fn mock() -> Self; } +#[cfg(feature = "jsonrpsee-server")] +pub use jsonrpsee; pub type JsonRpcErrorType = jsonrpsee::core::error::Error; pub type JsonRpcErrorCode = jsonrpsee::types::error::ErrorCode; From 7c594aa0563a4db945a97622617a268356ac1af3 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 16 Jun 2025 08:34:14 -0700 Subject: [PATCH 21/46] iteration --- core/sdk/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/sdk/src/lib.rs b/core/sdk/src/lib.rs index 03114586a..bfe4836bc 100644 --- a/core/sdk/src/lib.rs +++ b/core/sdk/src/lib.rs @@ -28,7 +28,6 @@ pub mod utils; pub extern crate async_trait; pub extern crate chrono; pub extern crate futures; -pub extern crate jsonrpsee; pub extern crate libloading; pub extern crate log; pub extern crate semver; From c9ad9094ca654cbde8a5c3c31e38081675f82ef3 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Fri, 20 Jun 2025 06:44:37 -0700 Subject: [PATCH 22/46] checkpoint --- Cargo.lock | 1326 +++++++++---------- core/main/Cargo.toml | 11 +- core/sdk/src/api/gateway/rpc_gateway_api.rs | 20 + ssda/example-service/src/main.rs | 84 -- ssda/ssda_client/src/lib.rs | 50 - ssda/ssda_service/src/lib.rs | 720 ---------- ssda/ssda_tranports/src/main.rs | 3 - ssda/ssda_types/src/api_gateway_client.rs | 1 - ssda/ssda_types/src/api_gateway_server.rs | 1 - ssda/ssda_types/src/lib.rs | 755 ----------- ssda/ssda_types/src/service_api.rs | 1 - 11 files changed, 655 insertions(+), 2317 deletions(-) delete mode 100644 ssda/example-service/src/main.rs delete mode 100644 ssda/ssda_client/src/lib.rs delete mode 100644 ssda/ssda_service/src/lib.rs delete mode 100644 ssda/ssda_tranports/src/main.rs delete mode 100644 ssda/ssda_types/src/api_gateway_client.rs delete mode 100644 ssda/ssda_types/src/api_gateway_server.rs delete mode 100644 ssda/ssda_types/src/lib.rs delete mode 100644 ssda/ssda_types/src/service_api.rs diff --git a/Cargo.lock b/Cargo.lock index 072ca3e7a..a7f220abb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" @@ -23,7 +23,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", ] @@ -34,7 +34,7 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.3.3", "once_cell", "serde", @@ -51,6 +51,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -78,7 +87,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -163,9 +172,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.24" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" +checksum = "40f6024f3f856663b45fd0c9b6f2024034a702f453549449e0d84a305900dad4" dependencies = [ "flate2", "futures-core", @@ -210,7 +219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock 3.4.0", - "cfg-if 1.0.0", + "cfg-if", "concurrent-queue", "futures-io", "futures-lite", @@ -263,7 +272,7 @@ dependencies = [ "async-signal", "async-task", "blocking", - "cfg-if 1.0.0", + "cfg-if", "event-listener 5.4.0", "futures-lite", "rustix 1.0.7", @@ -279,7 +288,7 @@ dependencies = [ "async-io", "async-lock 3.4.0", "atomic-waker", - "cfg-if 1.0.0", + "cfg-if", "futures-core", "futures-io", "rustix 1.0.7", @@ -330,7 +339,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -354,11 +363,11 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes 1.10.1", + "bytes", "futures-util", "http 0.2.12", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.27", "itoa", "matchit", "memchr", @@ -380,10 +389,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes 1.10.1", + "bytes", "futures-util", "http 0.2.12", - "http-body", + "http-body 0.4.6", "mime", "rustversion", "tower-layer", @@ -397,7 +406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -476,25 +485,13 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -503,16 +500,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -544,12 +532,6 @@ version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytecount" version = "0.6.9" @@ -557,20 +539,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] -name = "byteorder" -version = "1.5.0" +name = "bytemuck" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] -name = "bytes" -version = "0.4.12" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -603,9 +581,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.26" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "jobserver", "libc", @@ -614,15 +592,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" @@ -717,7 +689,7 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.0", + "unicode-width 0.2.1", "windows-sys 0.59.0", ] @@ -743,6 +715,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpp_demangle" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +dependencies = [ + "cfg-if", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -758,7 +739,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -798,7 +779,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array", "typenum", ] @@ -829,6 +810,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + [[package]] name = "deranged" version = "0.4.0" @@ -844,22 +834,13 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -879,7 +860,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -891,7 +872,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -902,7 +883,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -944,7 +925,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -956,6 +937,26 @@ dependencies = [ "regex", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1024,22 +1025,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fancy-regex" version = "0.11.0" @@ -1071,12 +1056,24 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "libredox", "windows-sys 0.59.0", ] +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1099,21 +1096,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.2.1" @@ -1146,25 +1128,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.9", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", + "winapi", ] -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "futures" version = "0.3.31" @@ -1234,7 +1200,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -1282,15 +1248,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1301,27 +1258,16 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1331,7 +1277,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", @@ -1389,7 +1335,7 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes 1.10.1", + "bytes", "fnv", "futures-core", "futures-sink", @@ -1402,6 +1348,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap 2.9.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1447,9 +1412,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1487,7 +1452,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.10.1", + "bytes", "fnv", "itoa", ] @@ -1498,7 +1463,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes 1.10.1", + "bytes", "fnv", "itoa", ] @@ -1509,11 +1474,34 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.10.1", + "bytes", "http 0.2.12", "pin-project-lite", ] +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.10.1" @@ -1541,7 +1529,7 @@ dependencies = [ "crossbeam-utils", "form_urlencoded", "futures-util", - "hyper", + "hyper 0.14.27", "lazy_static", "levenshtein", "log", @@ -1560,13 +1548,13 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes 1.10.1", + "bytes", "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", - "http-body", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1578,6 +1566,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.10", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1586,7 +1594,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper", + "hyper 0.14.27", "log", "rustls", "rustls-native-certs", @@ -1600,12 +1608,28 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.27", "pin-project-lite", "tokio", "tokio-io-timeout", ] +[[package]] +name = "hyper-util" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -1737,12 +1761,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - [[package]] name = "indexmap" version = "1.9.3" @@ -1783,7 +1801,7 @@ dependencies = [ "proc-macro2", "quote", "strum 0.27.1", - "syn 2.0.101", + "syn 2.0.103", "thiserror 2.0.12", ] @@ -1796,26 +1814,35 @@ dependencies = [ "console", "number_prefix", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width 0.2.1", "web-time", ] [[package]] -name = "inout" -version = "0.1.4" +name = "inferno" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ - "generic-array 0.14.7", + "ahash", + "indexmap 2.9.0", + "is-terminal", + "itoa", + "log", + "num-format", + "once_cell", + "quick-xml 0.26.0", + "rgb", + "str_stack", ] [[package]] -name = "iovec" +name = "inout" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "libc", + "generic-array", ] [[package]] @@ -1824,6 +1851,17 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "iso8601" version = "0.6.3" @@ -1961,14 +1999,28 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" dependencies = [ - "jsonrpsee-core", - "jsonrpsee-proc-macros", - "jsonrpsee-server", - "jsonrpsee-types", + "jsonrpsee-core 0.16.3", + "jsonrpsee-proc-macros 0.16.3", + "jsonrpsee-server 0.16.3", + "jsonrpsee-types 0.16.3", "jsonrpsee-ws-client", "tracing", ] +[[package]] +name = "jsonrpsee" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b26c20e2178756451cfeb0661fb74c47dd5988cb7e3939de7e9241fd604d42" +dependencies = [ + "jsonrpsee-core 0.24.9", + "jsonrpsee-proc-macros 0.24.9", + "jsonrpsee-server 0.24.9", + "jsonrpsee-types 0.24.9", + "tokio", + "tracing", +] + [[package]] name = "jsonrpsee-client-transport" version = "0.16.3" @@ -1977,11 +2029,11 @@ checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a" dependencies = [ "futures-util", "http 0.2.12", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.16.3", + "jsonrpsee-types 0.16.3", "pin-project", "rustls-native-certs", - "soketto", + "soketto 0.7.1", "thiserror 1.0.69", "tokio", "tokio-rustls", @@ -2005,14 +2057,37 @@ dependencies = [ "futures-timer", "futures-util", "globset", - "hyper", - "jsonrpsee-types", + "hyper 0.14.27", + "jsonrpsee-types 0.16.3", "parking_lot", - "rand 0.8.5", - "rustc-hash", + "rand", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "soketto 0.7.1", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "jsonrpsee-types 0.24.9", + "parking_lot", + "rand", + "rustc-hash 2.1.1", "serde", "serde_json", - "soketto", "thiserror 1.0.69", "tokio", "tracing", @@ -2025,12 +2100,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" dependencies = [ "heck 0.4.1", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e65763c942dfc9358146571911b0cd1c361c2d63e2d2305622d40d36376ca80" +dependencies = [ + "heck 0.5.0", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "jsonrpsee-server" version = "0.16.3" @@ -2040,12 +2128,39 @@ dependencies = [ "futures-channel", "futures-util", "http 0.2.12", - "hyper", - "jsonrpsee-core", - "jsonrpsee-types", + "hyper 0.14.27", + "jsonrpsee-core 0.16.3", + "jsonrpsee-types 0.16.3", "serde", "serde_json", - "soketto", + "soketto 0.7.1", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55e363146da18e50ad2b51a0a7925fc423137a0b1371af8235b1c231a0647328" +dependencies = [ + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "jsonrpsee-core 0.24.9", + "jsonrpsee-types 0.24.9", + "pin-project", + "route-recognizer", + "serde", + "serde_json", + "soketto 0.8.1", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util", @@ -2067,6 +2182,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-types" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +dependencies = [ + "http 1.3.1", + "serde", + "serde_json", + "thiserror 1.0.69", +] + [[package]] name = "jsonrpsee-ws-client" version = "0.16.3" @@ -2075,8 +2202,8 @@ checksum = "4e1b3975ed5d73f456478681a417128597acd6a2487855fdb7b4a3d4d195bf5e" dependencies = [ "http 0.2.12", "jsonrpsee-client-transport", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.16.3", + "jsonrpsee-types 0.16.3", ] [[package]] @@ -2107,16 +2234,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2163,12 +2280,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lenient_semver" version = "0.4.2" @@ -2206,9 +2317,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libloading" @@ -2216,8 +2327,8 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", + "cfg-if", + "winapi", ] [[package]] @@ -2294,7 +2405,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -2318,18 +2429,18 @@ dependencies = [ "futures-channel", "futures-util", "httpmock", - "hyper", + "hyper 0.14.27", "jaq-core", "jaq-interpret", "jaq-parse", "jaq-std", - "jsonrpsee", + "jsonrpsee 0.16.3", "openrpc_validator", "proc-macro2", "querystring", - "rand 0.8.5", + "rand", "regex", - "ripple_sdk", + "ripple_sdk 1.1.0 (git+https://github.com/rdkcentral/Ripple.git?branch=ssda)", "ripple_tdk", "rstest", "sd-notify", @@ -2364,9 +2475,18 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] [[package]] name = "mime" @@ -2382,32 +2502,13 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "1.0.4" @@ -2415,34 +2516,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio 0.6.23", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "mock_app_gw" version = "0.1.0" @@ -2452,7 +2529,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "uuid", ] @@ -2461,8 +2538,8 @@ name = "mock_device" version = "1.0.0" dependencies = [ "http 0.2.12", - "jsonrpsee", - "ripple_sdk", + "jsonrpsee 0.16.3", + "ripple_sdk 1.1.0", "ripple_tdk", "serde", "serde_json", @@ -2475,7 +2552,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "downcast", "fragile", "mockall_derive", @@ -2489,10 +2566,10 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -2501,7 +2578,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "bytes 1.10.1", + "bytes", "encoding_rs", "futures-util", "http 0.2.12", @@ -2511,7 +2588,7 @@ dependencies = [ "mime", "serde", "serde_json", - "spin", + "spin 0.9.8", "version_check", ] @@ -2522,39 +2599,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] -name = "native-tls" -version = "0.2.14" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "net2" -version = "0.2.39" +name = "nix" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "cfg-if 0.1.10", + "bitflags 1.3.2", + "cfg-if", "libc", - "winapi 0.3.9", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nom" version = "7.1.3" @@ -2580,7 +2640,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2628,6 +2688,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -2711,12 +2781,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opaque-debug" version = "0.3.1" @@ -2733,50 +2797,12 @@ dependencies = [ "serde_json", ] -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.1", - "cfg-if 1.0.0", - "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.101", -] - [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "os_info" version = "3.12.0" @@ -2804,7 +2830,7 @@ dependencies = [ "anyhow", "async-trait", "backtrace", - "bytes 1.10.1", + "bytes", "chrono", "flate2", "futures-util", @@ -2845,7 +2871,7 @@ checksum = "016334b4a70ecb22f448267fd817003f7c09ffda5165aa31e9fe4ede5091aa07" dependencies = [ "anyhow", "async-trait", - "bytes 1.10.1", + "bytes", "futures", "itertools 0.10.5", "lazy_static", @@ -2872,7 +2898,7 @@ dependencies = [ "ansi_term", "anyhow", "base64 0.21.7", - "bytes 1.10.1", + "bytes", "chrono", "difference", "futures", @@ -2889,7 +2915,7 @@ dependencies = [ "onig", "pact-plugin-driver", "pact_models", - "rand 0.8.5", + "rand", "reqwest", "semver", "serde", @@ -2910,9 +2936,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daaea27b75fbc1bf7740562518a77933f8bb2ba5b0d4115f61f52691553fbabd" dependencies = [ "anyhow", - "bytes 1.10.1", + "bytes", "futures", - "hyper", + "hyper 0.14.27", "hyper-rustls", "itertools 0.10.5", "lazy_static", @@ -2942,7 +2968,7 @@ dependencies = [ "anyhow", "ariadne", "base64 0.21.7", - "bytes 1.10.1", + "bytes", "chrono", "chrono-tz", "fs2", @@ -2959,7 +2985,7 @@ dependencies = [ "nom 7.1.3", "onig", "parse-zoneinfo", - "rand 0.8.5", + "rand", "rand_regex", "regex", "regex-syntax 0.6.29", @@ -2994,7 +3020,7 @@ version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -3017,7 +3043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -3081,7 +3107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand", ] [[package]] @@ -3116,7 +3142,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -3150,13 +3176,13 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d" +checksum = "3d77244ce2d584cd84f6a15f86195b8c9b2a0dfbfd817c09e0464244091a58ed" dependencies = [ "base64 0.22.1", "indexmap 2.9.0", - "quick-xml", + "quick-xml 0.37.5", "serde", "time", ] @@ -3167,7 +3193,7 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", @@ -3197,6 +3223,28 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "pprof" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187" +dependencies = [ + "aligned-vec", + "backtrace", + "cfg-if", + "findshlibs", + "inferno", + "libc", + "log", + "nix", + "once_cell", + "smallvec", + "spin 0.10.0", + "symbolic-demangle", + "tempfile", + "thiserror 2.0.12", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -3258,6 +3306,15 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit 0.22.27", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -3273,7 +3330,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes 1.10.1", + "bytes", "prost-derive", ] @@ -3283,7 +3340,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ - "bytes 1.10.1", + "bytes", "heck 0.4.1", "itertools 0.10.5", "lazy_static", @@ -3329,9 +3386,18 @@ checksum = "9318ead08c799aad12a55a3e78b82e0b6167271ffd1f627b758891282f739187" [[package]] name = "quick-xml" -version = "0.32.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" dependencies = [ "memchr", ] @@ -3347,22 +3413,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "rand" -version = "0.7.3" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -3371,28 +3424,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -3402,26 +3435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -3433,31 +3447,13 @@ dependencies = [ "getrandom 0.2.16", ] -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_regex" version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b2a9fe2d7d9eeaf3279d1780452a5bbd26b31b27938787ef1c3e930d1e9cfbd" dependencies = [ - "rand 0.8.5", + "rand", "regex-syntax 0.6.29", ] @@ -3483,9 +3479,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags 2.9.1", ] @@ -3550,14 +3546,14 @@ checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", - "bytes 1.10.1", + "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.27", "hyper-rustls", "ipnet", "js-sys", @@ -3586,6 +3582,15 @@ dependencies = [ "winreg", ] +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.17.14" @@ -3593,7 +3598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.2.16", "libc", "untrusted", @@ -3615,14 +3620,14 @@ dependencies = [ "jaq-interpret", "jaq-parse", "jaq-std", - "jsonrpsee", + "jsonrpsee 0.16.3", "lazy_static", "libloading", "log", "mock_app_gw", "mockall", "regex", - "ripple_sdk", + "ripple_sdk 1.1.0", "rstest", "semver", "serde", @@ -3631,20 +3636,58 @@ dependencies = [ "serde_yaml", "testing_logger", "tokio", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "tree_magic_mini", "url", "uuid", ] +[[package]] +name = "ripple_sdk" +version = "1.1.0" +source = "git+https://github.com/rdkcentral/Ripple.git?branch=ssda#7c594aa0563a4db945a97622617a268356ac1af3" +dependencies = [ + "async-trait", + "chrono", + "fern", + "futures", + "futures-channel", + "futures-util", + "jaq-core", + "jaq-interpret", + "jaq-parse", + "jaq-std", + "jsonrpsee 0.16.3", + "lazy_static", + "libloading", + "log", + "mockall", + "regex", + "semver", + "serde", + "serde_json", + "serde_millis", + "serde_yaml", + "tokio", + "tokio-tungstenite", + "url", + "uuid", +] + [[package]] name = "ripple_tdk" version = "1.1.0" dependencies = [ - "ripple_sdk", + "ripple_sdk 1.1.0", "serde_json", ] +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + [[package]] name = "rstest" version = "0.18.2" @@ -3663,22 +3706,22 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "glob", "proc-macro2", "quote", "regex", "relative-path", "rustc_version", - "syn 2.0.101", + "syn 2.0.103", "unicode-ident", ] [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -3686,6 +3729,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3880,7 +3929,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -3970,19 +4019,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "syn 2.0.103", ] [[package]] @@ -3992,10 +4029,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.1", + "opaque-debug", ] [[package]] @@ -4004,7 +4041,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -4021,7 +4058,7 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -4041,12 +4078,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "similar" version = "2.7.0" @@ -4061,12 +4092,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallvec" @@ -4081,7 +4109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4101,13 +4129,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes 1.10.1", + "bytes", "futures", "http 0.2.12", "httparse", "log", - "rand 0.8.5", - "sha-1 0.9.8", + "rand", + "sha-1", +] + +[[package]] +name = "soketto" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures", + "http 1.3.1", + "httparse", + "log", + "rand", + "sha1", ] [[package]] @@ -4117,19 +4161,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "ssda_client" -version = "0.1.0" +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" dependencies = [ - "async-trait", - "log", - "serde", - "serde_json", - "ssda_types", - "tokio", - "tokio-tungstenite 0.20.1", - "tungstenite 0.26.2", - "url", - "ws", + "lock_api", ] [[package]] @@ -4141,14 +4178,12 @@ dependencies = [ "http 0.2.12", "log", "mockall", - "ripple_sdk", + "ripple_sdk 1.1.0 (git+https://github.com/rdkcentral/Ripple.git?branch=ssda)", "serde_json", - "ssda_client", "ssda_types", "tokio", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "url", - "uuid", ] [[package]] @@ -4158,17 +4193,15 @@ dependencies = [ "async-trait", "futures-util", "http 0.2.12", - "jsonrpsee", + "jsonrpsee 0.24.9", "mockall", - "ripple_sdk", + "pprof", + "ripple_sdk 1.1.0 (git+https://github.com/rdkcentral/Ripple.git?branch=ssda)", "serde", "serde_json", - "stream-tungstenite", "tokio", - "tokio-tungstenite 0.20.1", - "tokio-websockets", + "tokio-tungstenite", "url", - "uuid", ] [[package]] @@ -4178,23 +4211,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "stream-tungstenite" -version = "0.4.6" +name = "str_stack" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99193254746dac7d4dd50211ae4dbb7a95ab7024dda4251782c4ad42c852d2fa" -dependencies = [ - "async-trait", - "eyre", - "futures", - "futures-util", - "rand 0.9.1", - "thiserror 2.0.12", - "tokio", - "tokio-stream", - "tokio-tungstenite 0.26.2", - "tracing", - "tungstenite 0.26.2", -] +checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" [[package]] name = "string_cache" @@ -4246,7 +4266,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4265,6 +4285,29 @@ dependencies = [ "typed-arena", ] +[[package]] +name = "symbolic-common" +version = "12.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1150bdda9314f6cfeeea801c23f5593c6e6a6c72e64f67e48d723a12b8efdb" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "12.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f66537def48fbc704a92e4fdaab7833bc7cb2255faca8182592fb5fa617eb82" +dependencies = [ + "cpp_demangle", + "rustc-demangle", + "symbolic-common", +] + [[package]] name = "syn" version = "1.0.109" @@ -4278,9 +4321,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", @@ -4301,7 +4344,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4310,13 +4353,13 @@ version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "core-foundation-sys", "libc", "ntapi", "once_cell", "rayon", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4372,7 +4415,7 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4427,7 +4470,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4438,7 +4481,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4453,12 +4496,12 @@ dependencies = [ "futures-channel", "futures-util", "home", - "jsonrpsee", + "jsonrpsee 0.16.3", "maplit", "pact_consumer", "regex", "reqwest", - "ripple_sdk", + "ripple_sdk 1.1.0", "ripple_tdk", "rstest", "serde", @@ -4527,9 +4570,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", - "bytes 1.10.1", + "bytes", "libc", - "mio 1.0.4", + "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -4556,17 +4599,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", -] - -[[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", + "syn 2.0.103", ] [[package]] @@ -4600,21 +4633,7 @@ dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.20.1", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.26.2", + "tungstenite", ] [[package]] @@ -4623,7 +4642,7 @@ version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ - "bytes 1.10.1", + "bytes", "futures-core", "futures-io", "futures-sink", @@ -4631,25 +4650,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-websockets" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fcaf159b4e7a376b05b5bfd77bfd38f3324f5fce751b4213bfc7eaa47affb4e" -dependencies = [ - "base64 0.22.1", - "bytes 1.10.1", - "futures-core", - "futures-sink", - "http 1.3.1", - "httparse", - "openssl", - "rand 0.9.1", - "simdutf8", - "tokio", - "tokio-util", -] - [[package]] name = "toml" version = "0.8.23" @@ -4693,7 +4693,7 @@ dependencies = [ "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.10", + "winnow 0.7.11", ] [[package]] @@ -4711,13 +4711,13 @@ dependencies = [ "async-trait", "axum", "base64 0.21.7", - "bytes 1.10.1", + "bytes", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.27", "hyper-timeout", "percent-encoding", "pin-project", @@ -4754,7 +4754,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand", "slab", "tokio", "tokio-util", @@ -4789,13 +4789,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4835,36 +4835,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", - "bytes 1.10.1", + "bytes", "data-encoding", "http 0.2.12", "httparse", "log", - "rand 0.8.5", + "rand", "sha1", "thiserror 1.0.69", "url", "utf-8", ] -[[package]] -name = "tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" -dependencies = [ - "bytes 1.10.1", - "data-encoding", - "http 1.3.1", - "httparse", - "log", - "native-tls", - "rand 0.9.1", - "sha1", - "thiserror 2.0.12", - "utf-8", -] - [[package]] name = "typed-arena" version = "1.7.0" @@ -4891,9 +4873,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unicode-xid" @@ -4967,12 +4949,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "vergen" version = "1.1.1" @@ -5011,15 +4987,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -5036,7 +5006,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -5052,7 +5022,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "wasm-bindgen-shared", ] @@ -5062,7 +5032,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "once_cell", "wasm-bindgen", @@ -5087,7 +5057,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5152,12 +5122,6 @@ dependencies = [ "rustix 0.38.44", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -5168,12 +5132,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -5216,7 +5174,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5227,14 +5185,14 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" @@ -5413,9 +5371,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -5426,7 +5384,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -5445,34 +5403,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" -[[package]] -name = "ws" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "httparse", - "log", - "mio 0.6.23", - "mio-extras", - "rand 0.7.3", - "sha-1 0.8.2", - "slab", - "url", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "xattr" version = "1.5.0" @@ -5509,28 +5439,28 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5550,7 +5480,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -5584,7 +5514,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index 010df7c2f..685eb82c2 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -45,7 +45,8 @@ contract_tests = [ tdk=[] [dependencies] base64.workspace = true -ripple_sdk = { workspace = true, features = ["full","local_dev"] } +ripple_sdk = { git = "https://github.com/rdkcentral/Ripple.git", branch = "ssda", subdir = "core/sdk" } + jsonrpsee = { workspace = true, features = ["macros"] } futures-channel.workspace = true futures.workspace = true @@ -71,9 +72,11 @@ strum_macros = "0.24" openrpc_validator = { path = "../../openrpc_validator" } proc-macro2.workspace = true -ssda_service = {path = "../../ssda/ssda_service/"} -ssda_types = {path = "../../ssda/ssda_types/"} +ssda_service = {path = "../../../ssda/ssda_service/"} +ssda_types = {path = "../../../ssda/ssda_types/"} +[patch. "https://github.com/rdkcentral/Ripple.git" ] +ripple_sdk = { path = "../sdk" } [build-dependencies] @@ -85,4 +88,4 @@ rstest = "0.18.0" # serial_test is used to provide determinism around monotonic counter generation # using AtomicU64 serial_test = "3" -httpmock = "0.7.0" \ No newline at end of file +httpmock = "0.7.0" diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index 0a71d659a..b26d4dbc4 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -257,6 +257,26 @@ impl JsonRpcApiRequest { self } } +impl From for RpcRequest { + fn from(request: JsonRpcApiRequest) -> Self { + RpcRequest { + ctx: CallContext::default(), + method: request.method, + params_json: serde_json::to_string(&request.params.unwrap_or_default()) + .unwrap_or_default(), + } + } +} +impl From for JsonRpcApiRequest { + fn from(request: RpcRequest) -> Self { + JsonRpcApiRequest { + jsonrpc: "2.0".to_owned(), + id: Some(request.clone().ctx.call_id), + method: request.clone().method, + params: request.get_params(), + } + } +} #[derive(Clone, Default, Debug)] pub struct JsonRpcApiError { diff --git a/ssda/example-service/src/main.rs b/ssda/example-service/src/main.rs deleted file mode 100644 index fc2ab6ef2..000000000 --- a/ssda/example-service/src/main.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::{sync::Arc, vec}; - -use ssda_client::APIGatewayClientBuilder; -use ssda_types::client::ServiceRequestHandlerImpl; -use ssda_types::service::{ - FireboltMethodHandlerAPIRegistration, FireboltMethodHandlerRegistration, ServiceCall, - ServiceCallErrorResponse, ServiceCallSuccessResponse, ServiceRegistration, -}; -use ssda_types::{JqRule, ServiceId}; - -#[derive(Debug, Clone)] -pub struct ExampleService {} - -impl ExampleService { - pub fn new() -> Self { - Self {} - } -} -#[async_trait::async_trait] -impl ServiceRequestHandlerImpl for ExampleService { - fn register(&self) -> Vec { - vec![] - } - fn handle_request( - &self, - request: ServiceCall, - ) -> Result { - // Handle the request and return a response - println!("handle_request: handling request {:?}", request); - match request.method.as_str() { - "device.audio" => Ok(ServiceCallSuccessResponse { - request_id: request.request_id, - response: serde_json::json!({ "status": "success" }), - }), - bad_method => { - return Err(ServiceCallErrorResponse { - request_id: request.request_id, - error: format!("Unknown method: {}", bad_method), - }); - } - } - } - fn on_connected(&self) { - println!("example connected") - } - fn on_disconnected(&self) { - println!("disconnected") - } - fn healthy(&self) -> bool { - todo!() - } -} -#[tokio::main] -async fn main() { - let my_handler = ExampleService::new(); - let mut firebolt_handlers = Vec::new(); - firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { - firebolt_method: "device.audio".to_string(), - jq_rule: Some(JqRule { - alias: "device.audio".to_string(), - rule: "jq_type".to_string(), - }), - }); - firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { - firebolt_method: "device.make".to_string(), - jq_rule: Some(JqRule { - alias: "device.make".to_string(), - rule: "jq_type".to_string(), - }), - }); - - let registration = ServiceRegistration { - service_id: ServiceId { - service_id: "example".to_string(), - }, - firebolt_handlers: firebolt_handlers, - }; - - let _ = APIGatewayClientBuilder::new(registration) - .websocket() - .build(Arc::new(my_handler)) - .start() - .await; -} diff --git a/ssda/ssda_client/src/lib.rs b/ssda/ssda_client/src/lib.rs deleted file mode 100644 index 08384c780..000000000 --- a/ssda/ssda_client/src/lib.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::sync::Arc; - -use ssda_types::{ - service::{ServiceRegistration, ServiceRequestHandler}, - APIGatewayClient, DBUSAPIGatewayClient, WebsocketAPIGatewayClient, -}; -pub enum APIGatewayClientTransport { - WebSocket, - Dbus, -} -pub struct APIGatewayClientBuilder { - transport: APIGatewayClientTransport, - service_registration: ServiceRegistration, -} - -impl APIGatewayClientBuilder { - pub fn new(service_registration: ServiceRegistration) -> Self { - APIGatewayClientBuilder { - transport: APIGatewayClientTransport::WebSocket, - service_registration, - } - } - pub fn with_service_registration( - &mut self, - service_registration: ServiceRegistration, - ) -> &mut Self { - self.service_registration = service_registration; - self - } - - pub fn websocket(&mut self) -> &mut Self { - // Initialize WebSocket client - self.transport = APIGatewayClientTransport::WebSocket; - self - } - pub fn dbus(&mut self) -> &mut Self { - // Initialize DBus client - self.transport = APIGatewayClientTransport::Dbus; - self - } - pub fn build(&self, handler: Arc) -> Box { - match self.transport { - APIGatewayClientTransport::WebSocket => Box::new(WebsocketAPIGatewayClient::new( - handler, - self.service_registration.clone(), - )), - APIGatewayClientTransport::Dbus => Box::new(DBUSAPIGatewayClient {}), - } - } -} diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs deleted file mode 100644 index d8026c4e1..000000000 --- a/ssda/ssda_service/src/lib.rs +++ /dev/null @@ -1,720 +0,0 @@ -/* -This is the API gateway, and it meant to be hosted in the main ripple process -*/ - -use std::{collections::HashMap, f32::consts::E, sync::Arc}; - -use futures_util::stream::SplitSink; -use futures_util::stream::StreamExt; -use futures_util::SinkExt; -use http::Uri; -use log::{error, info}; - -use ripple_sdk::api::rules_engine::{Rule, RuleEngineProvider, RuleTransform}; -use tokio::sync::{mpsc, RwLock}; -pub struct ServiceMap { - service_map: HashMap>, -} -impl ServiceMap { - fn new() -> Self { - Self { - service_map: HashMap::new(), - } - } - fn add_service( - &mut self, - service_id: ServiceId, - registrations: Vec, - ) { - self.service_map.insert(service_id, registrations); - } - fn remove_service(&mut self, service_id: &ServiceId) { - self.service_map.remove(service_id); - } - fn get_registrations( - &self, - service_id: &ServiceId, - ) -> Vec { - self.service_map.get(service_id).unwrap_or(&vec![]).clone() - } - fn get_service_for_method( - &self, - method: &str, - ) -> Option<(ServiceId, FireboltMethodHandlerAPIRegistration)> { - for (service_id, registrations) in self.service_map.iter() { - for registration in registrations.iter() { - if registration.firebolt_method == method { - return Some((service_id.clone(), registration.clone())); - } - } - } - None - } -} -pub struct WebSocketChannels { - pub tx: mpsc::Sender, - pub rx: mpsc::Receiver, -} -pub struct ApiGateway { - pub service_endpoints: Arc>>>, - pub rules_engine: Arc>>, - pub methods_2_services: Arc>, - pub broker_sender: mpsc::Sender, - pub services_2_rxs: - Arc>>>, - pub reply_to_tx: mpsc::Sender, -} -pub enum APIGatewayClientState { - Failed(String), - Connecting, - Registering(APIGatewayServiceRegistrationRequest), - Connected, - Closed, - Message(ServiceRequestId, Value), - ServiceCallFailed(ServiceRequestId, String), -} -type RequestIds2SendersType = Arc< - RwLock< - HashMap>>>>, - >, ->; - -impl ApiGateway { - pub fn new( - rules_engine: Arc>>, - ) -> Self { - let (tx, rx) = mpsc::channel::(32); - let (reply_to_tx, _) = mpsc::channel::(32); - let services_2_rxs = Arc::new(tokio::sync::RwLock::new(HashMap::new())); - - let me = Self { - service_endpoints: Arc::new(tokio::sync::RwLock::new(HashMap::new())), - rules_engine, - methods_2_services: Arc::new(tokio::sync::RwLock::new(ServiceMap::new())), - broker_sender: tx.clone(), - services_2_rxs: services_2_rxs.clone(), - reply_to_tx, - }; - - me.start(rx, Arc::clone(&services_2_rxs)); - - me - } - /* - start the task that handles the service routing requests, and routes them to the appropriate service - */ - pub fn start( - &self, - mut rx: mpsc::Receiver, - services_2_rxes: Arc< - tokio::sync::RwLock>>, - >, - ) { - let methods_2_services = self.methods_2_services.clone(); - let services_2_rxs = Arc::clone(&services_2_rxes); - tokio::spawn(async move { - while let Some(request) = rx.recv().await { - let methods_2_services = methods_2_services.read().await; - let method = request.payload.method.clone(); - match methods_2_services.get_service_for_method(method.as_str()) { - Some((service_id, _registration)) => { - /* - send the request to the websocket handler for the service - */ - if let Some(service) = services_2_rxs.read().await.get(&service_id) { - let (send, receive) = oneshot::channel::(); - let method = request.payload.method.clone(); - let payload = serde_json::to_value(request.payload.clone()); - if payload.is_err() { - error!("Failed to serialize payload: {:?}", payload); - continue; - } - let payload = payload.unwrap(); - let websocket_request = WebsocketServiceRequest { - method, - request_id: request.request_id.clone(), - payload, - respond_to: send, - }; - let _ = service.send(websocket_request).await; - match receive.await { - Ok(response) => { - info!("start Received response from service: {:?}", response); - match response { - WebsocketServiceResponse::Success(request_id, result) => { - info!("Received success response: {:?}", result); - // Send the response back to the broker - let _ = request.respond_to.send( - ServiceRoutingResponse::Success( - ServiceRoutingSuccessResponse { - request_id, - response: result, - }, - ), - ); - } - WebsocketServiceResponse::Error(request_id, error) => { - info!("Received error response: {:?}", error); - // Send the error response back to the broker - let _ = request.respond_to.send( - ServiceRoutingResponse::Error( - ServiceRoutingErrorResponse { - request_id, - error, - }, - ), - ); - } - } - } - Err(e) => { - error!("Failed to receive response from service: {:?}", e); - } - } - } else { - error!( - "else No service sender found for method: {:?} in {:?} ", - method, - services_2_rxs.read().await - ); - } - } - - None => { - error!("None No service found for method: {:?}", method); - } - } - } - }); - } - /// This function is used to check if the given URI is a service URL - pub fn is_apigateway_connection( - uri: &http::Uri, - ) -> Result { - // Check if the URI is a service URL - // This is a placeholder implementation - if !uri.path().starts_with("/apigateway") { - return Err(APIGatewayServiceConnectionError::NotAService); - } - - if let Some(query) = uri.query() { - let query_pairs = form_urlencoded::parse(query.as_bytes()); - for (key, value) in query_pairs { - if key == "serviceId" { - return Ok(APIGatewayServiceConnectionDisposition::Accept( - ServiceId::new(value.to_string()), - )); - } - } - } - Err(APIGatewayServiceConnectionError::NotAService) - } - pub fn classify_message(message: &Message) -> APIGatewayClientState { - // Classify the message based on its content - // This is a placeholder implementation - if let Message::Text(text) = message { - let parsed: Result = serde_json::from_str(text); - info!("Parsed message: {:?}", parsed); - if let Ok(msg) = parsed { - match msg { - APIClientMessages::Register(registration) => { - return APIGatewayClientState::Registering(registration); - } - - APIClientMessages::ServiceCallSuccessResponse(succcess) => { - return APIGatewayClientState::Message( - succcess.request_id, - succcess.response, - ) - } - APIClientMessages::ServiceCallErrorResponse(error) => { - return APIGatewayClientState::ServiceCallFailed( - error.request_id, - error.error, - ); - } - e => { - info!("Classified message: {:?}", e); - return APIGatewayClientState::Failed(format!( - "Unknown message type: {:?}", - e - )); - } - } - } - } else if let Message::Close(_) = message { - return APIGatewayClientState::Closed; - } - - APIGatewayClientState::Failed(format!("Failed to parse message: {}", message)) - } - fn jq_rule_to_string(jq_rule: Option) -> Option { - if let Some(rule) = jq_rule { - return Some(rule.rule); - } - None - } - async fn handle_registration( - service_id: ServiceId, - rule_engine: Arc>>, - registration: &APIGatewayServiceRegistrationRequest, - methods_2_services: Arc>, - ) { - let rules = ®istration.firebolt_handlers; - - let mut rule_engine = rule_engine.write().await; - - for handle_rule in rules { - let rule = Rule { - alias: handle_rule.firebolt_method.clone(), - transform: RuleTransform::default(), - filter: Self::jq_rule_to_string(handle_rule.jq_rule.clone()), - event_handler: None, - endpoint: Some("service".to_string()), - sources: None, - }; - /* - todo, save off existing rule for rollback (if it exists) - */ - rule_engine.add_rule(rule); - } - methods_2_services - .write() - .await - .add_service(service_id.clone(), rules.clone()); - } - async fn handle_unregister( - service_id: &ServiceId, - methods_2_services: Arc>, - rule_engine: Arc>>, - ) { - let mut rule_engine = rule_engine.write().await; - let aliases = methods_2_services - .read() - .await - .get_registrations(service_id); - for handle_rule in aliases { - rule_engine.remove_rule(&handle_rule.firebolt_method); - } - methods_2_services.write().await.remove_service(service_id); - } - - async fn handle_message( - message: Result, - tx: &mut SplitSink, Message>, - service_id: &ServiceId, - rule_engine: Arc>>, - methods_2_services: Arc>, - services_2_rxes: Arc< - tokio::sync::RwLock>>, - >, - bridge_tx: mpsc::Sender, - ) { - match message { - Ok(msg) => { - info!("gateway server received websocket message: {:?}", msg); - match Self::classify_message(&msg) { - APIGatewayClientState::Registering(registration) => { - info!("Registering service: {:?}", registration); - Self::handle_unregister( - service_id, - methods_2_services.clone(), - rule_engine.clone(), - ) - .await; - - Self::handle_registration( - service_id.clone(), - rule_engine.clone(), - ®istration, - methods_2_services.clone(), - ) - .await; - - let response: APIGatewayServiceRegistrationResponse = registration.into(); - let response = APIClientMessages::Registered(response); - let msg = serde_json::to_string(&response); - match msg { - Ok(msg) => { - let _ = tx.send(Message::Text(msg.clone())).await; - info!("Sending registration response: {:?}", msg); - } - Err(e) => { - error!("Failed to serialize registration response: {:?}", e); - } - } - - info!("Sent registration response: {:?}", response) - } - APIGatewayClientState::Failed(e) => { - error!("Failed to classify message {} err {},{}", msg, E, e); - - let _ = tx.send(Message::Close(None)).await; - let _ = tx.close().await; - } - APIGatewayClientState::Closed => { - info!("Client closed connection"); - Self::handle_unregister(service_id, methods_2_services, rule_engine).await; - let _ = tx.close().await; - } - APIGatewayClientState::Message(request_id, msg) => { - info!( - "got msg from websocket: {} for request {:?}", - msg, request_id - ); - let _ = bridge_tx - .send(WebsocketServiceResponse::Success(request_id, msg)) - .await; - } - APIGatewayClientState::ServiceCallFailed(id, error) => { - info!("Service call failed: {:?}", error); - let fail = WebsocketServiceResponse::Error(id, error); - let _ = bridge_tx.send(fail).await; - } - - _ => { - info!("handle_message: Unknown message type: {:?}", msg); - let _ = tx.send(Message::Close(None)).await; - let _ = tx.close().await; - } - } - } - Err(e) => { - /* - for now, just treat all errors as fatal and cleanup, drop tx and let client reconnect - */ - info!("Client closed connection. Error: {:?}", e); - info!("Unregistering service: {:?}", service_id); - - Self::handle_unregister(service_id, methods_2_services, rule_engine.clone()).await; - let _ = services_2_rxes.write().await.remove(service_id); - - let _ = tx.close().await; - } - } - } - /* - Spawn a task to handle exactly one service connection over websocket (for now, maybe dbus later) - */ - - async fn handle_service_connection( - service_id: ServiceId, - ws_stream: tokio_tungstenite::WebSocketStream, - rule_engine: Arc>>, - methods_2_services: Arc>, - mut websocket_service_request_rx: mpsc::Receiver, - service_2_rxes: Arc< - tokio::sync::RwLock>>, - >, - ) -> Result<(), APIGatewayServiceConnectionError> { - info!("Handling service connection: {:?}", service_id); - - let (mut websocket_tx, mut websocket_rx) = ws_stream.split(); - - let (bridge_tx, mut bridge_rx) = mpsc::channel::(32); - - let requests_2_requestors: RequestIds2SendersType = Arc::new(RwLock::new(HashMap::new())); - - loop { - tokio::select! { - // Handle incoming messages from the WebSocket stream - Some(message) = websocket_rx.next() => { - info!("gateway Received websocket message: {:?}", message); - Self::handle_message( - message, - &mut websocket_tx, - &service_id, - rule_engine.clone(), - methods_2_services.clone(), - service_2_rxes.clone(), - bridge_tx.clone(), - ).await - } - // this is a request from the main api gateway thread that needs to be sent to the service - //via the websocket - Some(request) = websocket_service_request_rx.recv() => { - let request_id = request.request_id.clone(); - let sender_entry = Arc::new(Mutex::new(Some(request.respond_to))); - requests_2_requestors.write().await.insert(request_id.clone(), sender_entry.clone()); - - let service_call = APIClientMessages::ServiceCall( - ServiceCall { - method: request.method.clone(), - request_id, - payload: request.payload.clone(), - } - ); - match serde_json::to_string(&service_call) { - Ok(service_call) => { - let _ = websocket_tx.send(Message::Text(service_call)).await; - } - Err(e) => { - error!("Failed to serialize service call: {:?}", e); - let fail = WebsocketServiceResponse::Error(request.request_id, e.to_string()); - let _ = bridge_tx.send(fail).await; - continue; - } - } - } - Some(bridge_message) = bridge_rx.recv() => { - info!("Received message from bridge: {:?}", bridge_message); - - let id = bridge_message.get_id(); - - if let Some(requestor) = requests_2_requestors.write().await.remove(&id) { - let mut requestor_lock = requestor.lock().await; - if let Some(sender) = requestor_lock.take() { - let _ = sender.send(bridge_message.clone()); - } - } - } - else => { - info!("Service connection closed: {:?}", service_id); - // Handle service disconnection - // Clean up resources, etc. - Self::handle_unregister( - &service_id, - methods_2_services.clone(), - rule_engine.clone(), - ).await; - let _ = service_2_rxes - .write() - .await - .remove(&service_id); - break Ok(()); - } - } - } - } -} -use serde_json::Value; -use ssda_types::gateway::{ - APIGatewayServiceConnectionDisposition, APIGatewayServiceConnectionError, ApiGatewayServer, - ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingResponse, - ServiceRoutingSuccessResponse, -}; -use ssda_types::service::{ - APIClientMessages, APIGatewayServiceRegistrationRequest, APIGatewayServiceRegistrationResponse, - FireboltMethodHandlerAPIRegistration, ServiceCall, WebsocketServiceRequest, - WebsocketServiceResponse, -}; -use ssda_types::{JqRule, ServiceId, ServiceRequestId}; -use tokio::net::TcpStream; -use tokio::sync::{oneshot, Mutex}; -use tokio_tungstenite::tungstenite::{Error, Message}; -use tokio_tungstenite::WebSocketStream; -use url::form_urlencoded; - -pub struct WebsocketHandler { - pub service_id: ServiceId, -} -#[async_trait::async_trait] -impl ApiGatewayServer for ApiGateway { - async fn is_service_connect( - &self, - uri: Uri, - ) -> Result { - Self::is_apigateway_connection(&uri) - } - async fn service_connect( - &mut self, - service_id: ServiceId, - ws_stream: tokio_tungstenite::WebSocketStream, - ) -> Result { - info!("new Service connected: {:?}", service_id); - - let spawn_service_id = service_id.clone(); - let rule_engine_for_service = self.rules_engine.clone(); - /* - The broker_rx is a channel that receives service routing requests from the broker. It is the responsibility - of this (APIGateway) to handle the service routing requests and send them to the appropriate service. - Each service connection will have its own broker_rx channel, and the APIGateway will handle the routing - */ - let (websocket_handler_sender, websocket_handler_receiver) = - mpsc::channel::(32); - - /* - map sender for the websocket handler to the service id for later use - */ - { - let mut updater = self.services_2_rxs.write().await; - updater.insert(service_id.clone(), websocket_handler_sender); - } - let methods_2_services = self.methods_2_services.clone(); - let services_2_rxs = Arc::clone(&self.services_2_rxs); - tokio::spawn(async move { - let _ = Self::handle_service_connection( - spawn_service_id, - ws_stream, - rule_engine_for_service, - methods_2_services.clone(), - websocket_handler_receiver, - services_2_rxs.clone(), - ) - .await; - }); - - Ok(APIGatewayServiceConnectionDisposition::Accept(service_id)) - } - fn get_sender(&self) -> tokio::sync::mpsc::Sender { - self.broker_sender.clone() - } -} -/* -write unit tests for ApiGateway -*/ -#[cfg(test)] -mod tests { - use super::*; - - use mockall::predicate::eq; - - use std::sync::Arc; - - use ripple_sdk::api::rules_engine::MockRuleEngineProvider; - - use ssda_types::service::{ - APIClientMessages, APIGatewayServiceRegistrationRequest, - FireboltMethodHandlerAPIRegistration, - }; - use ssda_types::{JqRule, ServiceId}; - use tokio::sync::RwLock; - - fn make_registration(method: &str) -> APIGatewayServiceRegistrationRequest { - APIGatewayServiceRegistrationRequest { - firebolt_handlers: vec![FireboltMethodHandlerAPIRegistration { - firebolt_method: method.to_string(), - jq_rule: Some(JqRule { - alias: "foo".to_string(), - rule: ".foo".to_string(), - }), - }], - } - } - - #[tokio::test] - async fn test_service_map_add_and_get() { - let mut map = ServiceMap::new(); - let service_id = ServiceId::new("svc1".to_string()); - let reg = FireboltMethodHandlerAPIRegistration { - firebolt_method: "foo.bar".to_string(), - jq_rule: None, - }; - map.add_service(service_id.clone(), vec![reg.clone()]); - let regs = map.get_registrations(&service_id); - assert_eq!(regs.len(), 1); - assert_eq!(regs[0].firebolt_method, "foo.bar"); - } - - #[tokio::test] - async fn test_service_map_remove() { - let mut map = ServiceMap::new(); - let service_id = ServiceId::new("svc2".to_string()); - let reg = FireboltMethodHandlerAPIRegistration { - firebolt_method: "foo.baz".to_string(), - jq_rule: None, - }; - map.add_service(service_id.clone(), vec![reg]); - map.remove_service(&service_id); - let regs = map.get_registrations(&service_id); - assert!(regs.is_empty()); - } - - #[tokio::test] - async fn test_service_map_get_service_for_method() { - let mut map = ServiceMap::new(); - let service_id = ServiceId::new("svc3".to_string()); - let reg = FireboltMethodHandlerAPIRegistration { - firebolt_method: "foo.qux".to_string(), - jq_rule: None, - }; - map.add_service(service_id.clone(), vec![reg.clone()]); - let found = map.get_service_for_method("foo.qux"); - assert!(found.is_some()); - let (sid, r) = found.unwrap(); - assert_eq!(sid, service_id); - assert_eq!(r.firebolt_method, "foo.qux"); - } - - #[tokio::test] - async fn test_is_apigateway_connection_accept() { - let uri: http::Uri = "/apigateway?serviceId=testsvc".parse().unwrap(); - let res = ApiGateway::is_apigateway_connection(&uri); - assert!(matches!( - res, - Ok(APIGatewayServiceConnectionDisposition::Accept(_)) - )); - } - - #[tokio::test] - async fn test_is_apigateway_connection_reject() { - let uri: http::Uri = "/notgateway".parse().unwrap(); - let res = ApiGateway::is_apigateway_connection(&uri); - assert!(matches!( - res, - Err(APIGatewayServiceConnectionError::NotAService) - )); - } - - #[tokio::test] - async fn test_classify_message_register() { - let reg = APIClientMessages::Register(make_registration("foo.bar")); - let msg = Message::Text(serde_json::to_string(®).unwrap()); - let state = ApiGateway::classify_message(&msg); - match state { - APIGatewayClientState::Registering(_) => {} - _ => panic!("Expected Registering"), - } - } - - #[tokio::test] - async fn test_classify_message_close() { - let msg = Message::Close(None); - let state = ApiGateway::classify_message(&msg); - assert!(matches!(state, APIGatewayClientState::Closed)); - } - - #[tokio::test] - async fn test_handle_registration_and_unregister() { - let service_id = ServiceId::new("svc4".to_string()); - let mut mock = MockRuleEngineProvider::new(); - let r = Rule { - alias: "foo.bar".to_string(), - filter: Some(".foo".to_string()), - endpoint: Some("service".to_string()), - ..Default::default() - }; - mock.expect_add_rule() - .with(eq(r.clone())) - .times(1) - .return_const(()); - mock.expect_remove_rule().times(1).return_const(()); - - let rule_engine: Arc< - RwLock>, - > = Arc::new(RwLock::new(Box::new(mock))); - - let methods_2_services = Arc::new(RwLock::new(ServiceMap::new())); - let registration = make_registration("foo.bar"); - ApiGateway::handle_registration( - service_id.clone(), - rule_engine.clone(), - ®istration, - methods_2_services.clone(), - ) - .await; - let regs = methods_2_services - .read() - .await - .get_registrations(&service_id); - assert_eq!(regs.len(), 1); - - ApiGateway::handle_unregister(&service_id, methods_2_services.clone(), rule_engine.clone()) - .await; - let regs = methods_2_services - .read() - .await - .get_registrations(&service_id); - assert!(regs.is_empty()); - } -} diff --git a/ssda/ssda_tranports/src/main.rs b/ssda/ssda_tranports/src/main.rs deleted file mode 100644 index e7a11a969..000000000 --- a/ssda/ssda_tranports/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/ssda/ssda_types/src/api_gateway_client.rs b/ssda/ssda_types/src/api_gateway_client.rs deleted file mode 100644 index 8b1378917..000000000 --- a/ssda/ssda_types/src/api_gateway_client.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ssda/ssda_types/src/api_gateway_server.rs b/ssda/ssda_types/src/api_gateway_server.rs deleted file mode 100644 index 8b1378917..000000000 --- a/ssda/ssda_types/src/api_gateway_server.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs deleted file mode 100644 index 390cabfdd..000000000 --- a/ssda/ssda_types/src/lib.rs +++ /dev/null @@ -1,755 +0,0 @@ -use std::sync::Arc; -use std::time::Duration; - -use futures_util::{SinkExt, StreamExt}; -use gateway::ServiceRoutingRequest; -use ripple_sdk::api::rules_engine::{Rule, RuleTransform}; -use ripple_sdk::log::{debug, error, info}; -use serde::{Deserialize, Serialize}; - -use service::{ - APIClientMessages, APIGatewayServiceRegistrationRequest, ServiceRegistration, - ServiceRequestHandler, -}; - -/* -Who what why -# API Gateway -The API gateway is a standalone binary component -that listens for Firebolt requests on a websocket. Upon receiving a firebolt -request, the gateway will look up a handler service (based on the method name) in it's -runtime (dynamically created) registry, and (assumign a service is registered to for the method), -will wrap the request with metadata, and dispatch the request to the handler service. Upon receiving -a response from the service, the API Gateway will translate the service response (using the rules engine) -into a Firebolt compatible (success or failure) result. - -# Servicesprintln -ServiceRequestHandler. This design is motivated by the need to free the Service from as much connection oriented -detail and let the developer focus on business logic. The API Gateway client is instanced as a crate that can be -consumed by a service at the highest possible level of abstraction (and ease of use) - it should only requuire a bit of -bootstrapping, and a ServiceRequestHandler instance/implementation, and then it should manage all the details of the -interactions between the Service and the API gateway with the Service being as blissfully ignorant of the details -as possible. -*/ -/* - -register: Service -> API Gateway Client -> API Gateway - -*/ - -pub mod api_gateway_client; -pub mod api_gateway_server; -pub mod service_api; - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] - -pub struct JqRule { - pub alias: String, - pub rule: String, -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct StaticRule { - pub alias: String, - pub rule: String, -} -#[derive(Debug, Clone, Default, Serialize, Deserialize)] - -pub struct HandlerId { - pub handler_id: String, -} -#[derive(Debug, Clone, Default, Serialize, Deserialize)] - -pub struct ServiceHandler { - pub handler_id: HandlerId, - pub handler_type: Handler, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub enum Handler { - #[default] - None, - JqRule(JqRule), - StaticRule(StaticRule), -} -impl std::fmt::Display for Handler { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Handler::None => write!(f, "none"), - Handler::JqRule(jq_rule) => write!(f, "{}", jq_rule.alias), - Handler::StaticRule(static_rule) => write!(f, "{}", static_rule.alias), - } - } -} - -impl From for ripple_sdk::api::rules_engine::Rule { - fn from(handler: Handler) -> Self { - match handler { - Handler::None => Rule { - alias: "none".to_string(), - filter: None, - transform: RuleTransform::default(), - event_handler: None, - endpoint: None, - sources: None, - }, - Handler::JqRule(jq_rule) => Rule { - alias: jq_rule.alias, - filter: Some(jq_rule.rule), - ..Default::default() - }, - Handler::StaticRule(static_rule) => Rule { - alias: static_rule.alias, - filter: Some(static_rule.rule), - ..Default::default() - }, - } - } -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct ServiceId { - pub service_id: String, -} -impl ServiceId { - pub fn new(service_id: String) -> Self { - ServiceId { service_id } - } -} - -impl PartialEq for ServiceId { - fn eq(&self, other: &Self) -> bool { - self.service_id == other.service_id - } -} - -impl Eq for ServiceId {} - -impl std::hash::Hash for ServiceId { - fn hash(&self, state: &mut H) { - self.service_id.hash(state); - } -} -impl std::fmt::Display for ServiceId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.service_id) - } -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct ServiceRequestId { - pub request_id: u64, -} -impl PartialEq for ServiceRequestId { - fn eq(&self, other: &Self) -> bool { - self.request_id == other.request_id - } -} - -impl Eq for ServiceRequestId {} - -impl std::hash::Hash for ServiceRequestId { - fn hash(&self, state: &mut H) { - self.request_id.hash(state); - } -} -impl ServiceRequestId { - pub fn new(request_id: u64) -> Self { - ServiceRequestId { request_id } - } -} - -/* -gateway messages: from endpoint broker to api gateway and back. -*/ -pub mod gateway { - use crate::ServiceId; - use http::Uri; - use ripple_sdk::api::gateway::rpc_gateway_api::{ - JsonRpcApiError, JsonRpcApiResponse, RpcRequest, - }; - use serde::{Deserialize, Serialize}; - use serde_json::Value; - use tokio::sync::oneshot::Sender; - - use crate::ServiceRequestId; - - /* - ServiceRequest is the request that is sent from the API Gateway to the service - */ - #[derive(Debug)] - pub struct ServiceRoutingRequest { - pub request_id: ServiceRequestId, - pub payload: RpcRequest, - pub respond_to: Sender, - } - #[derive(Debug, Default, Clone, Serialize, Deserialize)] - pub struct ServiceRoutingSuccessResponse { - pub request_id: ServiceRequestId, - pub response: Value, - } - impl From for JsonRpcApiResponse { - fn from(response: ServiceRoutingResponse) -> Self { - match response { - ServiceRoutingResponse::Error(_error) => JsonRpcApiError::default().into(), - ServiceRoutingResponse::Success(success) => JsonRpcApiResponse { - id: Some(success.request_id.request_id), - jsonrpc: "2.0".to_string(), - result: Some(success.response), - error: None, - method: None, - params: None, - }, - } - } - } - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct ServiceRoutingErrorResponse { - pub request_id: ServiceRequestId, - pub error: String, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum ServiceRoutingResponse { - Success(ServiceRoutingSuccessResponse), - Error(ServiceRoutingErrorResponse), - } - #[derive(Debug)] - pub enum APIGatewayServiceConnectionDisposition { - Accept(ServiceId), - Connected(ServiceId), - } - #[derive(Debug)] - pub enum APIGatewayServiceConnectionError { - ConnectionError, - NotAService, - } - - /* - This is the API gateway, and it meant to be hosted in the main ripple process - */ - - #[async_trait::async_trait] - pub trait ApiGatewayServer: Send + Sync { - async fn is_service_connect( - &self, - uri: Uri, - ) -> Result; - async fn service_connect( - &mut self, - service_id: ServiceId, - ws_stream: tokio_tungstenite::WebSocketStream, - ) -> Result; - fn get_sender(&self) -> tokio::sync::mpsc::Sender; - } -} -/* -service message: from api gateawy to services and back (over websockets) -*/ -pub mod service { - - use serde::{Deserialize, Serialize}; - - use crate::{Handler, JqRule, ServiceId, ServiceRequestId}; - - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct FireboltMethodHandlerRegistration { - pub firebolt_method: Handler, - } - #[derive(Debug, Clone, Serialize, Deserialize, Default)] - pub struct FireboltMethodHandlerAPIRegistration { - pub firebolt_method: String, - pub jq_rule: Option, - } - #[derive(Debug, Clone, Serialize, Deserialize, Default)] - pub struct APIGatewayServiceRegistrationRequest { - pub firebolt_handlers: Vec, - } - #[derive(Debug, Clone, Serialize, Deserialize, Default)] - pub struct APIGatewayServiceRegistrationResponse { - pub firebolt_handlers: Vec, - } - impl From for APIGatewayServiceRegistrationResponse { - fn from( - request: APIGatewayServiceRegistrationRequest, - ) -> APIGatewayServiceRegistrationResponse { - APIGatewayServiceRegistrationResponse { - firebolt_handlers: request.firebolt_handlers, - } - } - } - - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct ServiceRequest { - pub service_id: ServiceId, - pub firebolt_method: Handler, - pub payload: serde_json::Value, - } - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct ServiceErrorResponse { - pub service_id: ServiceId, - pub firebolt_method: Handler, - pub error: String, - } - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct ServiceSuccessResponse { - pub service_id: ServiceId, - pub firebolt_method: Handler, - pub payload: serde_json::Value, - } - - /* - send by api client to the api gateway over websocket - - */ - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct APIClientRegistration { - pub firebolt_handlers: Vec, - } - /* - Sent during callback registration in service - */ - #[derive(Debug, Clone, Default, Serialize, Deserialize)] - pub struct ServiceRegistration { - pub service_id: ServiceId, - pub firebolt_handlers: Vec, - } - - impl ServiceRegistration { - pub fn new( - service_id: ServiceId, - firebolt_handlers: Vec, - ) -> Self { - ServiceRegistration { - service_id, - firebolt_handlers, - } - } - pub fn get_rule_registrations(&self) -> Vec { - self.firebolt_handlers.clone() - } - } - - pub struct ServiceRegistrationBuilder { - service_id: ServiceId, - firebolt_handlers: Vec, - } - impl ServiceRegistrationBuilder { - pub fn new(service_id: ServiceId) -> Self { - ServiceRegistrationBuilder { - service_id, - firebolt_handlers: Vec::new(), - } - } - pub fn add_handler(&mut self, firebolt_method: Handler) -> &mut Self { - self.firebolt_handlers.push(match firebolt_method { - Handler::None => todo!(), - Handler::JqRule(jq_rule) => FireboltMethodHandlerAPIRegistration { - firebolt_method: jq_rule.alias.clone(), - jq_rule: Some(jq_rule), - }, - Handler::StaticRule(static_rule) => FireboltMethodHandlerAPIRegistration { - firebolt_method: static_rule.alias.clone(), - jq_rule: Some(JqRule { - alias: static_rule.alias, - rule: static_rule.rule, - }), - }, - }); - self - } - pub fn build(&self) -> ServiceRegistration { - ServiceRegistration { - service_id: self.service_id.clone(), - firebolt_handlers: self.firebolt_handlers.clone(), - } - } - } - /* - ServiceCall is the request that is presented to a callback handler. - */ - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ServiceCall { - pub request_id: ServiceRequestId, - pub method: String, - pub payload: serde_json::Value, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ServiceCallSuccessResponse { - pub request_id: ServiceRequestId, - pub response: serde_json::Value, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct ServiceCallErrorResponse { - pub request_id: ServiceRequestId, - pub error: String, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum ServiceCallResponse { - Success(ServiceCallSuccessResponse), - Error(ServiceCallErrorResponse), - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum APIClientMessages { - Register(APIGatewayServiceRegistrationRequest), - Registered(APIGatewayServiceRegistrationResponse), - Error(String), - Unregister(ServiceId), - ServiceCall(ServiceCall), - ServiceCallSuccessResponse(ServiceCallSuccessResponse), - ServiceCallErrorResponse(ServiceCallErrorResponse), - } - impl Default for APIClientMessages { - fn default() -> Self { - APIClientMessages::Register(APIGatewayServiceRegistrationRequest::default()) - } - } - - pub struct ServiceRegistrationResponse { - pub service_id: ServiceId, - } - pub struct ServiceRegistrationFailure { - pub service_id: ServiceId, - pub error: String, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub enum WebsocketServiceResponse { - Success(ServiceRequestId, serde_json::Value), - Error(ServiceRequestId, String), - } - impl WebsocketServiceResponse { - pub fn get_id(&self) -> ServiceRequestId { - match self { - WebsocketServiceResponse::Success(id, _) => id.clone(), - WebsocketServiceResponse::Error(id, _) => id.clone(), - } - } - } - #[derive(Debug)] - pub struct WebsocketServiceRequest { - pub request_id: ServiceRequestId, - pub method: String, - pub payload: serde_json::Value, - pub respond_to: tokio::sync::oneshot::Sender, - } - - /* - individiual services implement this trait to handle requests from the API gateway - This trait should faciliate fun testing of actual implementations - */ - - pub trait ServiceRequestHandler: Send + Sync { - /* - called by the client to allow the ServiceRequestHander return a Vec - to be used by the client to route requests. This is a blocking call, and will be called - after the client `on_connect`s - **/ - fn register(&self) -> Vec; - fn handle_request( - &self, - request: ServiceCall, - ) -> Result; - fn on_connected(&self); - fn on_disconnected(&self); - fn healthy(&self) -> bool; - } -} -pub mod client { - use mockall::automock; - - use crate::{HandlerId, ServiceId}; - - use crate::service::{ - FireboltMethodHandlerRegistration, ServiceCall, ServiceCallErrorResponse, - ServiceCallSuccessResponse, ServiceErrorResponse, ServiceRegistration, - ServiceRegistrationFailure, ServiceRegistrationResponse, ServiceRequest, - ServiceRequestHandler, ServiceSuccessResponse, - }; - - #[async_trait::async_trait] - /* - this is a trait that is implemented by a service client. - There will probably only be 2 of these for the foreseeable future: - 1) a real, websocket client - 2) a mock, for unit/integration testing - the point of this trait , and it's implementers, is to abstract the details related to auth, connection, etc. from the service (business logic) - that needs it. - - the methods in the actual interface are concerned with what to do during lifecycle transition events. the graph/steps/etc. of the lifecyle and - when to call these methods (and any state needed to call them) is the responsiblity of the concrete implementation. - */ - #[automock] - pub trait ServiceClientTrait: Send + Sync { - // this is a request to the service to register itself with the API gateway - fn register( - &self, - registraton: Box, - ) -> Result; - fn set_handler(&mut self, handler: Box); - fn unregister_service(&mut self, service_id: ServiceId) -> Result<(), String>; - fn register_handler( - &mut self, - handler: FireboltMethodHandlerRegistration, - ) -> Result<(), String>; - fn unregister_handler(&mut self, handler_id: HandlerId) -> Result<(), String>; - async fn invoke_handler( - &mut self, - request: ServiceRequest, - ) -> Result; - } - impl ServiceRequestHandler for T - where - T: Send + Sync + Clone + 'static + ServiceRequestHandlerImpl, - { - fn register(&self) -> Vec { - self.register() - } - - fn handle_request( - &self, - request: ServiceCall, - ) -> Result { - self.handle_request(request) - } - - fn on_connected(&self) { - self.on_connected() - } - - fn on_disconnected(&self) { - self.on_disconnected() - } - - fn healthy(&self) -> bool { - self.healthy() - } - } - - pub trait ServiceRequestHandlerImpl: Send + Sync + Clone { - fn register(&self) -> Vec; - fn handle_request( - &self, - request: ServiceCall, - ) -> Result; - fn on_connected(&self); - fn on_disconnected(&self); - fn healthy(&self) -> bool; - } -} -/* -This is the alternative API surface that services can use to communicate with the API gateway. -Firebolt calls are bidirectional, so the API gateway can send messages to the service, and the service can send messages to the API gateway. -*/ -mod api_surface { - use serde::{Deserialize, Serialize}; - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct FireboltRequest { - pub request_id: String, - pub payload: String, - } - #[derive(Debug, Clone, Serialize, Deserialize)] - pub struct FireboltResponse { - pub request_id: String, - pub payload: String, - } -} - -/* -This trait represents the layer that will actually "talk" to the API gateway. it handles transports, etc. -This is a trait to : -1) Enable testing -2) Abstract the details of the transport from the service -3) Allow for different transports (websocket, http, etc.)z -*/ -#[async_trait::async_trait] -pub trait APIGatewayClient { - fn connect(&self); - fn disconnect(&self); - fn dispatch(&self, request: gateway::ServiceRoutingRequest); - async fn start(&self); - async fn stop(&self); -} -pub struct WebsocketAPIGatewayClient { - handler: Arc, - registration: ServiceRegistration, -} - -use tokio_tungstenite::{connect_async, tungstenite::Message}; -use url::Url; - -impl WebsocketAPIGatewayClient { - pub fn new(handler: Arc, registration: ServiceRegistration) -> Self { - WebsocketAPIGatewayClient { - handler, - registration, - } - } - pub async fn handle_messages( - stream: tokio_tungstenite::WebSocketStream< - tokio_tungstenite::MaybeTlsStream, - >, - handler: Arc, - registration: ServiceRegistration, - ) { - let (mut tx, mut rx) = stream.split(); - - let registration_request = APIGatewayServiceRegistrationRequest { - firebolt_handlers: registration.get_rule_registrations(), - }; - let msg = serde_json::to_string(&APIClientMessages::Register(registration_request.clone())); - if let Ok(msg) = msg { - let _ = tx.send(Message::Text(msg)).await; - } else { - error!("websocket: Failed to serialize registration request"); - } - - while let Some(message) = rx.next().await { - match message { - Ok(msg) => { - /* - attempt to marshal the message into a ServiceRequest - if it fails, log the error and continue - */ - info!("websocket: Received message via websocket: {:?}", msg); - let msg = msg.into_text().unwrap_or_default(); - if let Ok(request) = serde_json::from_str::(&msg) { - match request { - APIClientMessages::Register(registration_request) => { - info!("Received registration request: {:?}", registration_request); - } - APIClientMessages::Registered(registration_request) => { - info!("Received registered response: {:?}", registration_request); - handler.on_connected(); - } - APIClientMessages::Error(error) => { - info!("Received error: {:?}", error); - } - APIClientMessages::Unregister(service_id) => { - info!("Received unregister request: {:?}", service_id); - } - APIClientMessages::ServiceCall(service_call) => { - info!("Received service call: {:?}", service_call); - match handler.handle_request(service_call) { - Ok(response) => { - let response = - APIClientMessages::ServiceCallSuccessResponse(response); - // Send the response back to the client - let response = serde_json::to_string(&response); - if let Ok(response) = response { - let _ = tx.send(Message::Text(response.clone())).await; - debug!("Sending response: {:?}", response); - } else { - error!("Failed to serialize response"); - } - } - Err(e) => { - // Handle error response - error!("Error handling request: {:?}", e); - let error_response = - APIClientMessages::ServiceCallErrorResponse(e); - let error_response = serde_json::to_string(&error_response); - if let Ok(error_response) = error_response { - let _ = tx - .send(Message::Text(error_response.clone())) - .await; - } - } - } - } - _ => {} - } - } else { - error!(" I don't understand this message: {:?}", msg); - } - } - Err(err) => { - error!("Error receiving message: {:?}", err); - // Handle the error (e.g., log it, retry, etc.) - // You might want to break the loop or handle reconnection logic here - // break; - } - } - } - } - pub async fn connect( - &self, - endpoint_url: Option, - ) -> Result<(), Box> { - let url = Url::parse( - &endpoint_url - .unwrap_or_else(|| "ws://localhost:3474/apigateway?serviceId=tester".to_string()), - )?; - let mut backoff = Duration::from_secs(1); - - loop { - match connect_async(url.clone()).await { - Ok((ws_stream, _)) => { - let handler = self.handler.clone(); - let registration = self.registration.clone(); - - info!("✅ Connected to WebSocket"); - - // Reset backoff after successful connection - backoff = Duration::from_secs(1); - - // This handles the message loop and returns on disconnect - Self::handle_messages(ws_stream, handler, registration).await; - info!("🔌 Disconnected, retrying..."); - } - Err(err) => { - error!("Error connecting to WebSocket: {:?}", err); - - // Exponential backoff (up to 1 minute) - tokio::time::sleep(backoff).await; - backoff = std::cmp::min(backoff * 2, Duration::from_secs(60)); - } - } - } - } -} - -#[async_trait::async_trait] -impl APIGatewayClient for WebsocketAPIGatewayClient { - fn connect(&self) { - // connect to the API gateway - } - fn disconnect(&self) { - // disconnect from the API gateway - } - fn dispatch(&self, _request: ServiceRoutingRequest) { - // send a request to the API gateway - } - - async fn start(&self) { - info!("starting websocket client"); - self.connect(None).await.unwrap(); - self.handler.on_connected(); - } - - async fn stop(&self) { - todo!() - } -} - -pub struct DBUSAPIGatewayClient { - // dbus client -} -#[async_trait::async_trait] -impl APIGatewayClient for DBUSAPIGatewayClient { - fn connect(&self) { - // connect to the API gateway - } - fn disconnect(&self) { - // disconnect from the API gateway - } - fn dispatch(&self, _request: ServiceRoutingRequest) { - // send a request to the API gateway - } - - async fn start(&self) { - todo!() - } - - async fn stop(&self) { - todo!() - } -} diff --git a/ssda/ssda_types/src/service_api.rs b/ssda/ssda_types/src/service_api.rs deleted file mode 100644 index 8b1378917..000000000 --- a/ssda/ssda_types/src/service_api.rs +++ /dev/null @@ -1 +0,0 @@ - From 4d15106449b8bd4ce1c7819e843188439ee78713 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Fri, 20 Jun 2025 06:44:48 -0700 Subject: [PATCH 23/46] checkpoint --- ssda/.gitignore | 1 - ssda/Cargo.toml | 5 ----- ssda/bak/.gitignore | 1 - ssda/bak/Cargo.toml | 5 ----- ssda/bak/rust-toolchain.toml | 2 -- ssda/example-service/Cargo.toml | 14 -------------- ssda/rust-toolchain.toml | 2 -- ssda/ssda_client/Cargo.toml | 16 ---------------- ssda/ssda_service/Cargo.toml | 19 ------------------- ssda/ssda_tranports/Cargo.toml | 6 ------ ssda/ssda_types/Cargo.toml | 23 ----------------------- 11 files changed, 94 deletions(-) delete mode 100644 ssda/.gitignore delete mode 100644 ssda/Cargo.toml delete mode 100644 ssda/bak/.gitignore delete mode 100644 ssda/bak/Cargo.toml delete mode 100644 ssda/bak/rust-toolchain.toml delete mode 100644 ssda/example-service/Cargo.toml delete mode 100644 ssda/rust-toolchain.toml delete mode 100644 ssda/ssda_client/Cargo.toml delete mode 100644 ssda/ssda_service/Cargo.toml delete mode 100644 ssda/ssda_tranports/Cargo.toml delete mode 100644 ssda/ssda_types/Cargo.toml diff --git a/ssda/.gitignore b/ssda/.gitignore deleted file mode 100644 index ea8c4bf7f..000000000 --- a/ssda/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/ssda/Cargo.toml b/ssda/Cargo.toml deleted file mode 100644 index 3106b8a15..000000000 --- a/ssda/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[workspace] -resolver = "2" -members = [ "example-service", "ssda_client","ssda_service", "ssda_tranports", "ssda_types"] - - diff --git a/ssda/bak/.gitignore b/ssda/bak/.gitignore deleted file mode 100644 index ea8c4bf7f..000000000 --- a/ssda/bak/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/ssda/bak/Cargo.toml b/ssda/bak/Cargo.toml deleted file mode 100644 index 3106b8a15..000000000 --- a/ssda/bak/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[workspace] -resolver = "2" -members = [ "example-service", "ssda_client","ssda_service", "ssda_tranports", "ssda_types"] - - diff --git a/ssda/bak/rust-toolchain.toml b/ssda/bak/rust-toolchain.toml deleted file mode 100644 index 2e2b8c852..000000000 --- a/ssda/bak/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "1.82.0" diff --git a/ssda/example-service/Cargo.toml b/ssda/example-service/Cargo.toml deleted file mode 100644 index caf0534bf..000000000 --- a/ssda/example-service/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "example-service" -version = "0.1.0" -edition = "2021" - -[dependencies] -async-trait = "0.1.88" -serde_json = "1.0.140" -ssda_types = {path="../ssda_types"} -ssda_client = {path = "../ssda_client"} -tokio = "1.44.2" -mockall = "0.13.1" -tokio-websockets = "0.11.4" -log = "0.4.27" diff --git a/ssda/rust-toolchain.toml b/ssda/rust-toolchain.toml deleted file mode 100644 index 2e2b8c852..000000000 --- a/ssda/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "1.82.0" diff --git a/ssda/ssda_client/Cargo.toml b/ssda/ssda_client/Cargo.toml deleted file mode 100644 index 6fbe7f198..000000000 --- a/ssda/ssda_client/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "ssda_client" -version = "0.1.0" -edition = "2021" - -[dependencies] -tokio = { version = "1", features = ["full"] } -ws = "0.9.2" -log = "0.4" -serde = { version = "1.0", features = ["derive"] } -ssda_types = {path = "../ssda_types"} -async-trait = "0.1.88" -serde_json = "1.0.140" -tokio-tungstenite = "0.20.1" -tungstenite = "0.26.2" -url = "2.5.4" \ No newline at end of file diff --git a/ssda/ssda_service/Cargo.toml b/ssda/ssda_service/Cargo.toml deleted file mode 100644 index 3b7aed7d5..000000000 --- a/ssda/ssda_service/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "ssda_service" -version = "0.1.0" -edition = "2021" - -[dependencies] -async-trait = "0.1.88" -serde_json = "1.0.140" -ssda_types = {path="../ssda_types"} -ssda_client = {path = "../ssda_client"} -ripple_sdk = {path = "../../core/sdk"} -tokio = "1.44.2" -mockall = "0.13.1" -tokio-tungstenite = "0.20.1" -http = "0.2.12" -url = "2.5.4" -log = "0.4.27" -futures-util = "0.3.31" -uuid = { version = "1.13.1", default-features = false, features = ["v4"] } \ No newline at end of file diff --git a/ssda/ssda_tranports/Cargo.toml b/ssda/ssda_tranports/Cargo.toml deleted file mode 100644 index 3457b87cc..000000000 --- a/ssda/ssda_tranports/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "ssda_tranports" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/ssda/ssda_types/Cargo.toml b/ssda/ssda_types/Cargo.toml deleted file mode 100644 index f2a9a77fb..000000000 --- a/ssda/ssda_types/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "ssda_types" -version = "0.1.0" -edition = "2021" - -[dependencies] -jsonrpsee = { version = "=0.16.3", default-features = false } - -ripple_sdk = {path = "../../core/sdk"} - -async-trait = "0.1.88" -mockall = "0.13.1" -serde = "1.0.219" -serde_json = "1.0.140" -tokio = { version = "1", features = ["full"] } -tokio-tungstenite = "0.20.1" -futures-util = "0.3" -url = "2.5" -uuid = "1.16.0" - -http = "0.2.12" -tokio-websockets = { version = "0.11.4", features=["client","openssl","rand"]} -stream-tungstenite = "0.4.5" From a70e6a4446dee4616410ed0e6c2bc9e4b5fc4c4a Mon Sep 17 00:00:00 2001 From: bobra200 Date: Wed, 25 Jun 2025 06:37:37 -0700 Subject: [PATCH 24/46] feat: correcting rpc param types --- core/main/src/broker/service_broker.rs | 6 ++++++ core/sdk/src/api/gateway/rpc_gateway_api.rs | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 2eea7bf1a..5f7ddcd46 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -3,6 +3,7 @@ use ripple_sdk::{ log::{error, info}, tokio::sync::mpsc, }; +use serde_json::Value; use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; use ssda_types::ServiceRequestId; @@ -53,6 +54,7 @@ impl EndpointBroker for ServiceBroker { use tokio::sync::oneshot; let (oneshot_tx, oneshot_rx) = oneshot::channel::(); + let service_request = ServiceRoutingRequest { request_id: ServiceRequestId { request_id: request.rpc.ctx.call_id, @@ -60,6 +62,10 @@ impl EndpointBroker for ServiceBroker { payload: request.rpc.clone(), respond_to: oneshot_tx, }; + info!( + "ServiceBroker sending service request: {:?}", + service_request + ); services_tx.try_send(service_request).unwrap(); diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index b26d4dbc4..40d0f3aa2 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -273,7 +273,7 @@ impl From for JsonRpcApiRequest { jsonrpc: "2.0".to_owned(), id: Some(request.clone().ctx.call_id), method: request.clone().method, - params: request.get_params(), + params: request.get_params_as_map(), } } } @@ -674,6 +674,22 @@ impl RpcRequest { } None } + pub fn get_params_as_map(&self) -> Option { + if let Ok(params) = serde_json::from_str::(&self.params_json.clone()) { + let params = params.as_array().unwrap_or(&vec![]).to_vec(); + let mut params_map = serde_json::Map::new(); + for param in ¶ms { + let f = param.as_object().unwrap(); + params_map.extend(f.clone()); + } + if params_map.is_empty() { + return None; + } + return Some(Value::Object(params_map)); + } + + return None; + } pub fn get_new_internal(method: String, params: Option) -> Self { let ctx = CallContext::new( From 3e7a48a114e3b1d31845dcbb283384394d21f889 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Wed, 25 Jun 2025 08:13:18 -0700 Subject: [PATCH 25/46] feat: convert RpcReqest to JsonRpcApiRequest --- core/sdk/src/api/gateway/rpc_gateway_api.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index 40d0f3aa2..f71feb63a 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -540,6 +540,14 @@ impl RpcRequest { self.ctx.cid = Some(cid); self } + pub fn as_json_rpc(&self) -> JsonRpcApiRequest { + JsonRpcApiRequest { + jsonrpc: "2.0".to_owned(), + id: Some(self.ctx.call_id), + method: self.method.clone(), + params: self.get_params_as_map(), + } + } } impl ExtnPayloadProvider for RpcRequest { fn get_extn_payload(&self) -> ExtnPayload { From 2ad2bdc6e1cae088484f0aa0eeadc931d931d0d6 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Wed, 25 Jun 2025 08:44:04 -0700 Subject: [PATCH 26/46] type converter --- Cargo.lock | 6 ++++-- core/main/Cargo.toml | 6 ++++-- core/sdk/src/api/gateway/rpc_gateway_api.rs | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7f220abb..706224dc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3645,7 +3645,7 @@ dependencies = [ [[package]] name = "ripple_sdk" version = "1.1.0" -source = "git+https://github.com/rdkcentral/Ripple.git?branch=ssda#7c594aa0563a4db945a97622617a268356ac1af3" +source = "git+https://github.com/rdkcentral/Ripple.git?branch=ssda#3e7a48a114e3b1d31845dcbb283384394d21f889" dependencies = [ "async-trait", "chrono", @@ -4172,6 +4172,7 @@ dependencies = [ [[package]] name = "ssda_service" version = "0.1.0" +source = "git+ssh://git@github.com/bobra200_comcast/ssda.git?branch=main#10562c88f7bacda9895c28047f8d36e99123525d" dependencies = [ "async-trait", "futures-util", @@ -4189,6 +4190,7 @@ dependencies = [ [[package]] name = "ssda_types" version = "0.1.0" +source = "git+ssh://git@github.com/bobra200_comcast/ssda.git?branch=main#10562c88f7bacda9895c28047f8d36e99123525d" dependencies = [ "async-trait", "futures-util", @@ -5144,7 +5146,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index 685eb82c2..a80ae4e43 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -72,8 +72,10 @@ strum_macros = "0.24" openrpc_validator = { path = "../../openrpc_validator" } proc-macro2.workspace = true -ssda_service = {path = "../../../ssda/ssda_service/"} -ssda_types = {path = "../../../ssda/ssda_types/"} +#ssda_service = {path = "../../../ssda/ssda_service/"} +#ssda_types = {path = "../../../ssda/ssda_types/"} +ssda_service = { git = "ssh://git@github.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_service" } +ssda_types= { git = "ssh://git@github.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_types" } [patch. "https://github.com/rdkcentral/Ripple.git" ] ripple_sdk = { path = "../sdk" } diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index f71feb63a..cf863a8c7 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -256,6 +256,9 @@ impl JsonRpcApiRequest { self.id = Some(id); self } + pub fn as_json(&self) ->serde_json::Value { + serde_json::to_value(self).unwrap_or_default() + } } impl From for RpcRequest { fn from(request: JsonRpcApiRequest) -> Self { From f25f977fecb1df0a056c65bcdcb2e1cb539e1073 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Thu, 26 Jun 2025 08:47:24 -0700 Subject: [PATCH 27/46] feat: jsonrpcapiresponse from value --- core/main/Cargo.toml | 4 ++-- core/main/src/broker/service_broker.rs | 10 +++++----- core/sdk/src/api/gateway/rpc_gateway_api.rs | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index a80ae4e43..612c2a480 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -74,8 +74,8 @@ openrpc_validator = { path = "../../openrpc_validator" } proc-macro2.workspace = true #ssda_service = {path = "../../../ssda/ssda_service/"} #ssda_types = {path = "../../../ssda/ssda_types/"} -ssda_service = { git = "ssh://git@github.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_service" } -ssda_types= { git = "ssh://git@github.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_types" } +ssda_service = { git = "ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_service" } +ssda_types= { git = "ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git", branch = "main", subdir = "ssda_types" } [patch. "https://github.com/rdkcentral/Ripple.git" ] ripple_sdk = { path = "../sdk" } diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 5f7ddcd46..e9c8e9fbc 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -85,12 +85,12 @@ impl EndpointBroker for ServiceBroker { ServiceRoutingResponse::Success(response) => { info!( "ServiceBroker received success response: {:?}", - response + response.response ); - let win = JsonRpcApiResponse::default() - .with_id(response.request_id.request_id) - .with_result(Some(response.response)) - .as_bytes(); + let json_rpc_response = + JsonRpcApiResponse::from_value(response.response).unwrap(); + let win: Vec = json_rpc_response.to_string().into_bytes(); + info!("ServiceBroker sending response: {:?}", win); send_broker_response(&callback, &request, &win).await; } } diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index cf863a8c7..2e7437f7d 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -256,7 +256,7 @@ impl JsonRpcApiRequest { self.id = Some(id); self } - pub fn as_json(&self) ->serde_json::Value { + pub fn as_json(&self) -> serde_json::Value { serde_json::to_value(self).unwrap_or_default() } } @@ -412,6 +412,9 @@ impl JsonRpcApiResponse { params: None, } } + pub fn from_value(value: Value) -> Result { + serde_json::from_value::(value) + } pub fn update_event_message(&mut self, request: &RpcRequest) { if request.is_rpc_v2() { From 35a60d44597ecf68e4da74b7b5b125b713107c42 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 30 Jun 2025 09:11:22 -0700 Subject: [PATCH 28/46] more --- core/main/src/broker/endpoint_broker.rs | 7 ++- core/main/src/broker/service_broker.rs | 18 +++++- core/main/src/firebolt/firebolt_ws.rs | 70 +++++++++++++++++------ core/sdk/src/api/firebolt/fb_telemetry.rs | 2 +- 4 files changed, 73 insertions(+), 24 deletions(-) diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 9e3dccb68..6f9ad8a98 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -1669,7 +1669,12 @@ impl BrokerOutputForwarder { None }; let parse_result = serde_json::from_slice::(data); - debug!("parse result {:?}", parse_result); + debug!( + "parse result {:?} processing: {:?}, which is: {:?}", + parse_result, + data, + String::from_utf8_lossy(data) + ); if parse_result.is_err() { return Err(RippleError::ParseError); } diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index e9c8e9fbc..af9f3eb9e 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -79,8 +79,12 @@ impl EndpointBroker for ServiceBroker { .with_id(e.request_id.request_id) .with_message(e.error) .to_response(); - send_broker_response(&callback, &request, &err.as_bytes()) - .await; + BrokerOutputForwarder::send_json_rpc_response_to_broker( + err, + callback.clone(), + ); + // send_broker_response(&callback, &request, &err.as_bytes()) + // .await; } ServiceRoutingResponse::Success(response) => { info!( @@ -89,9 +93,17 @@ impl EndpointBroker for ServiceBroker { ); let json_rpc_response = JsonRpcApiResponse::from_value(response.response).unwrap(); + info!( + "ServiceBroker creating JSON-RPC response: {:?}", + json_rpc_response + ); + // Convert the response to let win: Vec = json_rpc_response.to_string().into_bytes(); info!("ServiceBroker sending response: {:?}", win); - send_broker_response(&callback, &request, &win).await; + BrokerOutputForwarder::send_json_rpc_response_to_broker( + json_rpc_response, + callback.clone(), + ); } } } diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index f73e31025..50d3d3ba9 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -31,20 +31,6 @@ use crate::{ use futures::SinkExt; use futures::StreamExt; use jsonrpsee::types::{error::INVALID_REQUEST_CODE, ErrorObject, ErrorResponse, Id}; -use ripple_sdk::{ - api::manifest::extn_manifest::ExtnSymbol, - extn::{ - extn_client_message::{ExtnMessage, ExtnPayload, ExtnResponse}, - extn_id::ExtnId, - }, - framework::ripple_contract::RippleContract, - log::trace, - tokio_tungstenite::{ - tungstenite::{self, Message}, - WebSocketStream, - }, - utils::error::RippleError, -}; use ripple_sdk::{ api::{ gateway::rpc_gateway_api::{ @@ -60,6 +46,24 @@ use ripple_sdk::{ utils::channel_utils::oneshot_send_and_log, uuid::Uuid, }; +use ripple_sdk::{ + api::{ + gateway::rpc_gateway_api::{CallContext, JsonRpcApiRequest}, + manifest::extn_manifest::ExtnSymbol, + }, + chrono::format::format, + extn::{ + extn_client_message::{ExtnMessage, ExtnPayload, ExtnResponse}, + extn_id::ExtnId, + }, + framework::ripple_contract::RippleContract, + log::trace, + tokio_tungstenite::{ + tungstenite::{self, Message}, + WebSocketStream, + }, + utils::error::RippleError, +}; use ripple_sdk::{log::debug, tokio}; use ssda_service::ApiGateway; use ssda_types::gateway::{APIGatewayServiceConnectionDisposition, ApiGatewayServer}; @@ -436,6 +440,7 @@ impl FireboltWs { let (mut sender, mut receiver) = ws_stream.split(); let mut platform_state = state.clone(); let context_clone = ctx.clone(); + let spawn_state = state.clone(); tokio::spawn(async move { while let Some(api_message) = resp_rx.recv().await { @@ -469,11 +474,38 @@ impl FireboltWs { stats.stats_ref, stats.stats.get_total_time() ); - debug!( - "Full Firebolt Split: {:?},{}", - stats.stats_ref, - stats.stats.get_stage_durations() - ); + if let Some(stats_ref) = stats.stats_ref { + let split = format!( + "Firebolt Split: {:?},{}", + stats_ref.clone(), + stats.stats.get_total_time() + ); + let request = JsonRpcApiRequest::new( + "telemetry.event".to_string(), + Some(serde_json::json!({ + "payload": split, + + })), + ); + let request = request.as_json().to_string(); + debug!("telemetry event request: {}", request); + + let rpc_request = RpcRequest::new( + String::from("telemetry.event"), + request, + CallContext::default(), + ); + spawn_state + .endpoint_state + .handle_brokerage(rpc_request, None, None, vec![], None, vec![]) + .await; + debug!( + "Full Firebolt Split: {:?},{}", + stats_ref, + stats.stats.get_stage_durations() + ); + } + platform_state .metrics .remove_api_stats(&api_message.request_id); diff --git a/core/sdk/src/api/firebolt/fb_telemetry.rs b/core/sdk/src/api/firebolt/fb_telemetry.rs index 37586fc1a..bf057312a 100644 --- a/core/sdk/src/api/firebolt/fb_telemetry.rs +++ b/core/sdk/src/api/firebolt/fb_telemetry.rs @@ -225,7 +225,7 @@ pub struct TelemetryUtil; impl TelemetryUtil { pub fn send_telemetry(client: &ExtnClient, payload: TelemetryPayload) { if let Err(e) = client.request_transient(RpcRequest::get_new_internal( - "ripple.sendTelemetry".to_owned(), + "y".to_owned(), Some(serde_json::to_value(payload).unwrap()), )) { error!("Error sending telemetry {:?}", e); From a9d9004d79c23ad86dcafaf2661cc5771e2ba8e9 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 30 Jun 2025 10:25:27 -0700 Subject: [PATCH 29/46] json map parsing fix --- core/sdk/src/api/gateway/rpc_gateway_api.rs | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index 2e7437f7d..9e545d0f5 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -17,7 +17,7 @@ use jsonrpsee::types::ErrorObject; use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; +use serde_json::{json, Map, Value}; use tokio::sync::{mpsc, oneshot}; use uuid::Uuid; @@ -690,18 +690,10 @@ impl RpcRequest { } pub fn get_params_as_map(&self) -> Option { if let Ok(params) = serde_json::from_str::(&self.params_json.clone()) { - let params = params.as_array().unwrap_or(&vec![]).to_vec(); - let mut params_map = serde_json::Map::new(); - for param in ¶ms { - let f = param.as_object().unwrap(); - params_map.extend(f.clone()); - } - if params_map.is_empty() { - return None; - } + let params_map: Map = params.as_object().unwrap_or(&Map::new()).clone(); + return Some(Value::Object(params_map)); } - return None; } @@ -1102,4 +1094,14 @@ mod tests { let request = serde_json::from_str::(&new.params_json).unwrap(); assert!(!request.listen); } + #[test] + fn test_params_as_map() { + let mut rpc_request = RpcRequest::mock(); + rpc_request.params_json = r#"{"param1": {"key": "value"}}"#.to_string(); + let params = rpc_request.get_params_as_map().unwrap(); + assert!(params.is_object()); + let map = params.as_object().unwrap(); + assert!(map.contains_key("param1")); + assert_eq!(map.get("param1").unwrap(), &json!({"key": "value"})); + } } From 1b367d0ce3b257663fc965f258b83aaa636fd1ba Mon Sep 17 00:00:00 2001 From: bobra200 Date: Tue, 1 Jul 2025 14:07:01 -0700 Subject: [PATCH 30/46] feat: send metrics to t2 service --- core/main/src/firebolt/firebolt_ws.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 50d3d3ba9..26fdca888 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -476,33 +476,26 @@ impl FireboltWs { ); if let Some(stats_ref) = stats.stats_ref { let split = format!( - "Firebolt Split: {:?},{}", + "Full Firebolt Split: {:?},{}", stats_ref.clone(), - stats.stats.get_total_time() - ); - let request = JsonRpcApiRequest::new( - "telemetry.event".to_string(), - Some(serde_json::json!({ - "payload": split, - - })), + stats.stats.get_stage_durations() ); - let request = request.as_json().to_string(); - debug!("telemetry event request: {}", request); + let rpc_request = RpcRequest::new( String::from("telemetry.event"), - request, + serde_json::json!({ + "payload": split, + }).to_string(), CallContext::default(), ); + spawn_state .endpoint_state .handle_brokerage(rpc_request, None, None, vec![], None, vec![]) .await; debug!( - "Full Firebolt Split: {:?},{}", - stats_ref, - stats.stats.get_stage_durations() + "{}", split ); } From 6ddfb1916f7c50e2f69583a3d9af190acae04601 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Thu, 3 Jul 2025 07:06:11 -0700 Subject: [PATCH 31/46] checkpoint: before 2nd attempt at ripple_sdk modularity --- Cargo.lock | 343 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 271 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 706224dc0..7f2f7b9e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,12 +90,56 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + [[package]] name = "anyhow" version = "1.0.98" @@ -339,7 +383,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -350,9 +394,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" @@ -528,9 +572,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecount" @@ -671,6 +715,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -682,15 +732,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.11" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" dependencies = [ "encode_unicode", "libc", "once_cell", "unicode-width 0.2.1", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -769,9 +819,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -883,7 +933,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -937,6 +987,29 @@ dependencies = [ "regex", ] +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equator" version = "0.4.2" @@ -954,7 +1027,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -965,12 +1038,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1200,7 +1273,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -1341,7 +1414,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.9.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -1350,9 +1423,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -1360,7 +1433,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.9.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -1575,7 +1648,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.10", + "h2 0.4.11", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -1773,9 +1846,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", @@ -1801,20 +1874,20 @@ dependencies = [ "proc-macro2", "quote", "strum 0.27.1", - "syn 2.0.103", + "syn 2.0.104", "thiserror 2.0.12", ] [[package]] name = "indicatif" -version = "0.17.11" +version = "0.17.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +checksum = "4adb2ee6ad319a912210a36e56e3623555817bcc877a7e6e8802d1d69c4d8056" dependencies = [ "console", - "number_prefix", "portable-atomic", "unicode-width 0.2.1", + "unit-prefix", "web-time", ] @@ -1825,7 +1898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", - "indexmap 2.9.0", + "indexmap 2.10.0", "is-terminal", "itoa", "log", @@ -1862,6 +1935,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "iso8601" version = "0.6.3" @@ -1939,7 +2018,7 @@ dependencies = [ "ahash", "dyn-clone", "hifijson", - "indexmap 2.9.0", + "indexmap 2.10.0", "jaq-syn", "once_cell", "serde_json", @@ -1973,6 +2052,30 @@ dependencies = [ "serde", ] +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "jobserver" version = "0.1.33" @@ -2116,7 +2219,7 @@ dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -2339,9 +2442,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ "bitflags 2.9.1", "libc", @@ -2405,7 +2508,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -2569,7 +2672,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -2738,12 +2841,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "object" version = "0.36.7" @@ -2759,6 +2856,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "onig" version = "6.5.1" @@ -3078,7 +3181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.9.0", + "indexmap 2.10.0", ] [[package]] @@ -3142,7 +3245,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -3181,7 +3284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d77244ce2d584cd84f6a15f86195b8c9b2a0dfbfd817c09e0464244091a58ed" dependencies = [ "base64 0.22.1", - "indexmap 2.9.0", + "indexmap 2.10.0", "quick-xml 0.37.5", "serde", "time", @@ -3208,6 +3311,15 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.2" @@ -3645,7 +3757,7 @@ dependencies = [ [[package]] name = "ripple_sdk" version = "1.1.0" -source = "git+https://github.com/rdkcentral/Ripple.git?branch=ssda#3e7a48a114e3b1d31845dcbb283384394d21f889" +source = "git+https://github.com/rdkcentral/Ripple.git?branch=ssda#a9d9004d79c23ad86dcafaf2661cc5771e2ba8e9" dependencies = [ "async-trait", "chrono", @@ -3713,7 +3825,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.103", + "syn 2.0.104", "unicode-ident", ] @@ -3929,7 +4041,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -3990,7 +4102,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "itoa", "ryu", "serde", @@ -4019,7 +4131,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4172,9 +4284,10 @@ dependencies = [ [[package]] name = "ssda_service" version = "0.1.0" -source = "git+ssh://git@github.com/bobra200_comcast/ssda.git?branch=main#10562c88f7bacda9895c28047f8d36e99123525d" +source = "git+ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git?branch=main#33ccf6af0d71adb30dcacf7c1f5aa9edb4ee4202" dependencies = [ "async-trait", + "env_logger", "futures-util", "http 0.2.12", "log", @@ -4190,9 +4303,10 @@ dependencies = [ [[package]] name = "ssda_types" version = "0.1.0" -source = "git+ssh://git@github.com/bobra200_comcast/ssda.git?branch=main#10562c88f7bacda9895c28047f8d36e99123525d" +source = "git+ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git?branch=main#33ccf6af0d71adb30dcacf7c1f5aa9edb4ee4202" dependencies = [ "async-trait", + "env_logger", "futures-util", "http 0.2.12", "jsonrpsee 0.24.9", @@ -4268,7 +4382,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4323,9 +4437,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -4346,7 +4460,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4472,7 +4586,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4483,7 +4597,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4601,7 +4715,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4679,7 +4793,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "toml_datetime", "winnow 0.5.40", ] @@ -4690,7 +4804,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", @@ -4797,7 +4911,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -4885,6 +4999,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unit-prefix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -4926,6 +5046,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.17.0" @@ -5024,7 +5150,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -5059,7 +5185,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5146,7 +5272,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -5176,7 +5302,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5187,7 +5313,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5241,6 +5367,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -5265,13 +5400,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -5284,6 +5435,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -5296,6 +5453,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -5308,12 +5471,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5326,6 +5501,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5338,6 +5519,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -5350,6 +5537,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5362,6 +5555,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.5.40" @@ -5407,9 +5606,9 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "xattr" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" +checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" dependencies = [ "libc", "rustix 1.0.7", @@ -5441,7 +5640,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -5462,7 +5661,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] @@ -5482,7 +5681,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", "synstructure", ] @@ -5516,7 +5715,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.103", + "syn 2.0.104", ] [[package]] From 78aa84e5eef0b2910ff6156b12b2f6ac8c8f3008 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Thu, 3 Jul 2025 07:45:48 -0700 Subject: [PATCH 32/46] feat: ssda into ripple monorepo for ease of use --- Cargo.lock | 513 ++++++++++--- Cargo.toml | 5 +- ssda/.gitignore | 1 + ssda/Cargo.toml | 5 + ssda/README.md | 4 + ssda/example-service/Cargo.toml | 29 + ssda/example-service/flamegraph.svg | 0 ssda/example-service/src/main.rs | 121 ++++ ssda/rust-toolchain.toml | 2 + ssda/ssda_client/Cargo.toml | 14 + ssda/ssda_client/src/lib.rs | 48 ++ ssda/ssda_service/Cargo.toml | 20 + ssda/ssda_service/src/lib.rs | 731 +++++++++++++++++++ ssda/ssda_types/Cargo.toml | 21 + ssda/ssda_types/src/api_gateway_client.rs | 1 + ssda/ssda_types/src/api_gateway_server.rs | 1 + ssda/ssda_types/src/lib.rs | 837 ++++++++++++++++++++++ ssda/ssda_types/src/service_api.rs | 1 + 18 files changed, 2261 insertions(+), 93 deletions(-) create mode 100644 ssda/.gitignore create mode 100644 ssda/Cargo.toml create mode 100644 ssda/README.md create mode 100644 ssda/example-service/Cargo.toml create mode 100644 ssda/example-service/flamegraph.svg create mode 100644 ssda/example-service/src/main.rs create mode 100644 ssda/rust-toolchain.toml create mode 100644 ssda/ssda_client/Cargo.toml create mode 100644 ssda/ssda_client/src/lib.rs create mode 100644 ssda/ssda_service/Cargo.toml create mode 100644 ssda/ssda_service/src/lib.rs create mode 100644 ssda/ssda_types/Cargo.toml create mode 100644 ssda/ssda_types/src/api_gateway_client.rs create mode 100644 ssda/ssda_types/src/api_gateway_server.rs create mode 100644 ssda/ssda_types/src/lib.rs create mode 100644 ssda/ssda_types/src/service_api.rs diff --git a/Cargo.lock b/Cargo.lock index 7f2f7b9e4..240e3bc18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "cipher", "cpufeatures", ] @@ -34,7 +34,7 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "getrandom 0.3.3", "once_cell", "serde", @@ -87,7 +87,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -263,7 +263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock 3.4.0", - "cfg-if", + "cfg-if 1.0.1", "concurrent-queue", "futures-io", "futures-lite", @@ -316,7 +316,7 @@ dependencies = [ "async-signal", "async-task", "blocking", - "cfg-if", + "cfg-if 1.0.1", "event-listener 5.4.0", "futures-lite", "rustix 1.0.7", @@ -332,7 +332,7 @@ dependencies = [ "async-io", "async-lock 3.4.0", "atomic-waker", - "cfg-if", + "cfg-if 1.0.1", "futures-core", "futures-io", "rustix 1.0.7", @@ -407,7 +407,7 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes", + "bytes 1.10.1", "futures-util", "http 0.2.12", "http-body 0.4.6", @@ -433,7 +433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes", + "bytes 1.10.1", "futures-util", "http 0.2.12", "http-body 0.4.6", @@ -450,7 +450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.1", "libc", "miniz_oxide", "object", @@ -529,13 +529,25 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -544,7 +556,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -576,6 +597,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytecount" version = "0.6.9" @@ -594,6 +621,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.10.1" @@ -634,6 +671,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.1" @@ -771,7 +814,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", ] [[package]] @@ -789,7 +832,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", ] [[package]] @@ -829,7 +872,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -884,13 +927,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -910,7 +962,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "dirs-sys-next", ] @@ -922,7 +974,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -975,7 +1027,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", ] [[package]] @@ -1098,6 +1150,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fancy-regex" version = "0.11.0" @@ -1129,7 +1187,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "libc", "libredox", "windows-sys 0.59.0", @@ -1144,7 +1202,7 @@ dependencies = [ "cc", "lazy_static", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1201,9 +1259,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", ] +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.31" @@ -1321,6 +1395,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1331,13 +1414,24 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.1", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", @@ -1350,7 +1444,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", @@ -1408,7 +1502,7 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes", + "bytes 1.10.1", "fnv", "futures-core", "futures-sink", @@ -1428,7 +1522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", - "bytes", + "bytes 1.10.1", "fnv", "futures-core", "futures-sink", @@ -1525,7 +1619,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes", + "bytes 1.10.1", "fnv", "itoa", ] @@ -1536,7 +1630,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes", + "bytes 1.10.1", "fnv", "itoa", ] @@ -1547,7 +1641,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes", + "bytes 1.10.1", "http 0.2.12", "pin-project-lite", ] @@ -1558,7 +1652,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes", + "bytes 1.10.1", "http 1.3.1", ] @@ -1568,7 +1662,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ - "bytes", + "bytes 1.10.1", "futures-core", "http 1.3.1", "http-body 1.0.1", @@ -1621,7 +1715,7 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes", + "bytes 1.10.1", "futures-channel", "futures-core", "futures-util", @@ -1645,7 +1739,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "bytes", + "bytes 1.10.1", "futures-channel", "futures-util", "h2 0.4.11", @@ -1693,7 +1787,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "bytes", + "bytes 1.10.1", "futures-core", "http 1.3.1", "http-body 1.0.1", @@ -1915,7 +2009,16 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", ] [[package]] @@ -2163,7 +2266,7 @@ dependencies = [ "hyper 0.14.27", "jsonrpsee-types 0.16.3", "parking_lot", - "rand", + "rand 0.8.5", "rustc-hash 1.1.0", "serde", "serde_json", @@ -2180,14 +2283,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" dependencies = [ "async-trait", - "bytes", + "bytes 1.10.1", "futures-util", "http 1.3.1", "http-body 1.0.1", "http-body-util", "jsonrpsee-types 0.24.9", "parking_lot", - "rand", + "rand 0.8.5", "rustc-hash 2.1.1", "serde", "serde_json", @@ -2337,6 +2440,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2383,6 +2496,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "lenient_semver" version = "0.4.2" @@ -2430,8 +2549,8 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if", - "winapi", + "cfg-if 1.0.1", + "winapi 0.3.9", ] [[package]] @@ -2541,7 +2660,7 @@ dependencies = [ "openrpc_validator", "proc-macro2", "querystring", - "rand", + "rand 0.8.5", "regex", "ripple_sdk 1.1.0 (git+https://github.com/rdkcentral/Ripple.git?branch=ssda)", "ripple_tdk", @@ -2550,8 +2669,8 @@ dependencies = [ "serde", "serde_json", "serial_test", - "ssda_service", - "ssda_types", + "ssda_service 0.1.0 (git+ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git?branch=main)", + "ssda_types 0.1.0 (git+ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git?branch=main)", "strum 0.24.1", "strum_macros 0.24.3", "url", @@ -2612,6 +2731,25 @@ dependencies = [ "adler2", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "1.0.4" @@ -2623,6 +2761,30 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "mock_app_gw" version = "0.1.0" @@ -2655,7 +2817,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "downcast", "fragile", "mockall_derive", @@ -2669,7 +2831,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "proc-macro2", "quote", "syn 2.0.104", @@ -2681,7 +2843,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ - "bytes", + "bytes 1.10.1", "encoding_rs", "futures-util", "http 0.2.12", @@ -2701,6 +2863,17 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -2714,7 +2887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.1", "libc", ] @@ -2743,7 +2916,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2884,6 +3057,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2933,7 +3112,7 @@ dependencies = [ "anyhow", "async-trait", "backtrace", - "bytes", + "bytes 1.10.1", "chrono", "flate2", "futures-util", @@ -2974,7 +3153,7 @@ checksum = "016334b4a70ecb22f448267fd817003f7c09ffda5165aa31e9fe4ede5091aa07" dependencies = [ "anyhow", "async-trait", - "bytes", + "bytes 1.10.1", "futures", "itertools 0.10.5", "lazy_static", @@ -3001,7 +3180,7 @@ dependencies = [ "ansi_term", "anyhow", "base64 0.21.7", - "bytes", + "bytes 1.10.1", "chrono", "difference", "futures", @@ -3018,7 +3197,7 @@ dependencies = [ "onig", "pact-plugin-driver", "pact_models", - "rand", + "rand 0.8.5", "reqwest", "semver", "serde", @@ -3039,7 +3218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daaea27b75fbc1bf7740562518a77933f8bb2ba5b0d4115f61f52691553fbabd" dependencies = [ "anyhow", - "bytes", + "bytes 1.10.1", "futures", "hyper 0.14.27", "hyper-rustls", @@ -3071,7 +3250,7 @@ dependencies = [ "anyhow", "ariadne", "base64 0.21.7", - "bytes", + "bytes 1.10.1", "chrono", "chrono-tz", "fs2", @@ -3088,7 +3267,7 @@ dependencies = [ "nom 7.1.3", "onig", "parse-zoneinfo", - "rand", + "rand 0.8.5", "rand_regex", "regex", "regex-syntax 0.6.29", @@ -3123,7 +3302,7 @@ version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "libc", "redox_syscall", "smallvec", @@ -3146,7 +3325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -3210,7 +3389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -3296,7 +3475,7 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "concurrent-queue", "hermit-abi", "pin-project-lite", @@ -3343,7 +3522,7 @@ checksum = "38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187" dependencies = [ "aligned-vec", "backtrace", - "cfg-if", + "cfg-if 1.0.1", "findshlibs", "inferno", "libc", @@ -3442,7 +3621,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes", + "bytes 1.10.1", "prost-derive", ] @@ -3452,7 +3631,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ - "bytes", + "bytes 1.10.1", "heck 0.4.1", "itertools 0.10.5", "lazy_static", @@ -3529,6 +3708,19 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -3536,8 +3728,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -3547,7 +3749,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -3559,13 +3770,22 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_regex" version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b2a9fe2d7d9eeaf3279d1780452a5bbd26b31b27938787ef1c3e930d1e9cfbd" dependencies = [ - "rand", + "rand 0.8.5", "regex-syntax 0.6.29", ] @@ -3658,7 +3878,7 @@ checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", - "bytes", + "bytes 1.10.1", "encoding_rs", "futures-core", "futures-util", @@ -3710,7 +3930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.1", "getrandom 0.2.16", "libc", "untrusted", @@ -3818,7 +4038,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "glob", "proc-macro2", "quote", @@ -4134,6 +4354,18 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -4141,10 +4373,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.1", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.1", ] [[package]] @@ -4153,7 +4385,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "cpufeatures", "digest 0.10.7", ] @@ -4170,7 +4402,7 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "cpufeatures", "digest 0.10.7", ] @@ -4221,7 +4453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4241,13 +4473,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes", + "bytes 1.10.1", "futures", "http 0.2.12", "httparse", "log", - "rand", - "sha-1", + "rand 0.8.5", + "sha-1 0.9.8", ] [[package]] @@ -4257,12 +4489,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" dependencies = [ "base64 0.22.1", - "bytes", + "bytes 1.10.1", "futures", "http 1.3.1", "httparse", "log", - "rand", + "rand 0.8.5", "sha1", ] @@ -4281,6 +4513,38 @@ dependencies = [ "lock_api", ] +[[package]] +name = "ssda_client" +version = "0.1.0" +dependencies = [ + "jsonrpsee 0.24.9", + "log", + "ripple_sdk 1.1.0", + "serde", + "ssda_types 0.1.0", + "tokio", + "url", + "ws", +] + +[[package]] +name = "ssda_service" +version = "0.1.0" +dependencies = [ + "async-trait", + "env_logger", + "futures-util", + "http 0.2.12", + "log", + "mockall", + "ripple_sdk 1.1.0", + "serde_json", + "ssda_types 0.1.0", + "tokio", + "tokio-tungstenite", + "url", +] + [[package]] name = "ssda_service" version = "0.1.0" @@ -4294,7 +4558,26 @@ dependencies = [ "mockall", "ripple_sdk 1.1.0 (git+https://github.com/rdkcentral/Ripple.git?branch=ssda)", "serde_json", - "ssda_types", + "ssda_types 0.1.0 (git+ssh://git@fireboltghec.comcast.com/bobra200_comcast/ssda.git?branch=main)", + "tokio", + "tokio-tungstenite", + "url", +] + +[[package]] +name = "ssda_types" +version = "0.1.0" +dependencies = [ + "async-trait", + "env_logger", + "futures-util", + "http 0.2.12", + "jsonrpsee 0.24.9", + "mockall", + "pprof", + "ripple_sdk 1.1.0", + "serde", + "serde_json", "tokio", "tokio-tungstenite", "url", @@ -4469,13 +4752,13 @@ version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "core-foundation-sys", "libc", "ntapi", "once_cell", "rayon", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4531,7 +4814,7 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4686,9 +4969,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", - "bytes", + "bytes 1.10.1", "libc", - "mio", + "mio 1.0.4", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -4758,7 +5041,7 @@ version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ - "bytes", + "bytes 1.10.1", "futures-core", "futures-io", "futures-sink", @@ -4827,7 +5110,7 @@ dependencies = [ "async-trait", "axum", "base64 0.21.7", - "bytes", + "bytes 1.10.1", "futures-core", "futures-util", "h2 0.3.26", @@ -4870,7 +5153,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -4951,12 +5234,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", - "bytes", + "bytes 1.10.1", "data-encoding", "http 0.2.12", "httparse", "log", - "rand", + "rand 0.8.5", "sha1", "thiserror 1.0.69", "url", @@ -5113,6 +5396,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -5134,7 +5423,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -5160,7 +5449,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "js-sys", "once_cell", "wasm-bindgen", @@ -5250,6 +5539,12 @@ dependencies = [ "rustix 0.38.44", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -5260,6 +5555,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -5585,7 +5886,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "windows-sys 0.48.0", ] @@ -5604,6 +5905,34 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "ws" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "httparse", + "log", + "mio 0.6.23", + "mio-extras", + "rand 0.7.3", + "sha-1 0.8.2", + "slab", + "url", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "xattr" version = "1.5.1" diff --git a/Cargo.toml b/Cargo.toml index 2451dfb84..c3635f69c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,10 @@ members = [ "device/thunder_ripple_sdk", "core/main", "device/mock_device", - "openrpc_validator"] + "openrpc_validator", + "ssda/ssda_types", + "ssda/ssda_client", + "ssda/ssda_service"] [workspace.package] version = "1.1.0" diff --git a/ssda/.gitignore b/ssda/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/ssda/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ssda/Cargo.toml b/ssda/Cargo.toml new file mode 100644 index 000000000..c353a9b97 --- /dev/null +++ b/ssda/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +resolver = "2" +members = [ "example-service", "ssda_client","ssda_service", "ssda_types"] + + diff --git a/ssda/README.md b/ssda/README.md new file mode 100644 index 000000000..d88d2c701 --- /dev/null +++ b/ssda/README.md @@ -0,0 +1,4 @@ +#update ripple_sdk git dependency +``` +cargo update -p ripple_sdk +``` diff --git a/ssda/example-service/Cargo.toml b/ssda/example-service/Cargo.toml new file mode 100644 index 000000000..f2d595994 --- /dev/null +++ b/ssda/example-service/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "example-service" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.88" +serde_json = "1.0.140" +ssda_types = {path="../ssda_types"} +ssda_client = {path = "../ssda_client"} +tokio = "1.44.2" +mockall = "0.13.1" +tokio-websockets = "0.11.4" +log = "0.4.27" +ripple_sdk = { git = "https://github.com/rdkcentral/Ripple.git", branch = "ssda", subdir = "core/sdk" } +#jsonrpsee-server = "0.24.9" +#jsonrpsee-types = "0.24.9" +#jsonrpsee-proc-macros = "0.24.9" +#jsonrpsee-core = "0.24.9" +jsonrpsee = {version= "0.24.9", features= ["server", "macros"] } +pprof = { version = "0.15", features = ["flamegraph"] } +#jsonrpsee = { version = "0.16.3", features = ["server", "macros"] } + +[profile.release] +strip=true +opt-level="z" +codegen-units=1 +lto=true +panic="abort" diff --git a/ssda/example-service/flamegraph.svg b/ssda/example-service/flamegraph.svg new file mode 100644 index 000000000..e69de29bb diff --git a/ssda/example-service/src/main.rs b/ssda/example-service/src/main.rs new file mode 100644 index 000000000..38752f8d7 --- /dev/null +++ b/ssda/example-service/src/main.rs @@ -0,0 +1,121 @@ +use std::fs::File; +use std::{sync::Arc, vec}; + +use async_trait::async_trait; +use jsonrpsee::core::RpcResult; +use jsonrpsee::proc_macros::rpc; +use log::info; +use serde_json::json; +use ssda_client::APIGatewayClientBuilder; +use ssda_types::client::ServiceRequestHandlerImpl; +use ssda_types::service::{ + FireboltMethodHandlerAPIRegistration, FireboltMethodHandlerRegistration, ServiceCall, + ServiceCallErrorResponse, ServiceCallSuccessResponse, ServiceRegistration, +}; +use ssda_types::{JqRule, ServiceId}; + +#[rpc(server)] +pub trait ExampleServiceRpc { + #[method(name = "device.audio")] + async fn audio(&self) -> RpcResult; + #[method(name = "device.make")] + async fn make(&self) -> RpcResult; +} + +#[derive(Debug, Clone)] +pub struct ExampleService {} + +impl ExampleService { + pub fn new() -> Self { + Self {} + } +} + +#[async_trait] +impl ExampleServiceRpcServer for ExampleService { + async fn audio(&self) -> RpcResult { + Ok("Audio response".to_string()) + } + async fn make(&self) -> RpcResult { + Ok("Make response".to_string()) + } +} + +#[async_trait::async_trait] +impl ServiceRequestHandlerImpl for ExampleService { + fn register(&self) -> Vec { + vec![] + } + fn handle_request( + &self, + request: ServiceCall, + ) -> Result { + // Handle the request and return a response + info!("handle_request: handling request {:?}", request); + match request.method.as_str() { + "device.audio" => Ok(ServiceCallSuccessResponse { + request_id: request.request_id, + response: serde_json::json!({ "status": "success" }), + }), + bad_method => { + return Err(ServiceCallErrorResponse { + request_id: request.request_id, + error: format!("Unknown method: {}", bad_method), + }); + } + } + } + fn on_connected(&self) { + println!("example connected") + } + fn on_disconnected(&self) { + println!("disconnected") + } + fn healthy(&self) -> bool { + todo!() + } +} +#[tokio::main] +async fn main() { + let module = ExampleService::new().into_rpc(); + // let request = json!({ + // "jsonrpc": "2.0", + // "id": 1, + // "method": "device.aasdf", + // "params": [] + // }); + // let request= serde_json::to_string(&request).unwrap(); + // let f = module.raw_json_request(&request, 1).await.unwrap(); + // println!("Response: {:?}", f); + + let my_handler = ExampleService::new(); + let mut firebolt_handlers = Vec::new(); + + firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { + firebolt_method: "device.audio".to_string(), + jq_rule: Some(JqRule { + alias: "device.audio".to_string(), + rule: "jq_type".to_string(), + }), + }); + firebolt_handlers.push(FireboltMethodHandlerAPIRegistration { + firebolt_method: "device.make".to_string(), + jq_rule: Some(JqRule { + alias: "device.make".to_string(), + rule: "jq_type".to_string(), + }), + }); + + let registration = ServiceRegistration { + service_id: ServiceId { + service_id: "example".to_string(), + }, + firebolt_handlers: firebolt_handlers, + }; + + let _ = APIGatewayClientBuilder::::new(registration) + .websocket() + .build(module) + .start() + .await; +} diff --git a/ssda/rust-toolchain.toml b/ssda/rust-toolchain.toml new file mode 100644 index 000000000..2e2b8c852 --- /dev/null +++ b/ssda/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.82.0" diff --git a/ssda/ssda_client/Cargo.toml b/ssda/ssda_client/Cargo.toml new file mode 100644 index 000000000..23a554036 --- /dev/null +++ b/ssda/ssda_client/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ssda_client" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = { version = "1", features = ["full"] } +ws = "0.9.2" +log = "0.4" +serde = { version = "1.0", features = ["derive"] } +ssda_types = {path = "../ssda_types"} +url = "2.5.4" +ripple_sdk = { path="../../core/sdk" } +jsonrpsee = {version= "0.24.9", features= ["server", "macros"] } \ No newline at end of file diff --git a/ssda/ssda_client/src/lib.rs b/ssda/ssda_client/src/lib.rs new file mode 100644 index 000000000..e5431ede2 --- /dev/null +++ b/ssda/ssda_client/src/lib.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use jsonrpsee::RpcModule; +use ssda_types::{ + service::{ServiceRegistration, ServiceRequestHandler}, + APIGatewayClient, WebsocketAPIGatewayClient, +}; +pub enum APIGatewayClientTransport { + WebSocket, +} +pub struct APIGatewayClientBuilder { + transport: APIGatewayClientTransport, + service_registration: ServiceRegistration, + rpc_server: Option>, +} + +impl APIGatewayClientBuilder { + pub fn new(service_registration: ServiceRegistration) -> Self { + APIGatewayClientBuilder { + transport: APIGatewayClientTransport::WebSocket, + service_registration, + rpc_server: None, + } + } + pub fn with_service_registration( + &mut self, + service_registration: ServiceRegistration, + ) -> &mut Self { + self.service_registration = service_registration; + self + } + + pub fn websocket(&mut self) -> &mut Self { + // Initialize WebSocket client + self.transport = APIGatewayClientTransport::WebSocket; + self + } + + pub fn build(&self, rpc_server: RpcModule) -> Box { + let methods = rpc_server.clone(); + match self.transport { + APIGatewayClientTransport::WebSocket => Box::new(WebsocketAPIGatewayClient::new( + methods, + self.service_registration.service_id.clone(), + )), + } + } +} diff --git a/ssda/ssda_service/Cargo.toml b/ssda/ssda_service/Cargo.toml new file mode 100644 index 000000000..73737a838 --- /dev/null +++ b/ssda/ssda_service/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "ssda_service" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.88" +serde_json = "1.0.140" +ssda_types = {path="../ssda_types"} + +ripple_sdk = { path="../../core/sdk" } + +tokio = "1.44.2" +mockall = "0.13.1" +tokio-tungstenite = "0.20.1" +http = "0.2.12" +url = "2.5.4" +log = "0.4.27" +futures-util = "0.3.31" +env_logger = "0.11.8" diff --git a/ssda/ssda_service/src/lib.rs b/ssda/ssda_service/src/lib.rs new file mode 100644 index 000000000..9f1d0637c --- /dev/null +++ b/ssda/ssda_service/src/lib.rs @@ -0,0 +1,731 @@ +/* +This is the API gateway, and it meant to be hosted in the main ripple process +*/ + +use std::{collections::HashMap, f32::consts::E, sync::Arc}; + +use futures_util::stream::SplitSink; +use futures_util::stream::StreamExt; +use futures_util::SinkExt; +use http::Uri; +use log::debug; +use log::{error, info}; + +use ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiRequest; +use ripple_sdk::api::rules_engine::{Rule, RuleEngineProvider, RuleTransform}; +use tokio::sync::{mpsc, RwLock}; +pub struct ServiceMap { + service_map: HashMap>, +} +impl ServiceMap { + fn new() -> Self { + Self { + service_map: HashMap::new(), + } + } + fn add_service( + &mut self, + service_id: ServiceId, + registrations: Vec, + ) { + self.service_map.insert(service_id, registrations); + } + fn remove_service(&mut self, service_id: &ServiceId) { + self.service_map.remove(service_id); + } + fn get_registrations( + &self, + service_id: &ServiceId, + ) -> Vec { + self.service_map.get(service_id).unwrap_or(&vec![]).clone() + } + fn get_service_for_method( + &self, + method: &str, + ) -> Option<(ServiceId, FireboltMethodHandlerAPIRegistration)> { + for (service_id, registrations) in self.service_map.iter() { + for registration in registrations.iter() { + if registration.firebolt_method == method { + return Some((service_id.clone(), registration.clone())); + } + } + } + None + } +} +pub struct WebSocketChannels { + pub tx: mpsc::Sender, + pub rx: mpsc::Receiver, +} +pub struct ApiGateway { + pub service_endpoints: Arc>>>, + pub rules_engine: Arc>>, + pub methods_2_services: Arc>, + pub broker_sender: mpsc::Sender, + pub services_2_rxs: + Arc>>>, + pub reply_to_tx: mpsc::Sender, +} +pub enum APIGatewayClientState { + Failed(String), + Connecting, + Registering(APIGatewayServiceRegistrationRequest), + Connected, + Closed, + Message(ServiceRequestId, Value), + ServiceCallFailed(ServiceRequestId, String), +} +type RequestIds2SendersType = Arc< + RwLock< + HashMap>>>>, + >, +>; + +impl ApiGateway { + pub fn new( + rules_engine: Arc>>, + ) -> Self { + let (tx, rx) = mpsc::channel::(32); + let (reply_to_tx, _) = mpsc::channel::(32); + let services_2_rxs = Arc::new(tokio::sync::RwLock::new(HashMap::new())); + + let me = Self { + service_endpoints: Arc::new(tokio::sync::RwLock::new(HashMap::new())), + rules_engine, + methods_2_services: Arc::new(tokio::sync::RwLock::new(ServiceMap::new())), + broker_sender: tx.clone(), + services_2_rxs: services_2_rxs.clone(), + reply_to_tx, + }; + + me.start(rx, Arc::clone(&services_2_rxs)); + + me + } + /* + start the task that handles the service routing requests, and routes them to the appropriate service + */ + + pub fn start( + &self, + mut rx: mpsc::Receiver, + services_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + ) { + let methods_2_services = self.methods_2_services.clone(); + let services_2_rxs = Arc::clone(&services_2_rxes); + tokio::spawn(async move { + while let Some(request) = rx.recv().await { + let methods_2_services = methods_2_services.read().await; + let method = request.payload.method.clone(); + match methods_2_services.get_service_for_method(method.as_str()) { + Some((service_id, _registration)) => { + /* + send the request to the websocket handler for the service + */ + if let Some(service) = services_2_rxs.read().await.get(&service_id) { + let (send, receive) = oneshot::channel::(); + let method = request.payload.method.clone(); + let payload = request.payload.clone(); + debug!("sending rpc request to service: {:?}", payload); + + let payload: JsonRpcApiRequest = payload.into(); + info!( + "------------------ JSONRPC Request: {:?}, from rpc_request: {:?}", + payload, payload + ); + let websocket_request = WebsocketServiceRequest { + method: method.clone(), + request_id: request.request_id.clone(), + payload: payload.as_json(), + respond_to: send, + }; + info!( + "------------------ Sending WebsocketServiceRequest to service:{:?}", + websocket_request + ); + let _ = service.send(websocket_request).await; + match receive.await { + Ok(response) => { + info!("start Received response from service: {:?}", response); + match response { + WebsocketServiceResponse::Success(request_id, result) => { + info!("Received success response: {:?}", result); + // Send the response back to the broker + let _ = request.respond_to.send( + ServiceRoutingResponse::Success( + ServiceRoutingSuccessResponse { + request_id, + response: result, + }, + ), + ); + } + WebsocketServiceResponse::Error(request_id, error) => { + info!("Received error response: {:?}", error); + // Send the error response back to the broker + let _ = request.respond_to.send( + ServiceRoutingResponse::Error( + ServiceRoutingErrorResponse { + request_id, + error, + }, + ), + ); + } + } + } + Err(e) => { + error!("Failed to receive response from service: {:?}", e); + } + } + } else { + error!( + "else No service sender found for method: {:?} in {:?} ", + method, + services_2_rxs.read().await + ); + } + } + + None => { + error!("None No service found for method: {:?}", method); + } + } + } + }); + } + /// This function is used to check if the given URI is a service URL + pub fn is_apigateway_connection( + uri: &http::Uri, + ) -> Result { + // Check if the URI is a service URL + // This is a placeholder implementation + if !uri.path().starts_with("/apigateway") { + return Err(APIGatewayServiceConnectionError::NotAService); + } + + if let Some(query) = uri.query() { + let query_pairs = form_urlencoded::parse(query.as_bytes()); + for (key, value) in query_pairs { + if key == "serviceId" { + return Ok(APIGatewayServiceConnectionDisposition::Accept( + ServiceId::new(value.to_string()), + )); + } + } + } + Err(APIGatewayServiceConnectionError::NotAService) + } + pub fn classify_message(message: &Message) -> APIGatewayClientState { + // Classify the message based on its content + // This is a placeholder implementation + if let Message::Text(text) = message { + let parsed: Result = serde_json::from_str(text); + info!("Parsed message: {:?}", parsed); + if let Ok(msg) = parsed { + match msg { + APIClientMessages::Register(registration) => { + return APIGatewayClientState::Registering(registration); + } + + APIClientMessages::ServiceCallSuccessResponse(succcess) => { + return APIGatewayClientState::Message( + succcess.request_id, + succcess.response, + ) + } + APIClientMessages::ServiceCallErrorResponse(error) => { + return APIGatewayClientState::ServiceCallFailed( + error.request_id, + error.error, + ); + } + e => { + info!("Classified message: {:?}", e); + return APIGatewayClientState::Failed(format!( + "Unknown message type: {:?}", + e + )); + } + } + } + } else if let Message::Close(_) = message { + return APIGatewayClientState::Closed; + } + + APIGatewayClientState::Failed(format!("Failed to parse message: {}", message)) + } + fn jq_rule_to_string(jq_rule: Option) -> Option { + if let Some(rule) = jq_rule { + return Some(rule.rule); + } + None + } + async fn handle_registration( + service_id: ServiceId, + rule_engine: Arc>>, + registration: &APIGatewayServiceRegistrationRequest, + methods_2_services: Arc>, + ) { + let rules = ®istration.firebolt_handlers; + + let mut rule_engine = rule_engine.write().await; + + for handle_rule in rules { + let rule = Rule { + alias: handle_rule.firebolt_method.clone(), + transform: RuleTransform::default(), + filter: Self::jq_rule_to_string(handle_rule.jq_rule.clone()), + event_handler: None, + endpoint: Some("service".to_string()), + sources: None, + }; + /* + todo, save off existing rule for rollback (if it exists) + */ + rule_engine.add_rule(rule); + } + methods_2_services + .write() + .await + .add_service(service_id.clone(), rules.clone()); + } + async fn handle_unregister( + service_id: &ServiceId, + methods_2_services: Arc>, + rule_engine: Arc>>, + ) { + let mut rule_engine = rule_engine.write().await; + let aliases = methods_2_services + .read() + .await + .get_registrations(service_id); + for handle_rule in aliases { + rule_engine.remove_rule(&handle_rule.firebolt_method); + } + methods_2_services.write().await.remove_service(service_id); + } + + async fn handle_message( + message: Result, + tx: &mut SplitSink, Message>, + service_id: &ServiceId, + rule_engine: Arc>>, + methods_2_services: Arc>, + services_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + bridge_tx: mpsc::Sender, + ) { + match message { + Ok(msg) => { + info!("gateway server received websocket message: {:?}", msg); + match Self::classify_message(&msg) { + APIGatewayClientState::Registering(registration) => { + info!("Registering service: {:?}", registration); + Self::handle_unregister( + service_id, + methods_2_services.clone(), + rule_engine.clone(), + ) + .await; + + Self::handle_registration( + service_id.clone(), + rule_engine.clone(), + ®istration, + methods_2_services.clone(), + ) + .await; + + let response: APIGatewayServiceRegistrationResponse = registration.into(); + let response = APIClientMessages::Registered(response); + let msg = serde_json::to_string(&response); + match msg { + Ok(msg) => { + let _ = tx.send(Message::Text(msg.clone())).await; + info!("Sending registration response: {:?}", msg); + } + Err(e) => { + error!("Failed to serialize registration response: {:?}", e); + } + } + + info!("Sent registration response: {:?}", response) + } + APIGatewayClientState::Failed(e) => { + error!("Failed to classify message {} err {},{}", msg, E, e); + + let _ = tx.send(Message::Close(None)).await; + let _ = tx.close().await; + } + APIGatewayClientState::Closed => { + info!("Client closed connection"); + Self::handle_unregister(service_id, methods_2_services, rule_engine).await; + let _ = tx.close().await; + } + APIGatewayClientState::Message(request_id, msg) => { + info!( + "got msg from websocket: {} for request {:?}", + msg, request_id + ); + let _ = bridge_tx + .send(WebsocketServiceResponse::Success(request_id, msg)) + .await; + } + APIGatewayClientState::ServiceCallFailed(id, error) => { + info!("Service call failed: {:?}", error); + let fail = WebsocketServiceResponse::Error(id, error); + let _ = bridge_tx.send(fail).await; + } + + _ => { + info!("handle_message: Unknown message type: {:?}", msg); + let _ = tx.send(Message::Close(None)).await; + let _ = tx.close().await; + } + } + } + Err(e) => { + /* + for now, just treat all errors as fatal and cleanup, drop tx and let client reconnect + */ + info!("Client closed connection. Error: {:?}", e); + info!("Unregistering service: {:?}", service_id); + + Self::handle_unregister(service_id, methods_2_services, rule_engine.clone()).await; + let _ = services_2_rxes.write().await.remove(service_id); + + let _ = tx.close().await; + } + } + } + /* + Spawn a task to handle exactly one service connection over websocket (for now, maybe dbus later) + */ + + async fn handle_service_connection( + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + rule_engine: Arc>>, + methods_2_services: Arc>, + mut websocket_service_request_rx: mpsc::Receiver, + service_2_rxes: Arc< + tokio::sync::RwLock>>, + >, + ) -> Result<(), APIGatewayServiceConnectionError> { + info!("Handling service connection: {:?}", service_id); + + let (mut websocket_tx, mut websocket_rx) = ws_stream.split(); + + let (bridge_tx, mut bridge_rx) = mpsc::channel::(32); + + let requests_2_requestors: RequestIds2SendersType = Arc::new(RwLock::new(HashMap::new())); + + loop { + tokio::select! { + // Handle incoming messages from the WebSocket stream + Some(message) = websocket_rx.next() => { + info!("gateway Received websocket message: {:?}", message); + Self::handle_message( + message, + &mut websocket_tx, + &service_id, + rule_engine.clone(), + methods_2_services.clone(), + service_2_rxes.clone(), + bridge_tx.clone(), + ).await + } + // this is a request from the main api gateway thread that needs to be sent to the service + //via the websocket + Some(request) = websocket_service_request_rx.recv() => { + let request_id = request.request_id.clone(); + let sender_entry = Arc::new(Mutex::new(Some(request.respond_to))); + requests_2_requestors.write().await.insert(request_id.clone(), sender_entry.clone()); + info!("Received request to send to service: {:?} with method: {:?} and payload: {:?}", service_id, request.method, request.payload); + + let service_call = APIClientMessages::ServiceCall( + ServiceCall { + method: request.method.clone(), + request_id, + payload: request.payload, + } + ); + debug!("Sending service call: {:?}", service_call); + match serde_json::to_string(&service_call) { + Ok(service_call) => { + let _ = websocket_tx.send(Message::Text(service_call)).await; + } + Err(e) => { + error!("Failed to serialize service call: {:?}", e); + let fail = WebsocketServiceResponse::Error(request.request_id, e.to_string()); + let _ = bridge_tx.send(fail).await; + continue; + } + } + } + Some(bridge_message) = bridge_rx.recv() => { + info!("Received message from bridge: {:?}", bridge_message); + + let id = bridge_message.get_id(); + + if let Some(requestor) = requests_2_requestors.write().await.remove(&id) { + let mut requestor_lock = requestor.lock().await; + if let Some(sender) = requestor_lock.take() { + let _ = sender.send(bridge_message.clone()); + } + } + } + else => { + info!("Service connection closed: {:?}", service_id); + // Handle service disconnection + // Clean up resources, etc. + Self::handle_unregister( + &service_id, + methods_2_services.clone(), + rule_engine.clone(), + ).await; + let _ = service_2_rxes + .write() + .await + .remove(&service_id); + break Ok(()); + } + } + } + } +} +use serde_json::Value; +use ssda_types::gateway::{ + APIGatewayServiceConnectionDisposition, APIGatewayServiceConnectionError, ApiGatewayServer, + ServiceRoutingErrorResponse, ServiceRoutingRequest, ServiceRoutingResponse, + ServiceRoutingSuccessResponse, +}; +use ssda_types::service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, APIGatewayServiceRegistrationResponse, + FireboltMethodHandlerAPIRegistration, ServiceCall, WebsocketServiceRequest, + WebsocketServiceResponse, +}; +use ssda_types::{JqRule, ServiceId, ServiceRequestId}; +use tokio::net::TcpStream; +use tokio::sync::{oneshot, Mutex}; +use tokio_tungstenite::tungstenite::{Error, Message}; +use tokio_tungstenite::WebSocketStream; +use url::form_urlencoded; + +pub struct WebsocketHandler { + pub service_id: ServiceId, +} +#[async_trait::async_trait] +impl ApiGatewayServer for ApiGateway { + async fn is_service_connect( + &self, + uri: Uri, + ) -> Result { + Self::is_apigateway_connection(&uri) + } + async fn service_connect( + &mut self, + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + ) -> Result { + info!("new Service connected: {:?}", service_id); + + let spawn_service_id = service_id.clone(); + let rule_engine_for_service = self.rules_engine.clone(); + /* + The broker_rx is a channel that receives service routing requests from the broker. It is the responsibility + of this (APIGateway) to handle the service routing requests and send them to the appropriate service. + Each service connection will have its own broker_rx channel, and the APIGateway will handle the routing + */ + let (websocket_handler_sender, websocket_handler_receiver) = + mpsc::channel::(32); + + /* + map sender for the websocket handler to the service id for later use + */ + { + let mut updater = self.services_2_rxs.write().await; + updater.insert(service_id.clone(), websocket_handler_sender); + } + let methods_2_services = self.methods_2_services.clone(); + let services_2_rxs = Arc::clone(&self.services_2_rxs); + tokio::spawn(async move { + let _ = Self::handle_service_connection( + spawn_service_id, + ws_stream, + rule_engine_for_service, + methods_2_services.clone(), + websocket_handler_receiver, + services_2_rxs.clone(), + ) + .await; + }); + + Ok(APIGatewayServiceConnectionDisposition::Accept(service_id)) + } + fn get_sender(&self) -> tokio::sync::mpsc::Sender { + self.broker_sender.clone() + } +} +/* +write unit tests for ApiGateway +*/ +#[cfg(test)] +mod tests { + use super::*; + + use mockall::predicate::eq; + + use std::sync::Arc; + + use ripple_sdk::api::rules_engine::MockRuleEngineProvider; + + use ssda_types::service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, + FireboltMethodHandlerAPIRegistration, + }; + use ssda_types::{JqRule, ServiceId}; + use tokio::sync::RwLock; + + fn make_registration(method: &str) -> APIGatewayServiceRegistrationRequest { + APIGatewayServiceRegistrationRequest { + firebolt_handlers: vec![FireboltMethodHandlerAPIRegistration { + firebolt_method: method.to_string(), + jq_rule: Some(JqRule { + alias: "foo".to_string(), + rule: ".foo".to_string(), + }), + }], + } + } + + #[tokio::test] + async fn test_service_map_add_and_get() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc1".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.bar".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg.clone()]); + let regs = map.get_registrations(&service_id); + assert_eq!(regs.len(), 1); + assert_eq!(regs[0].firebolt_method, "foo.bar"); + } + + #[tokio::test] + async fn test_service_map_remove() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc2".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.baz".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg]); + map.remove_service(&service_id); + let regs = map.get_registrations(&service_id); + assert!(regs.is_empty()); + } + + #[tokio::test] + async fn test_service_map_get_service_for_method() { + let mut map = ServiceMap::new(); + let service_id = ServiceId::new("svc3".to_string()); + let reg = FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo.qux".to_string(), + jq_rule: None, + }; + map.add_service(service_id.clone(), vec![reg.clone()]); + let found = map.get_service_for_method("foo.qux"); + assert!(found.is_some()); + let (sid, r) = found.unwrap(); + assert_eq!(sid, service_id); + assert_eq!(r.firebolt_method, "foo.qux"); + } + + #[tokio::test] + async fn test_is_apigateway_connection_accept() { + let uri: http::Uri = "/apigateway?serviceId=testsvc".parse().unwrap(); + let res = ApiGateway::is_apigateway_connection(&uri); + assert!(matches!( + res, + Ok(APIGatewayServiceConnectionDisposition::Accept(_)) + )); + } + + #[tokio::test] + async fn test_is_apigateway_connection_reject() { + let uri: http::Uri = "/notgateway".parse().unwrap(); + let res = ApiGateway::is_apigateway_connection(&uri); + assert!(matches!( + res, + Err(APIGatewayServiceConnectionError::NotAService) + )); + } + + #[tokio::test] + async fn test_classify_message_register() { + let reg = APIClientMessages::Register(make_registration("foo.bar")); + let msg = Message::Text(serde_json::to_string(®).unwrap()); + let state = ApiGateway::classify_message(&msg); + match state { + APIGatewayClientState::Registering(_) => {} + _ => panic!("Expected Registering"), + } + } + + #[tokio::test] + async fn test_classify_message_close() { + let msg = Message::Close(None); + let state = ApiGateway::classify_message(&msg); + assert!(matches!(state, APIGatewayClientState::Closed)); + } + + #[tokio::test] + async fn test_handle_registration_and_unregister() { + let service_id = ServiceId::new("svc4".to_string()); + let mut mock = MockRuleEngineProvider::new(); + let r = Rule { + alias: "foo.bar".to_string(), + filter: Some(".foo".to_string()), + endpoint: Some("service".to_string()), + ..Default::default() + }; + mock.expect_add_rule() + .with(eq(r.clone())) + .times(1) + .return_const(()); + mock.expect_remove_rule().times(1).return_const(()); + + let rule_engine: Arc< + RwLock>, + > = Arc::new(RwLock::new(Box::new(mock))); + + let methods_2_services = Arc::new(RwLock::new(ServiceMap::new())); + let registration = make_registration("foo.bar"); + ApiGateway::handle_registration( + service_id.clone(), + rule_engine.clone(), + ®istration, + methods_2_services.clone(), + ) + .await; + let regs = methods_2_services + .read() + .await + .get_registrations(&service_id); + assert_eq!(regs.len(), 1); + + ApiGateway::handle_unregister(&service_id, methods_2_services.clone(), rule_engine.clone()) + .await; + let regs = methods_2_services + .read() + .await + .get_registrations(&service_id); + assert!(regs.is_empty()); + } +} diff --git a/ssda/ssda_types/Cargo.toml b/ssda/ssda_types/Cargo.toml new file mode 100644 index 000000000..b66344b63 --- /dev/null +++ b/ssda/ssda_types/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ssda_types" +version = "0.1.0" +edition = "2021" + +[dependencies] + +ripple_sdk = { path="../../core/sdk" } + +async-trait = "0.1.88" +mockall = "0.13.1" +serde = "1.0.219" +serde_json = "1.0.140" +tokio = { version = "1", features = ["full"] } +tokio-tungstenite = "0.20.1" +futures-util = "0.3" +url = "2.5" +http = "0.2.12" +jsonrpsee = {version= "0.24.9", features= ["server", "macros"] } +pprof = { version = "0.15", features = ["flamegraph"] } +env_logger = "0.11.8" diff --git a/ssda/ssda_types/src/api_gateway_client.rs b/ssda/ssda_types/src/api_gateway_client.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/api_gateway_client.rs @@ -0,0 +1 @@ + diff --git a/ssda/ssda_types/src/api_gateway_server.rs b/ssda/ssda_types/src/api_gateway_server.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/api_gateway_server.rs @@ -0,0 +1 @@ + diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs new file mode 100644 index 000000000..6fdcaff3a --- /dev/null +++ b/ssda/ssda_types/src/lib.rs @@ -0,0 +1,837 @@ +use std::fs::File; +use std::sync::Arc; +use std::time::Duration; + +use futures_util::{SinkExt, StreamExt}; +use gateway::ServiceRoutingRequest; +use jsonrpsee::types::response; +use jsonrpsee::{Methods, RpcModule}; +use ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiRequest; +use ripple_sdk::api::rules_engine::{Rule, RuleTransform}; +use ripple_sdk::log::{debug, error, info}; +use serde::{Deserialize, Serialize}; + +use service::{ + APIClientMessages, APIGatewayServiceRegistrationRequest, ServiceRegistration, + ServiceRequestHandler, +}; + +/* +Who what why +# API Gateway +The API gateway is a standalone binary component +that listens for Firebolt requests on a websocket. Upon receiving a firebolt +request, the gateway will look up a handler service (based on the method name) in it's +runtime (dynamically created) registry, and (assumign a service is registered to for the method), +will wrap the request with metadata, and dispatch the request to the handler service. Upon receiving +a response from the service, the API Gateway will translate the service response (using the rules engine) +into a Firebolt compatible (success or failure) result. + +# Servicesprintln +ServiceRequestHandler. This design is motivated by the need to free the Service from as much connection oriented +detail and let the developer focus on business logic. The API Gateway client is instanced as a crate that can be +consumed by a service at the highest possible level of abstraction (and ease of use) - it should only requuire a bit of +bootstrapping, and a ServiceRequestHandler instance/implementation, and then it should manage all the details of the +interactions between the Service and the API gateway with the Service being as blissfully ignorant of the details +as possible. +*/ +/* + +register: Service -> API Gateway Client -> API Gateway + +*/ + +pub mod api_gateway_client; +pub mod api_gateway_server; +pub mod service_api; + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct JqRule { + pub alias: String, + pub rule: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct StaticRule { + pub alias: String, + pub rule: String, +} +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct HandlerId { + pub handler_id: String, +} +#[derive(Debug, Clone, Default, Serialize, Deserialize)] + +pub struct ServiceHandler { + pub handler_id: HandlerId, + pub handler_type: Handler, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub enum Handler { + #[default] + None, + JqRule(JqRule), + StaticRule(StaticRule), +} +impl std::fmt::Display for Handler { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Handler::None => write!(f, "none"), + Handler::JqRule(jq_rule) => write!(f, "{}", jq_rule.alias), + Handler::StaticRule(static_rule) => write!(f, "{}", static_rule.alias), + } + } +} + +impl From for ripple_sdk::api::rules_engine::Rule { + fn from(handler: Handler) -> Self { + match handler { + Handler::None => Rule { + alias: "none".to_string(), + filter: None, + transform: RuleTransform::default(), + event_handler: None, + endpoint: None, + sources: None, + }, + Handler::JqRule(jq_rule) => Rule { + alias: jq_rule.alias, + filter: Some(jq_rule.rule), + ..Default::default() + }, + Handler::StaticRule(static_rule) => Rule { + alias: static_rule.alias, + filter: Some(static_rule.rule), + ..Default::default() + }, + } + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ServiceId { + pub service_id: String, +} +impl ServiceId { + pub fn new(service_id: String) -> Self { + ServiceId { service_id } + } +} + +impl PartialEq for ServiceId { + fn eq(&self, other: &Self) -> bool { + self.service_id == other.service_id + } +} + +impl Eq for ServiceId {} + +impl std::hash::Hash for ServiceId { + fn hash(&self, state: &mut H) { + self.service_id.hash(state); + } +} +impl std::fmt::Display for ServiceId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.service_id) + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ServiceRequestId { + pub request_id: u64, +} +impl PartialEq for ServiceRequestId { + fn eq(&self, other: &Self) -> bool { + self.request_id == other.request_id + } +} + +impl Eq for ServiceRequestId {} + +impl std::hash::Hash for ServiceRequestId { + fn hash(&self, state: &mut H) { + self.request_id.hash(state); + } +} +impl ServiceRequestId { + pub fn new(request_id: u64) -> Self { + ServiceRequestId { request_id } + } +} + +/* +gateway messages: from endpoint broker to api gateway and back. +*/ +pub mod gateway { + use crate::ServiceId; + use http::Uri; + use ripple_sdk::api::gateway::rpc_gateway_api::{ + JsonRpcApiError, JsonRpcApiResponse, RpcRequest, + }; + use serde::{Deserialize, Serialize}; + use serde_json::Value; + use tokio::sync::oneshot::Sender; + + use crate::ServiceRequestId; + + /* + ServiceRequest is the request that is sent from the API Gateway to the service + */ + #[derive(Debug)] + pub struct ServiceRoutingRequest { + pub request_id: ServiceRequestId, + pub payload: RpcRequest, + pub respond_to: Sender, + } + #[derive(Debug, Default, Clone, Serialize, Deserialize)] + pub struct ServiceRoutingSuccessResponse { + pub request_id: ServiceRequestId, + pub response: Value, + } + impl From for JsonRpcApiResponse { + fn from(response: ServiceRoutingResponse) -> Self { + match response { + ServiceRoutingResponse::Error(_error) => JsonRpcApiError::default().into(), + ServiceRoutingResponse::Success(success) => JsonRpcApiResponse { + id: Some(success.request_id.request_id), + jsonrpc: "2.0".to_string(), + result: Some(success.response), + error: None, + method: None, + params: None, + }, + } + } + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRoutingErrorResponse { + pub request_id: ServiceRequestId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum ServiceRoutingResponse { + Success(ServiceRoutingSuccessResponse), + Error(ServiceRoutingErrorResponse), + } + #[derive(Debug)] + pub enum APIGatewayServiceConnectionDisposition { + Accept(ServiceId), + Connected(ServiceId), + } + #[derive(Debug)] + pub enum APIGatewayServiceConnectionError { + ConnectionError, + NotAService, + } + + /* + This is the API gateway, and it meant to be hosted in the main ripple process + */ + + #[async_trait::async_trait] + pub trait ApiGatewayServer: Send + Sync { + async fn is_service_connect( + &self, + uri: Uri, + ) -> Result; + async fn service_connect( + &mut self, + service_id: ServiceId, + ws_stream: tokio_tungstenite::WebSocketStream, + ) -> Result; + fn get_sender(&self) -> tokio::sync::mpsc::Sender; + } +} +/* +service message: from api gateawy to services and back (over websockets) +*/ +pub mod service { + + use ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiRequest; + use serde::{Deserialize, Serialize}; + use serde_json::Value; + + use crate::{Handler, JqRule, ServiceId, ServiceRequestId}; + + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct FireboltMethodHandlerRegistration { + pub firebolt_method: Handler, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct FireboltMethodHandlerAPIRegistration { + pub firebolt_method: String, + pub jq_rule: Option, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct APIGatewayServiceRegistrationRequest { + pub firebolt_handlers: Vec, + } + #[derive(Debug, Clone, Serialize, Deserialize, Default)] + pub struct APIGatewayServiceRegistrationResponse { + pub firebolt_handlers: Vec, + } + impl From for APIGatewayServiceRegistrationResponse { + fn from( + request: APIGatewayServiceRegistrationRequest, + ) -> APIGatewayServiceRegistrationResponse { + APIGatewayServiceRegistrationResponse { + firebolt_handlers: request.firebolt_handlers, + } + } + } + + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRequest { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub payload: serde_json::Value, + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceErrorResponse { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub error: String, + } + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceSuccessResponse { + pub service_id: ServiceId, + pub firebolt_method: Handler, + pub payload: serde_json::Value, + } + + /* + send by api client to the api gateway over websocket + + */ + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct APIClientRegistration { + pub firebolt_handlers: Vec, + } + /* + Sent during callback registration in service + */ + #[derive(Debug, Clone, Default, Serialize, Deserialize)] + pub struct ServiceRegistration { + pub service_id: ServiceId, + pub firebolt_handlers: Vec, + } + + impl ServiceRegistration { + pub fn new( + service_id: ServiceId, + firebolt_handlers: Vec, + ) -> Self { + ServiceRegistration { + service_id, + firebolt_handlers, + } + } + pub fn get_rule_registrations(&self) -> Vec { + self.firebolt_handlers.clone() + } + } + + pub struct ServiceRegistrationBuilder { + service_id: ServiceId, + firebolt_handlers: Vec, + } + impl ServiceRegistrationBuilder { + pub fn new(service_id: ServiceId) -> Self { + ServiceRegistrationBuilder { + service_id, + firebolt_handlers: Vec::new(), + } + } + pub fn add_handler(&mut self, firebolt_method: Handler) -> &mut Self { + self.firebolt_handlers.push(match firebolt_method { + Handler::None => todo!(), + Handler::JqRule(jq_rule) => FireboltMethodHandlerAPIRegistration { + firebolt_method: jq_rule.alias.clone(), + jq_rule: Some(jq_rule), + }, + Handler::StaticRule(static_rule) => FireboltMethodHandlerAPIRegistration { + firebolt_method: static_rule.alias.clone(), + jq_rule: Some(JqRule { + alias: static_rule.alias, + rule: static_rule.rule, + }), + }, + }); + self + } + pub fn build(&self) -> ServiceRegistration { + ServiceRegistration { + service_id: self.service_id.clone(), + firebolt_handlers: self.firebolt_handlers.clone(), + } + } + } + /* + ServiceCall is the request that is presented to a callback handler. + */ + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCall { + pub request_id: ServiceRequestId, + pub method: String, + pub payload: serde_json::Value, + } + impl From for JsonRpcApiRequest { + fn from(call: ServiceCall) -> Self { + JsonRpcApiRequest { + id: Some(call.request_id.request_id), + jsonrpc: "2.0".to_string(), + method: call.method, + params: Some(call.payload), + } + } + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCallSuccessResponse { + pub request_id: ServiceRequestId, + pub response: serde_json::Value, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct ServiceCallErrorResponse { + pub request_id: ServiceRequestId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum ServiceCallResponse { + Success(ServiceCallSuccessResponse), + Error(ServiceCallErrorResponse), + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum APIClientMessages { + Register(APIGatewayServiceRegistrationRequest), + Registered(APIGatewayServiceRegistrationResponse), + Error(String), + Unregister(ServiceId), + ServiceCall(ServiceCall), + ServiceCallSuccessResponse(ServiceCallSuccessResponse), + ServiceCallErrorResponse(ServiceCallErrorResponse), + } + impl Default for APIClientMessages { + fn default() -> Self { + APIClientMessages::Register(APIGatewayServiceRegistrationRequest::default()) + } + } + + pub struct ServiceRegistrationResponse { + pub service_id: ServiceId, + } + pub struct ServiceRegistrationFailure { + pub service_id: ServiceId, + pub error: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum WebsocketServiceResponse { + Success(ServiceRequestId, serde_json::Value), + Error(ServiceRequestId, String), + } + impl WebsocketServiceResponse { + pub fn get_id(&self) -> ServiceRequestId { + match self { + WebsocketServiceResponse::Success(id, _) => id.clone(), + WebsocketServiceResponse::Error(id, _) => id.clone(), + } + } + } + #[derive(Debug)] + pub struct WebsocketServiceRequest { + pub request_id: ServiceRequestId, + pub method: String, + pub payload: Value, + pub respond_to: tokio::sync::oneshot::Sender, + } + + /* + individiual services implement this trait to handle requests from the API gateway + This trait should faciliate fun testing of actual implementations + */ + + pub trait ServiceRequestHandler: Send + Sync { + /* + called by the client to allow the ServiceRequestHander return a Vec + to be used by the client to route requests. This is a blocking call, and will be called + after the client `on_connect`s + **/ + fn register(&self) -> Vec; + fn handle_request( + &self, + request: ServiceCall, + ) -> Result; + fn on_connected(&self); + fn on_disconnected(&self); + fn healthy(&self) -> bool; + } +} +pub mod client { + use mockall::automock; + + use crate::{HandlerId, ServiceId}; + + use crate::service::{ + FireboltMethodHandlerRegistration, ServiceCall, ServiceCallErrorResponse, + ServiceCallSuccessResponse, ServiceErrorResponse, ServiceRegistration, + ServiceRegistrationFailure, ServiceRegistrationResponse, ServiceRequest, + ServiceRequestHandler, ServiceSuccessResponse, + }; + + #[async_trait::async_trait] + /* + this is a trait that is implemented by a service client. + There will probably only be 2 of these for the foreseeable future: + 1) a real, websocket client + 2) a mock, for unit/integration testing + the point of this trait , and it's implementers, is to abstract the details related to auth, connection, etc. from the service (business logic) + that needs it. + + the methods in the actual interface are concerned with what to do during lifecycle transition events. the graph/steps/etc. of the lifecyle and + when to call these methods (and any state needed to call them) is the responsiblity of the concrete implementation. + */ + #[automock] + pub trait ServiceClientTrait: Send + Sync { + // this is a request to the service to register itself with the API gateway + fn register( + &self, + registraton: Box, + ) -> Result; + fn set_handler(&mut self, handler: Box); + fn unregister_service(&mut self, service_id: ServiceId) -> Result<(), String>; + fn register_handler( + &mut self, + handler: FireboltMethodHandlerRegistration, + ) -> Result<(), String>; + fn unregister_handler(&mut self, handler_id: HandlerId) -> Result<(), String>; + async fn invoke_handler( + &mut self, + request: ServiceRequest, + ) -> Result; + } + impl ServiceRequestHandler for T + where + T: Send + Sync + Clone + 'static + ServiceRequestHandlerImpl, + { + fn register(&self) -> Vec { + self.register() + } + + fn handle_request( + &self, + request: ServiceCall, + ) -> Result { + self.handle_request(request) + } + + fn on_connected(&self) { + self.on_connected() + } + + fn on_disconnected(&self) { + self.on_disconnected() + } + + fn healthy(&self) -> bool { + self.healthy() + } + } + + pub trait ServiceRequestHandlerImpl: Send + Sync + Clone { + fn register(&self) -> Vec; + fn handle_request( + &self, + request: ServiceCall, + ) -> Result; + fn on_connected(&self); + fn on_disconnected(&self); + fn healthy(&self) -> bool; + } +} +/* +This is the alternative API surface that services can use to communicate with the API gateway. +Firebolt calls are bidirectional, so the API gateway can send messages to the service, and the service can send messages to the API gateway. +*/ +mod api_surface { + use serde::{Deserialize, Serialize}; + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct FireboltRequest { + pub request_id: String, + pub payload: String, + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct FireboltResponse { + pub request_id: String, + pub payload: String, + } +} + +/* +This trait represents the layer that will actually "talk" to the API gateway. it handles transports, etc. +This is a trait to : +1) Enable testing +2) Abstract the details of the transport from the service +3) Allow for different transports (websocket, http, etc.)z +*/ +#[async_trait::async_trait] +pub trait APIGatewayClient { + //fn connect(&self); + //fn disconnect(&self); + fn dispatch(&self, request: gateway::ServiceRoutingRequest); + async fn start(&self); + // async fn stop(&self); +} +pub struct WebsocketAPIGatewayClient { + rpc_server: Methods, + service_id: ServiceId, +} + +use tokio_tungstenite::{connect_async, tungstenite::Message}; +use url::Url; + +use crate::service::{ + FireboltMethodHandlerAPIRegistration, FireboltMethodHandlerRegistration, + ServiceCallErrorResponse, ServiceCallResponse, ServiceCallSuccessResponse, +}; + +impl WebsocketAPIGatewayClient { + pub fn new(rpc_server: Methods, service_id: ServiceId) -> WebsocketAPIGatewayClient { + WebsocketAPIGatewayClient { + rpc_server: rpc_server, + service_id: service_id, + } + } + pub async fn handle_messages( + stream: tokio_tungstenite::WebSocketStream< + tokio_tungstenite::MaybeTlsStream, + >, + rpc_server: Methods, + firebolt_handlers: Vec, + // handler: Arc, + //registration: ServiceRegistration, + ) { + let (mut tx, mut rx) = stream.split(); + let firebolt_handlers: Vec = rpc_server + .method_names() + .map(|method| { + info!("Registered method: {}", method); + FireboltMethodHandlerAPIRegistration { + firebolt_method: method.to_string(), + jq_rule: None, // Assuming no jq rule for now, can be modified as needed + } + }) + .collect(); + + let registration_request = APIGatewayServiceRegistrationRequest { + firebolt_handlers: firebolt_handlers.clone(), + }; + let msg = serde_json::to_string(&APIClientMessages::Register(registration_request.clone())); + if let Ok(msg) = msg { + let _ = tx.send(Message::Text(msg)).await; + } else { + error!("websocket: Failed to serialize registration request"); + } + + while let Some(message) = rx.next().await { + match message { + Ok(msg) => { + /* + attempt to marshal the message into a ServiceRequest + if it fails, log the error and continue + */ + info!("websocket: Received message via websocket: {:?}", msg); + let msg = msg.into_text().unwrap_or_default(); + if let Ok(request) = serde_json::from_str::(&msg) { + match request { + APIClientMessages::Register(registration_request) => { + info!("Received registration request: {:?}", registration_request); + } + APIClientMessages::Registered(registration_request) => { + info!("Received registered response: {:?}", registration_request); + //handler.on_connected(); + } + APIClientMessages::Error(error) => { + info!("Received error: {:?}", error); + } + APIClientMessages::Unregister(service_id) => { + info!("Received unregister request: {:?}", service_id); + } + APIClientMessages::ServiceCall(service_call) => { + debug!( + "Received service call: {:?}", + service_call.payload.to_string() + ); + let request_id = service_call.request_id.clone(); + let json_rpc_request = service_call.payload.clone(); + debug!("Raw JSON-RPC request: {:?}", json_rpc_request); + let json_rpc_request = + serde_json::to_value(json_rpc_request).unwrap().to_string(); + debug!("sending request to RPC server: {:?}", json_rpc_request); + + match rpc_server.raw_json_request(&json_rpc_request, 1).await { + Ok(okie) => { + debug!("Received response from RPC server: {:?}", okie); + let raw_response = okie.0.clone(); + debug!("Raw response: {:?}", raw_response); + let response = serde_json::from_str::( + &raw_response, + ); + if let Err(e) = response { + debug!("Failed to parse response: {:?}", e); + let error_response = + APIClientMessages::ServiceCallErrorResponse( + ServiceCallErrorResponse { + request_id: request_id, + error: e.to_string(), + }, + ); + let error_response = + serde_json::to_string(&error_response); + if let Ok(error_response) = error_response { + let _ = tx + .send(Message::Text(error_response.clone())) + .await; + debug!( + "Sending error response: {:?}", + error_response + ); + } else { + debug!("Failed to serialize error response"); + } + return; + } else { + let response = response.unwrap(); + info!( + "Parsed response from called service: {:?}", + response + ); + let success_response = ServiceCallSuccessResponse { + request_id: request_id, + response, + }; + let success_response = + APIClientMessages::ServiceCallSuccessResponse( + success_response, + ); + let success_response = + serde_json::to_string(&success_response); + if let Ok(success_response) = success_response { + let _ = tx + .send(Message::Text(success_response.clone())) + .await; + debug!( + "Sending success response: {:?}", + success_response + ); + } else { + error!("Failed to serialize success response"); + } + } + } + Err(nope) => { + error!("nope! {:?}", nope); + let error_response = + APIClientMessages::ServiceCallErrorResponse( + ServiceCallErrorResponse { + request_id: request_id, + error: nope.to_string(), + }, + ); + let error_response = serde_json::to_string(&error_response); + if let Ok(error_response) = error_response { + let _ = tx + .send(Message::Text(error_response.clone())) + .await; + debug!("Sending error response: {:?}", error_response); + } else { + error!("Failed to serialize error response"); + } + } + } + } + _ => {} + } + } else { + error!(" I don't understand this message: {:?}", msg); + } + } + Err(err) => { + error!("Error receiving message: {:?}", err); + // Handle the error (e.g., log it, retry, etc.) + // You might want to break the loop or handle reconnection logic here + // break; + } + } + } + } + pub async fn connect( + &self, + endpoint_url: Option, + service_id: ServiceId, + ) -> Result<(), Box> { + let url = Url::parse(&endpoint_url.unwrap_or_else(|| { + format!( + "ws://localhost:3474/apigateway?serviceId={}", + &service_id.service_id + ) + }))?; + let mut backoff = Duration::from_secs(1); + println!("Connecting to WebSocket at {}", url); + + loop { + match connect_async(url.clone()).await { + Ok((ws_stream, _)) => { + //let handler = self.handler.clone(); + ///let registration = self.registration.clone(); + let rpc_server = self.rpc_server.clone(); + println!("✅ Connected to WebSocket"); + + // Reset backoff after successful connection + backoff = Duration::from_secs(1); + + // This handles the message loop and returns on disconnect + Self::handle_messages(ws_stream, rpc_server, vec![]).await; + info!("🔌 Disconnected, retrying..."); + } + Err(err) => { + error!("Error connecting to WebSocket: {:?}", err); + + // Exponential backoff (up to 1 minute) + tokio::time::sleep(backoff).await; + if backoff >= Duration::from_secs(60) { + backoff = Duration::from_secs(1); + } + + backoff = std::cmp::min(backoff * 2, Duration::from_secs(60)); + } + } + } + } +} + +#[async_trait::async_trait] +impl APIGatewayClient for WebsocketAPIGatewayClient { + // fn connect(&self) { + // // connect to the API gateway + // } + // fn disconnect(&self) { + // // disconnect from the API gateway + // } + fn dispatch(&self, _request: ServiceRoutingRequest) { + // send a request to the API gateway + } + + async fn start(&self) { + env_logger::init(); + info!("starting websocket client"); + self.connect(None, self.service_id.clone()).await.unwrap(); + // self.handler.on_connected(); + } + + // async fn stop(&self) { + // todo!() + // } +} diff --git a/ssda/ssda_types/src/service_api.rs b/ssda/ssda_types/src/service_api.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ssda/ssda_types/src/service_api.rs @@ -0,0 +1 @@ + From 66e772ad1ecd90c250bc2ec032e7ac50ad204b78 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Thu, 3 Jul 2025 12:40:24 -0700 Subject: [PATCH 33/46] chore: more cleanup --- core/main/src/broker/service_broker.rs | 28 +++++++++--------- core/main/src/firebolt/firebolt_ws.rs | 32 +++++++++------------ core/sdk/src/api/gateway/rpc_gateway_api.rs | 2 +- ssda/ssda_client/src/lib.rs | 15 +++------- ssda/ssda_types/src/lib.rs | 31 +++++++------------- 5 files changed, 42 insertions(+), 66 deletions(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index af9f3eb9e..1efbf2b06 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -3,31 +3,29 @@ use ripple_sdk::{ log::{error, info}, tokio::sync::mpsc, }; -use serde_json::Value; use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; use ssda_types::ServiceRequestId; use super::endpoint_broker::{ - BrokerCallback, BrokerCleaner, BrokerOutputForwarder, BrokerRequest, BrokerSender, - EndpointBroker, BROKER_CHANNEL_BUFFER_SIZE, + BrokerCleaner, BrokerOutputForwarder, BrokerSender, EndpointBroker, BROKER_CHANNEL_BUFFER_SIZE, }; use ripple_sdk::tokio; pub struct ServiceBroker { broker_sender: BrokerSender, } -async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest, body: &[u8]) { - match BrokerOutputForwarder::handle_non_jsonrpc_response( - body, - callback.clone(), - request.clone(), - ) { - Ok(_) => {} - Err(e) => { - error!("Error message from service broker {:?}", e) - } - } -} +// async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest, body: &[u8]) { +// match BrokerOutputForwarder::handle_non_jsonrpc_response( +// body, +// callback.clone(), +// request.clone(), +// ) { +// Ok(_) => {} +// Err(e) => { +// error!("Error message from service broker {:?}", e) +// } +// } +// } impl ServiceBroker {} impl EndpointBroker for ServiceBroker { diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index dc6782d56..ef54313aa 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -31,6 +31,20 @@ use crate::{ use futures::SinkExt; use futures::StreamExt; use jsonrpsee::types::{error::INVALID_REQUEST_CODE, ErrorObject, ErrorResponse, Id}; +use ripple_sdk::{ + api::{gateway::rpc_gateway_api::CallContext, manifest::extn_manifest::ExtnSymbol}, + extn::{ + extn_client_message::{ExtnMessage, ExtnPayload, ExtnResponse}, + extn_id::ExtnId, + }, + framework::ripple_contract::RippleContract, + log::trace, + tokio_tungstenite::{ + tungstenite::{self, Message}, + WebSocketStream, + }, + utils::error::RippleError, +}; use ripple_sdk::{ api::{ gateway::rpc_gateway_api::{ @@ -46,24 +60,6 @@ use ripple_sdk::{ utils::channel_utils::oneshot_send_and_log, uuid::Uuid, }; -use ripple_sdk::{ - api::{ - gateway::rpc_gateway_api::{CallContext, JsonRpcApiRequest}, - manifest::extn_manifest::ExtnSymbol, - }, - chrono::format::format, - extn::{ - extn_client_message::{ExtnMessage, ExtnPayload, ExtnResponse}, - extn_id::ExtnId, - }, - framework::ripple_contract::RippleContract, - log::trace, - tokio_tungstenite::{ - tungstenite::{self, Message}, - WebSocketStream, - }, - utils::error::RippleError, -}; use ripple_sdk::{log::debug, tokio}; use ssda_service::ApiGateway; use ssda_types::gateway::{APIGatewayServiceConnectionDisposition, ApiGatewayServer}; diff --git a/core/sdk/src/api/gateway/rpc_gateway_api.rs b/core/sdk/src/api/gateway/rpc_gateway_api.rs index 9e545d0f5..ebf5aa82c 100644 --- a/core/sdk/src/api/gateway/rpc_gateway_api.rs +++ b/core/sdk/src/api/gateway/rpc_gateway_api.rs @@ -694,7 +694,7 @@ impl RpcRequest { return Some(Value::Object(params_map)); } - return None; + None } pub fn get_new_internal(method: String, params: Option) -> Self { diff --git a/ssda/ssda_client/src/lib.rs b/ssda/ssda_client/src/lib.rs index e5431ede2..b7af0e0e1 100644 --- a/ssda/ssda_client/src/lib.rs +++ b/ssda/ssda_client/src/lib.rs @@ -1,25 +1,18 @@ -use std::sync::Arc; - use jsonrpsee::RpcModule; -use ssda_types::{ - service::{ServiceRegistration, ServiceRequestHandler}, - APIGatewayClient, WebsocketAPIGatewayClient, -}; +use ssda_types::{service::ServiceRegistration, APIGatewayClient, WebsocketAPIGatewayClient}; pub enum APIGatewayClientTransport { WebSocket, } -pub struct APIGatewayClientBuilder { +pub struct APIGatewayClientBuilder { transport: APIGatewayClientTransport, service_registration: ServiceRegistration, - rpc_server: Option>, } -impl APIGatewayClientBuilder { +impl APIGatewayClientBuilder { pub fn new(service_registration: ServiceRegistration) -> Self { APIGatewayClientBuilder { transport: APIGatewayClientTransport::WebSocket, service_registration, - rpc_server: None, } } pub fn with_service_registration( @@ -36,7 +29,7 @@ impl APIGatewayClientBuilder { self } - pub fn build(&self, rpc_server: RpcModule) -> Box { + pub fn build(&self, rpc_server: RpcModule) -> Box { let methods = rpc_server.clone(); match self.transport { APIGatewayClientTransport::WebSocket => Box::new(WebsocketAPIGatewayClient::new( diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index 6fdcaff3a..28ea82576 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -1,20 +1,12 @@ -use std::fs::File; -use std::sync::Arc; -use std::time::Duration; - use futures_util::{SinkExt, StreamExt}; use gateway::ServiceRoutingRequest; -use jsonrpsee::types::response; -use jsonrpsee::{Methods, RpcModule}; -use ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiRequest; +use jsonrpsee::Methods; use ripple_sdk::api::rules_engine::{Rule, RuleTransform}; use ripple_sdk::log::{debug, error, info}; use serde::{Deserialize, Serialize}; +use std::time::Duration; -use service::{ - APIClientMessages, APIGatewayServiceRegistrationRequest, ServiceRegistration, - ServiceRequestHandler, -}; +use service::{APIClientMessages, APIGatewayServiceRegistrationRequest}; /* Who what why @@ -593,15 +585,14 @@ use tokio_tungstenite::{connect_async, tungstenite::Message}; use url::Url; use crate::service::{ - FireboltMethodHandlerAPIRegistration, FireboltMethodHandlerRegistration, - ServiceCallErrorResponse, ServiceCallResponse, ServiceCallSuccessResponse, + FireboltMethodHandlerAPIRegistration, ServiceCallErrorResponse, ServiceCallSuccessResponse, }; impl WebsocketAPIGatewayClient { pub fn new(rpc_server: Methods, service_id: ServiceId) -> WebsocketAPIGatewayClient { WebsocketAPIGatewayClient { - rpc_server: rpc_server, - service_id: service_id, + rpc_server, + service_id, } } pub async fn handle_messages( @@ -609,7 +600,7 @@ impl WebsocketAPIGatewayClient { tokio_tungstenite::MaybeTlsStream, >, rpc_server: Methods, - firebolt_handlers: Vec, + _api_gateway_clientfirebolt_handlers: Vec, // handler: Arc, //registration: ServiceRegistration, ) { @@ -684,7 +675,7 @@ impl WebsocketAPIGatewayClient { let error_response = APIClientMessages::ServiceCallErrorResponse( ServiceCallErrorResponse { - request_id: request_id, + request_id, error: e.to_string(), }, ); @@ -709,7 +700,7 @@ impl WebsocketAPIGatewayClient { response ); let success_response = ServiceCallSuccessResponse { - request_id: request_id, + request_id, response, }; let success_response = @@ -736,7 +727,7 @@ impl WebsocketAPIGatewayClient { let error_response = APIClientMessages::ServiceCallErrorResponse( ServiceCallErrorResponse { - request_id: request_id, + request_id, error: nope.to_string(), }, ); @@ -784,8 +775,6 @@ impl WebsocketAPIGatewayClient { loop { match connect_async(url.clone()).await { Ok((ws_stream, _)) => { - //let handler = self.handler.clone(); - ///let registration = self.registration.clone(); let rpc_server = self.rpc_server.clone(); println!("✅ Connected to WebSocket"); From d11317b6c5727a33117625425ff4fe580e7a26db Mon Sep 17 00:00:00 2001 From: bobra200 Date: Fri, 4 Jul 2025 07:27:09 -0700 Subject: [PATCH 34/46] feat: unit tests --- ssda/ssda_types/src/lib.rs | 249 ++++++++++++++++++++++++++++++++++++- 1 file changed, 245 insertions(+), 4 deletions(-) diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index 28ea82576..5d88ce329 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -37,19 +37,19 @@ pub mod api_gateway_client; pub mod api_gateway_server; pub mod service_api; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct JqRule { pub alias: String, pub rule: String, } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct StaticRule { pub alias: String, pub rule: String, } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct HandlerId { pub handler_id: String, @@ -253,7 +253,7 @@ pub mod service { pub struct FireboltMethodHandlerRegistration { pub firebolt_method: Handler, } - #[derive(Debug, Clone, Serialize, Deserialize, Default)] + #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] pub struct FireboltMethodHandlerAPIRegistration { pub firebolt_method: String, pub jq_rule: Option, @@ -581,6 +581,8 @@ pub struct WebsocketAPIGatewayClient { service_id: ServiceId, } +use serde_json::json; +use std::collections::HashSet; use tokio_tungstenite::{connect_async, tungstenite::Message}; use url::Url; @@ -824,3 +826,242 @@ impl APIGatewayClient for WebsocketAPIGatewayClient { // todo!() // } } +pub mod tests { + use super::*; + + #[test] + fn test_service_id_equality() { + let id1 = ServiceId::new("service1".to_string()); + let id2 = ServiceId::new("service1".to_string()); + let id3 = ServiceId::new("service2".to_string()); + assert_eq!(id1, id2); + assert_ne!(id1, id3); + } + + #[test] + fn test_service_id_hash() { + let id1 = ServiceId::new("service1".to_string()); + let id2 = ServiceId::new("service1".to_string()); + let mut set = HashSet::new(); + set.insert(id1); + assert!(set.contains(&id2)); + } + + #[test] + fn test_service_id_display() { + let id = ServiceId::new("abc".to_string()); + assert_eq!(format!("{}", id), "abc"); + } + + #[test] + fn test_service_request_id_equality() { + let id1 = ServiceRequestId::new(1); + let id2 = ServiceRequestId::new(1); + let id3 = ServiceRequestId::new(2); + assert_eq!(id1, id2); + assert_ne!(id1, id3); + } + + #[test] + fn test_service_request_id_hash() { + let id1 = ServiceRequestId::new(1); + let id2 = ServiceRequestId::new(1); + let mut set = HashSet::new(); + set.insert(id1); + assert!(set.contains(&id2)); + } + + #[test] + fn test_handler_display() { + let jq = Handler::JqRule(JqRule { + alias: "jq".to_string(), + rule: ".foo".to_string(), + }); + let static_rule = Handler::StaticRule(StaticRule { + alias: "static".to_string(), + rule: "bar".to_string(), + }); + let none = Handler::None; + assert_eq!(format!("{}", jq), "jq"); + assert_eq!(format!("{}", static_rule), "static"); + assert_eq!(format!("{}", none), "none"); + } + + #[test] + fn test_handler_into_rule() { + let jq = Handler::JqRule(JqRule { + alias: "jq".to_string(), + rule: ".foo".to_string(), + }); + let rule: Rule = jq.clone().into(); + assert_eq!(rule.alias, "jq"); + assert_eq!(rule.filter, Some(".foo".to_string())); + + let static_rule = Handler::StaticRule(StaticRule { + alias: "static".to_string(), + rule: "bar".to_string(), + }); + let rule: Rule = static_rule.clone().into(); + assert_eq!(rule.alias, "static"); + assert_eq!(rule.filter, Some("bar".to_string())); + + let none = Handler::None; + let rule: Rule = none.into(); + assert_eq!(rule.alias, "none"); + assert!(rule.filter.is_none()); + } + + #[test] + fn test_service_registration_builder() { + let service_id = ServiceId::new("svc".to_string()); + let mut builder = service::ServiceRegistrationBuilder::new(service_id.clone()); + builder.add_handler(Handler::JqRule(JqRule { + alias: "jq".to_string(), + rule: ".foo".to_string(), + })); + let reg = builder.build(); + assert_eq!(reg.service_id, service_id); + assert_eq!(reg.firebolt_handlers.len(), 1); + assert_eq!(reg.firebolt_handlers[0].firebolt_method, "jq"); + } + + #[test] + fn test_service_registration_get_rule_registrations() { + let reg = service::ServiceRegistration { + service_id: ServiceId::new("svc".to_string()), + firebolt_handlers: vec![service::FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo".to_string(), + jq_rule: None, + }], + }; + let rules = reg.get_rule_registrations(); + assert_eq!(rules.len(), 1); + assert_eq!(rules[0].firebolt_method, "foo"); + } + + #[test] + fn test_service_call_into_jsonrpc_api_request() { + let call = service::ServiceCall { + request_id: ServiceRequestId::new(42), + method: "test".to_string(), + payload: json!({"foo": "bar"}), + }; + let req: ripple_sdk::api::gateway::rpc_gateway_api::JsonRpcApiRequest = call.into(); + assert_eq!(req.id, Some(42)); + assert_eq!(req.method, "test"); + assert_eq!(req.params, Some(json!({"foo": "bar"}))); + } + + #[test] + fn test_apigatewayserviceregistrationrequest_into_response() { + let req = service::APIGatewayServiceRegistrationRequest { + firebolt_handlers: vec![service::FireboltMethodHandlerAPIRegistration { + firebolt_method: "foo".to_string(), + jq_rule: None, + }], + }; + let resp: service::APIGatewayServiceRegistrationResponse = req.clone().into(); + assert_eq!(resp.firebolt_handlers, req.firebolt_handlers); + } + + #[test] + fn test_websocketserviceresponse_get_id() { + let id = ServiceRequestId::new(7); + let resp = service::WebsocketServiceResponse::Success(id.clone(), json!({})); + assert_eq!(resp.get_id(), id); + let resp = service::WebsocketServiceResponse::Error(id.clone(), "err".to_string()); + assert_eq!(resp.get_id(), id); + } + + #[test] + fn test_apiclientmessages_default() { + let msg = service::APIClientMessages::default(); + match msg { + service::APIClientMessages::Register(_) => {} + _ => panic!("Default should be Register"), + } + } + + #[test] + fn test_servicecallresponse_serialization() { + let resp = service::ServiceCallResponse::Success(service::ServiceCallSuccessResponse { + request_id: ServiceRequestId::new(1), + response: json!({"foo": "bar"}), + }); + let s = serde_json::to_string(&resp).unwrap(); + let de: service::ServiceCallResponse = serde_json::from_str(&s).unwrap(); + match de { + service::ServiceCallResponse::Success(success) => { + assert_eq!(success.request_id, ServiceRequestId::new(1)); + assert_eq!(success.response, json!({"foo": "bar"})); + } + _ => panic!("Expected Success"), + } + } + + #[test] + fn test_servicecallerrorresponse_serialization() { + let resp = service::ServiceCallResponse::Error(service::ServiceCallErrorResponse { + request_id: ServiceRequestId::new(2), + error: "fail".to_string(), + }); + let s = serde_json::to_string(&resp).unwrap(); + let de: service::ServiceCallResponse = serde_json::from_str(&s).unwrap(); + match de { + service::ServiceCallResponse::Error(err) => { + assert_eq!(err.request_id, ServiceRequestId::new(2)); + assert_eq!(err.error, "fail"); + } + _ => panic!("Expected Error"), + } + } + + #[test] + fn test_handlerid_serialize_deserialize() { + let handler_id = HandlerId { + handler_id: "abc".to_string(), + }; + let s = serde_json::to_string(&handler_id).unwrap(); + let de: HandlerId = serde_json::from_str(&s).unwrap(); + assert_eq!(handler_id, de); + } + + #[test] + fn test_jqrule_serialize_deserialize() { + let jq = JqRule { + alias: "a".to_string(), + rule: "b".to_string(), + }; + let s = serde_json::to_string(&jq).unwrap(); + let de: JqRule = serde_json::from_str(&s).unwrap(); + assert_eq!(jq, de); + } + + #[test] + fn test_statirule_serialize_deserialize() { + let sr = StaticRule { + alias: "a".to_string(), + rule: "b".to_string(), + }; + let s = serde_json::to_string(&sr).unwrap(); + let de: StaticRule = serde_json::from_str(&s).unwrap(); + assert_eq!(sr, de); + } + + #[test] + fn test_servicehandler_serialize_deserialize() { + let handler = ServiceHandler { + handler_id: HandlerId { + handler_id: "id".to_string(), + }, + handler_type: Handler::None, + }; + let s = serde_json::to_string(&handler).unwrap(); + let de: ServiceHandler = serde_json::from_str(&s).unwrap(); + assert_eq!(handler.handler_id, de.handler_id); + match de.handler_type { + Handler::None => {} + _ => panic!("Expected None"), + } + } +} From 63cbe9347939b7312372f6ffac4e029fafac773d Mon Sep 17 00:00:00 2001 From: bobra200 Date: Fri, 4 Jul 2025 07:37:25 -0700 Subject: [PATCH 35/46] feat: unit tests --- ssda/ssda_types/src/lib.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ssda/ssda_types/src/lib.rs b/ssda/ssda_types/src/lib.rs index 5d88ce329..028b25db2 100644 --- a/ssda/ssda_types/src/lib.rs +++ b/ssda/ssda_types/src/lib.rs @@ -581,8 +581,6 @@ pub struct WebsocketAPIGatewayClient { service_id: ServiceId, } -use serde_json::json; -use std::collections::HashSet; use tokio_tungstenite::{connect_async, tungstenite::Message}; use url::Url; @@ -826,8 +824,17 @@ impl APIGatewayClient for WebsocketAPIGatewayClient { // todo!() // } } +#[cfg(test)] pub mod tests { - use super::*; + use std::collections::HashSet; + + use ripple_sdk::api::rules_engine::Rule; + use serde_json::json; + + use crate::{ + service, Handler, HandlerId, JqRule, ServiceHandler, ServiceId, ServiceRequestId, + StaticRule, + }; #[test] fn test_service_id_equality() { From 4f33c9c2982bd20f61481c24c13299bf12ecb24c Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 7 Jul 2025 06:36:29 -0700 Subject: [PATCH 36/46] chore: test refactor --- core/main/Cargo.toml | 2 + core/main/src/broker/endpoint_broker.rs | 43 +- core/main/src/broker/mod.rs | 5 +- core/main/src/broker/service_broker.rs | 443 +++++++++++++++----- core/main/src/broker/ssda_service_broker.rs | 123 ++++++ core/main/src/state/platform_state.rs | 34 +- 6 files changed, 525 insertions(+), 125 deletions(-) create mode 100644 core/main/src/broker/ssda_service_broker.rs diff --git a/core/main/Cargo.toml b/core/main/Cargo.toml index f239b0fab..34bfd516b 100644 --- a/core/main/Cargo.toml +++ b/core/main/Cargo.toml @@ -43,10 +43,12 @@ contract_tests = [ "websocket_contract_tests", ] tdk=[] +ssda=[] [dependencies] base64.workspace = true ripple_sdk = { path = "../sdk" } + jsonrpsee = { workspace = true, features = ["macros"] } futures-channel.workspace = true futures.workspace = true diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 6f9ad8a98..6f98d5297 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -69,7 +69,6 @@ use super::{ extn_broker::ExtnBroker, http_broker::HttpBroker, provider_broker_state::{ProvideBrokerState, ProviderResult}, - service_broker::ServiceBroker, thunder_broker::ThunderBroker, websocket_broker::WebsocketBroker, workflow_broker::WorkflowBroker, @@ -793,12 +792,14 @@ impl EndpointBrokerState { None, ), RuleEndpointProtocol::Service => { - let service_broker = - ServiceBroker::get_broker(ps, request, self.callback.clone(), self); - ( - service_broker.get_sender(), - Some(service_broker.get_cleaner()), - ) + self.get_service_broker(ps, request) + + // let service_broker = + // SsdaServiceBroker::get_broker(ps, request, self.callback.clone(), self); + // ( + // service_broker.get_sender(), + // Some(service_broker.get_cleaner()), + // ) } }; self.add_endpoint(key, broker); @@ -808,6 +809,34 @@ impl EndpointBrokerState { cleaner_list.push(cleaner); } } + #[cfg(not(feature = "ssda"))] + fn get_service_broker( + &mut self, + ps: Option, + request: BrokerConnectRequest, + ) -> (BrokerSender, Option) { + use crate::broker::service_broker::ServiceBroker; + let service_broker = ServiceBroker::get_broker(ps, request, self.callback.clone(), self); + ( + service_broker.get_sender(), + Some(service_broker.get_cleaner()), + ) + } + + #[cfg(feature = "ssda")] + fn get_service_broker( + &mut self, + ps: Option, + request: BrokerConnectRequest, + ) -> (BrokerSender, Option) { + use super::ssda_service_broker::SsdaServiceBroker; + let service_broker = + SsdaServiceBroker::get_broker(ps, request, self.callback.clone(), self); + ( + service_broker.get_sender(), + Some(service_broker.get_cleaner()), + ) + } fn handle_static_request(&self, rpc_request: RpcRequest) -> JsonRpcApiResponse { let mut data = JsonRpcApiResponse::default(); diff --git a/core/main/src/broker/mod.rs b/core/main/src/broker/mod.rs index 6728214c5..2ae5b6934 100644 --- a/core/main/src/broker/mod.rs +++ b/core/main/src/broker/mod.rs @@ -20,9 +20,10 @@ pub mod event_management_utility; pub mod extn_broker; pub mod http_broker; pub mod provider_broker_state; - +#[cfg(not(feature = "ssda"))] pub mod service_broker; -#[cfg(test)] +#[cfg(feature = "ssda")] +pub mod ssda_service_broker; pub mod test; pub mod thunder; pub mod thunder_broker; diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 1efbf2b06..f7548b92b 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -1,135 +1,350 @@ +// Copyright 2023 Comcast Cable Communications Management, LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +use super::endpoint_broker::{ + BrokerCallback, BrokerCleaner, BrokerConnectRequest, BrokerRequest, BrokerSender, + EndpointBroker, EndpointBrokerState, BROKER_CHANNEL_BUFFER_SIZE, +}; +use crate::state::platform_state::PlatformState; use ripple_sdk::{ - api::gateway::rpc_gateway_api::{JsonRpcApiError, JsonRpcApiResponse}, + api::{gateway::rpc_gateway_api::JsonRpcApiError, observability::log_signal::LogSignal}, log::{error, info}, - tokio::sync::mpsc, -}; -use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; -use ssda_types::ServiceRequestId; - -use super::endpoint_broker::{ - BrokerCleaner, BrokerOutputForwarder, BrokerSender, EndpointBroker, BROKER_CHANNEL_BUFFER_SIZE, + service::service_message::{Id, ServiceMessage}, + tokio::{self, sync::mpsc}, + tokio_tungstenite::tungstenite::Message, + utils::error::RippleError, }; -use ripple_sdk::tokio; +#[derive(Clone)] pub struct ServiceBroker { - broker_sender: BrokerSender, + sender: BrokerSender, } -// async fn send_broker_response(callback: &BrokerCallback, request: &BrokerRequest, body: &[u8]) { -// match BrokerOutputForwarder::handle_non_jsonrpc_response( -// body, -// callback.clone(), -// request.clone(), -// ) { -// Ok(_) => {} -// Err(e) => { -// error!("Error message from service broker {:?}", e) -// } -// } -// } - -impl ServiceBroker {} -impl EndpointBroker for ServiceBroker { - fn get_broker( - ps: Option, - _connect_request: super::endpoint_broker::BrokerConnectRequest, - broker_callback: super::endpoint_broker::BrokerCallback, - _endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, - ) -> Self { - //todo!(); - // let endpoint = request.endpoint.clone(); - let (tx, mut tr) = mpsc::channel(BROKER_CHANNEL_BUFFER_SIZE); - let broker_sender = BrokerSender { sender: tx }; - let callback = broker_callback.clone(); - if let Some(platform_state) = ps.clone() { - tokio::spawn(async move { - while let Some(request) = tr.recv().await { - info!("ServiceBroker received request: {:?}", request); - let services_tx = platform_state - .services_gateway_api - .lock() - .await - .get_sender(); - use tokio::sync::oneshot; - - let (oneshot_tx, oneshot_rx) = oneshot::channel::(); - - let service_request = ServiceRoutingRequest { - request_id: ServiceRequestId { - request_id: request.rpc.ctx.call_id, - }, - payload: request.rpc.clone(), - respond_to: oneshot_tx, - }; - info!( - "ServiceBroker sending service request: {:?}", - service_request - ); - services_tx.try_send(service_request).unwrap(); - - match oneshot_rx.await { - Ok(response) => { - info!("ServiceBroker received response: {:?}", response); - match response { - ServiceRoutingResponse::Error(e) => { - error!("ServiceBroker received error response: {:?}", e); - let err = JsonRpcApiError::default() - .with_id(e.request_id.request_id) - .with_message(e.error) - .to_response(); - BrokerOutputForwarder::send_json_rpc_response_to_broker( - err, - callback.clone(), - ); - // send_broker_response(&callback, &request, &err.as_bytes()) - // .await; - } - ServiceRoutingResponse::Success(response) => { - info!( - "ServiceBroker received success response: {:?}", - response.response - ); - let json_rpc_response = - JsonRpcApiResponse::from_value(response.response).unwrap(); - info!( - "ServiceBroker creating JSON-RPC response: {:?}", - json_rpc_response - ); - // Convert the response to - let win: Vec = json_rpc_response.to_string().into_bytes(); - info!("ServiceBroker sending response: {:?}", win); - BrokerOutputForwarder::send_json_rpc_response_to_broker( - json_rpc_response, - callback.clone(), - ); - } - } - } - Err(e) => { - error!("ServiceBroker failed to receive response {}", e); +impl ServiceBroker { + pub fn start( + ps: Option, + callback: BrokerCallback, + _endpoint_broker: EndpointBrokerState, + ) -> BrokerSender { + let (broker_request_tx, mut broker_request_rx) = mpsc::channel(BROKER_CHANNEL_BUFFER_SIZE); + + // ps should be valid, otherwise we cannot proceed + let ps_c = if let Some(ps) = ps { + ps.clone() + } else { + error!("PlatformState is None, cannot start ServiceBroker"); + return BrokerSender { + sender: broker_request_tx, + }; + }; + + tokio::spawn(async move { + while let Some(broker_request) = broker_request_rx.recv().await { + LogSignal::new( + "service_broker".to_string(), + format!("received service broker request: {:?}", broker_request), + broker_request.rpc.ctx.clone(), + ) + .emit_debug(); + + let service_id = broker_request.rule.alias.clone(); + + // get the ws sender for the service from service_controller_state + let service_sender = + match ps_c.service_controller_state.get_sender(&service_id).await { + Some(sender) => sender, + None => { + error!("Service sender not found for service id: {}", service_id); + Self::log_error_and_send_broker_failure_response( + broker_request.clone(), + &callback, + JsonRpcApiError::default() + .with_code(-32001) + .with_message(format!( + "Service sender not found for service id: {}", + service_id + )) + .with_id(broker_request.rpc.ctx.call_id), + ); + continue; } + }; + + let request = match Self::update_service_request(&broker_request) { + Ok(req) => req, + Err(e) => { + error!("Failed to update request: {:?}", e); + Self::log_error_and_send_broker_failure_response( + broker_request.clone(), + &callback, + JsonRpcApiError::default() + .with_code(-32001) + .with_message(format!("Failed to update request: {}", e)) + .with_id(broker_request.rpc.ctx.call_id), + ); + continue; } + }; + + LogSignal::new( + "service_broker".to_string(), + format!("Sending request to service: {:?}", request), + broker_request.rpc.ctx.clone(), + ) + .emit_debug(); + + let request_id = broker_request.rpc.ctx.call_id; + // set the Broker callback in service controller for sending broker response + if let Some(workflow_callback) = broker_request.workflow_callback.clone() { + let _ = ps_c + .service_controller_state + .set_broker_callback(&service_id, request_id, workflow_callback) + .await; + } else { + let _ = ps_c + .service_controller_state + .set_broker_callback(&service_id, request_id, callback.clone()) + .await; } - }); - } else { - panic!("Platform state is required"); - }; + let message = Message::Text(request.clone()); + info!("Sending request to service {}: {:#?}", service_id, message); + + if let Err(err) = service_sender.try_send(message) { + error!( + "Failed to send request to service {}: {:?}", + service_id, err + ); + Self::log_error_and_send_broker_failure_response( + broker_request.clone(), + &callback, + JsonRpcApiError::default() + .with_code(-32001) + .with_message(format!( + "Failed to send request to service {}: {:?}", + service_id, err + )) + .with_id(broker_request.rpc.ctx.call_id), + ); + } else { + LogSignal::new( + "service_broker".to_string(), + format!("Request sent to service: {}", service_id), + broker_request.rpc.ctx.clone(), + ) + .emit_debug(); + } + } + }); + + BrokerSender { + sender: broker_request_tx, + } + } + + fn log_error_and_send_broker_failure_response( + request: BrokerRequest, + callback: &BrokerCallback, + error: JsonRpcApiError, + ) { + LogSignal::new( + "service_broker".to_string(), + format!("broker request failed: {:?} error: {:?}", request, error), + request.rpc.ctx.clone(), + ) + .emit_error(); + Self::send_broker_failure_response(callback, error.into()); + } + + fn update_service_request(broker_request: &BrokerRequest) -> Result { + let v = Self::apply_request_rule(broker_request)?; + info!("transformed request {:?}", v); + + // Create a ServiceMessage + let mut request = ServiceMessage::new_request( + broker_request.rpc.method.clone(), + Some(v.clone()), + Id::Number(broker_request.rpc.ctx.call_id.try_into().unwrap()), + ); + request.set_context(Some(serde_json::Value::from( + broker_request.rpc.ctx.clone(), + ))); + Ok(request.into()) + } +} + +impl EndpointBroker for ServiceBroker { + fn get_broker( + ps: Option, + _request: BrokerConnectRequest, + callback: BrokerCallback, + broker_state: &mut EndpointBrokerState, + ) -> Self { Self { - // platform_state: ps.clone(), - // connect_request, - // broker_callback, - // endpoint_broker_state: endpoint_broker.clone(), - broker_sender, - //cleaner: BrokerCleaner { cleaner: None }, + sender: Self::start(ps, callback, broker_state.clone()), } } - fn get_sender(&self) -> super::endpoint_broker::BrokerSender { - self.broker_sender.clone() + fn get_sender(&self) -> BrokerSender { + self.sender.clone() } fn get_cleaner(&self) -> super::endpoint_broker::BrokerCleaner { BrokerCleaner::default() } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::broker::endpoint_broker::BrokerOutput; + use crate::service::extn::ripple_client::RippleClient; + use crate::state::bootstrap_state::ChannelsState; + use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; + use ripple_sdk::api::manifest::device_manifest::DeviceManifest; + use ripple_sdk::api::manifest::extn_manifest::ExtnManifest; + use ripple_sdk::api::rules_engine::{Rule, RuleEngine}; + use ripple_sdk::Mockable; + use ssda_service::ApiGateway; + use std::sync::Arc; + use tokio::sync::Mutex; + use tokio::sync::RwLock; + + #[tokio::test] + pub async fn test_log_error_and_send_broker_failure_response() { + use super::*; + use tokio::time::{timeout, Duration}; + + let (tx, mut rx) = mpsc::channel::(10); + let callback = BrokerCallback { sender: tx }; + + let mut rpc_request = RpcRequest::internal("test_method", None); + rpc_request.ctx.call_id = 147; + + let broker_request = BrokerRequest { + rpc: rpc_request, + rule: Rule { + alias: "test_rule".to_string(), + ..Default::default() + }, + subscription_processed: None, + workflow_callback: Some(callback.clone()), + telemetry_response_listeners: vec![], + }; + + let error = JsonRpcApiError::default() + .with_code(-32001) + .with_message("Test error message".to_string()) + .with_id(147); + + ServiceBroker::log_error_and_send_broker_failure_response( + broker_request.clone(), + &callback, + error.clone(), + ); + + if let Ok(Some(BrokerOutput { data, .. })) = + timeout(Duration::from_secs(5), rx.recv()).await + { + assert!(data.is_error()); + } else { + panic!("Timeout or channel closed without receiving data"); + } + } + + #[tokio::test] + #[ignore] + pub async fn test_get_broker() { + use super::*; + + let (tx, _rx) = mpsc::channel::(10); + let callback = BrokerCallback { sender: tx }; + + let mut broker_state = EndpointBrokerState::default(); + + let broker = ServiceBroker::get_broker( + None, + BrokerConnectRequest::default(), + callback.clone(), + &mut broker_state, + ); + + assert!(!broker.get_sender().sender.is_closed()); + } + + #[tokio::test] + pub async fn test_get_sender() { + use super::*; + + let (tx, _rx) = mpsc::channel::(10); + let sender = BrokerSender { sender: tx.clone() }; + let broker = ServiceBroker { sender }; + + assert!(broker.get_sender().sender.same_channel(&tx)); + } + + #[tokio::test] + pub async fn test_get_cleaner() { + use super::*; + + let (tx, _rx) = mpsc::channel::(10); + let sender = BrokerSender { sender: tx }; + let broker = ServiceBroker { sender }; + + let cleaner = broker.get_cleaner(); + assert!(cleaner.cleaner.is_none()); + } + + #[tokio::test] + #[ignore] + pub async fn test_start_successful_response() { + use super::*; + use tokio::time::{timeout, Duration}; + + let (tx, mut rx) = mpsc::channel::(10); + let callback = BrokerCallback { sender: tx }; + + let mut rpc_request = RpcRequest::mock(); + rpc_request.ctx.call_id = 11; + + let broker_request = BrokerRequest { + rpc: rpc_request.clone(), + rule: Rule { + alias: "test_rule".to_string(), + ..Default::default() + }, + subscription_processed: None, + workflow_callback: Some(callback.clone()), + telemetry_response_listeners: vec![], + }; + let platform_state = PlatformState::default(); + + let sender = ServiceBroker::start( + Some(platform_state), + callback.clone(), + EndpointBrokerState::default(), + ); + sender.sender.send(broker_request.clone()).await.unwrap(); + + if let Ok(Some(BrokerOutput { data, .. })) = + timeout(Duration::from_secs(5), rx.recv()).await + { + assert!(data.is_success()); + } else { + eprintln!("Timeout or channel closed without receiving data, skipping test"); + } + } +} diff --git a/core/main/src/broker/ssda_service_broker.rs b/core/main/src/broker/ssda_service_broker.rs new file mode 100644 index 000000000..d101a8ef6 --- /dev/null +++ b/core/main/src/broker/ssda_service_broker.rs @@ -0,0 +1,123 @@ +use ripple_sdk::{ + api::gateway::rpc_gateway_api::{JsonRpcApiError, JsonRpcApiResponse}, + log::{error, info}, + tokio::sync::mpsc, +}; +use ssda_types::gateway::{ServiceRoutingRequest, ServiceRoutingResponse}; +use ssda_types::ServiceRequestId; + +use super::endpoint_broker::{ + BrokerCleaner, BrokerOutputForwarder, BrokerSender, EndpointBroker, BROKER_CHANNEL_BUFFER_SIZE, +}; +use ripple_sdk::tokio; + +pub struct SsdaServiceBroker { + broker_sender: BrokerSender, +} + +impl SsdaServiceBroker {} +impl EndpointBroker for SsdaServiceBroker { + fn get_broker( + ps: Option, + _connect_request: super::endpoint_broker::BrokerConnectRequest, + broker_callback: super::endpoint_broker::BrokerCallback, + _endpoint_broker: &mut super::endpoint_broker::EndpointBrokerState, + ) -> Self { + //todo!(); + // let endpoint = request.endpoint.clone(); + let (tx, mut tr) = mpsc::channel(BROKER_CHANNEL_BUFFER_SIZE); + let broker_sender = BrokerSender { sender: tx }; + let callback = broker_callback.clone(); + if let Some(platform_state) = ps.clone() { + tokio::spawn(async move { + while let Some(request) = tr.recv().await { + info!("ServiceBroker received request: {:?}", request); + let services_tx = platform_state + .services_gateway_api + .lock() + .await + .get_sender(); + use tokio::sync::oneshot; + + let (oneshot_tx, oneshot_rx) = oneshot::channel::(); + + let service_request = ServiceRoutingRequest { + request_id: ServiceRequestId { + request_id: request.rpc.ctx.call_id, + }, + payload: request.rpc.clone(), + respond_to: oneshot_tx, + }; + info!( + "ServiceBroker sending service request: {:?}", + service_request + ); + + services_tx.try_send(service_request).unwrap(); + + match oneshot_rx.await { + Ok(response) => { + info!("ServiceBroker received response: {:?}", response); + match response { + ServiceRoutingResponse::Error(e) => { + error!("ServiceBroker received error response: {:?}", e); + let err = JsonRpcApiError::default() + .with_id(e.request_id.request_id) + .with_message(e.error) + .to_response(); + BrokerOutputForwarder::send_json_rpc_response_to_broker( + err, + callback.clone(), + ); + // send_broker_response(&callback, &request, &err.as_bytes()) + // .await; + } + ServiceRoutingResponse::Success(response) => { + info!( + "ServiceBroker received success response: {:?}", + response.response + ); + let json_rpc_response = + JsonRpcApiResponse::from_value(response.response).unwrap(); + info!( + "ServiceBroker creating JSON-RPC response: {:?}", + json_rpc_response + ); + // Convert the response to + let win: Vec = json_rpc_response.to_string().into_bytes(); + info!("ServiceBroker sending response: {:?}", win); + BrokerOutputForwarder::send_json_rpc_response_to_broker( + json_rpc_response, + callback.clone(), + ); + } + } + } + Err(e) => { + error!("ServiceBroker failed to receive response {}", e); + } + } + } + }); + } else { + panic!("Platform state is required"); + }; + + Self { + // platform_state: ps.clone(), + // connect_request, + // broker_callback, + // endpoint_broker_state: endpoint_broker.clone(), + broker_sender, + //cleaner: BrokerCleaner { cleaner: None }, + } + } + + fn get_sender(&self) -> super::endpoint_broker::BrokerSender { + self.broker_sender.clone() + } + + fn get_cleaner(&self) -> super::endpoint_broker::BrokerCleaner { + BrokerCleaner::default() + } +} diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index 02d72bde9..ded845b92 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -25,7 +25,7 @@ use ripple_sdk::{ exclusory::ExclusoryImpl, extn_manifest::ExtnManifest, }, - rules_engine::RuleEngineProvider, + rules_engine::{RuleEngine, RuleEngineProvider}, session::SessionAdjective, }, extn::{ @@ -33,10 +33,14 @@ use ripple_sdk::{ extn_id::ExtnId, }, framework::ripple_contract::RippleContract, - tokio, + tokio::{ + self, + sync::{Mutex, RwLock}, + }, utils::error::RippleError, uuid::Uuid, }; +use ssda_service::ApiGateway; use ssda_types::gateway::ApiGatewayServer; use std::{collections::HashMap, fmt, sync::Arc}; @@ -52,6 +56,7 @@ use crate::{ extn::ripple_client::RippleClient, ripple_service::service_controller_state::ServiceControllerState, }, + state::bootstrap_state::ChannelsState, }; use super::{ @@ -149,6 +154,31 @@ impl std::fmt::Debug for PlatformState { .finish() } } +#[cfg(test)] +impl Default for PlatformState { + fn default() -> Self { + let extn_manifest = ExtnManifest::default(); + let rules_engine: Arc>> = + Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( + &extn_manifest, + )))); + + let api_gateway: Arc>> = + Arc::new(tokio::sync::Mutex::new(Box::new( + ssda_service::ApiGateway::new(rules_engine.clone()), + ))); + + PlatformState::new( + ExtnManifest::default(), + DeviceManifest::default(), + RippleClient::new(ChannelsState::default()), + Vec::new(), + None, + api_gateway, + rules_engine, + ) + } +} impl PlatformState { pub fn new( extn_manifest: ExtnManifest, From 30fd12d16cfeab10c73ed42692687282f4d19198 Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 7 Jul 2025 09:20:30 -0700 Subject: [PATCH 37/46] chore: clippy --- core/main/src/state/platform_state.rs | 53 ++++++++++++++------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index ded845b92..03db85860 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -25,7 +25,7 @@ use ripple_sdk::{ exclusory::ExclusoryImpl, extn_manifest::ExtnManifest, }, - rules_engine::{RuleEngine, RuleEngineProvider}, + rules_engine::RuleEngineProvider, session::SessionAdjective, }, extn::{ @@ -33,14 +33,10 @@ use ripple_sdk::{ extn_id::ExtnId, }, framework::ripple_contract::RippleContract, - tokio::{ - self, - sync::{Mutex, RwLock}, - }, utils::error::RippleError, uuid::Uuid, }; -use ssda_service::ApiGateway; + use ssda_types::gateway::ApiGatewayServer; use std::{collections::HashMap, fmt, sync::Arc}; @@ -56,7 +52,6 @@ use crate::{ extn::ripple_client::RippleClient, ripple_service::service_controller_state::ServiceControllerState, }, - state::bootstrap_state::ChannelsState, }; use super::{ @@ -84,7 +79,7 @@ pub struct DeviceSessionIdentifier { /// that implements the `Debug` trait. #[derive(Clone)] pub struct DebuggableApiGatewayServer( - pub Arc>>, + pub Arc>>, ); impl fmt::Debug for DebuggableApiGatewayServer { @@ -133,7 +128,8 @@ pub struct PlatformState { pub endpoint_state: EndpointBrokerState, pub lifecycle2_app_state: AppManagerState2_0, pub service_controller_state: ServiceControllerState, - pub services_gateway_api: Arc>>, + pub services_gateway_api: + Arc>>, } impl std::fmt::Debug for PlatformState { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -157,16 +153,18 @@ impl std::fmt::Debug for PlatformState { #[cfg(test)] impl Default for PlatformState { fn default() -> Self { + use crate::state::bootstrap_state::ChannelsState; + use ripple_sdk::api::rules_engine::RuleEngine; + use ripple_sdk::tokio::sync::Mutex; + use ripple_sdk::tokio::sync::RwLock; let extn_manifest = ExtnManifest::default(); - let rules_engine: Arc>> = - Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( - &extn_manifest, - )))); + let rules_engine: Arc>> = + Arc::new(RwLock::new(Box::new(RuleEngine::build(&extn_manifest)))); - let api_gateway: Arc>> = - Arc::new(tokio::sync::Mutex::new(Box::new( - ssda_service::ApiGateway::new(rules_engine.clone()), - ))); + let api_gateway: Arc>> = + Arc::new(Mutex::new(Box::new(ssda_service::ApiGateway::new( + rules_engine.clone(), + )))); PlatformState::new( ExtnManifest::default(), @@ -186,8 +184,12 @@ impl PlatformState { client: RippleClient, app_library: Vec, version: Option, - services_gateway_api: Arc>>, - rule_engine: Arc>>, + services_gateway_api: Arc< + ripple_sdk::tokio::sync::Mutex>, + >, + rule_engine: Arc< + ripple_sdk::tokio::sync::RwLock>, + >, ) -> PlatformState { let exclusory = ExclusoryImpl::get(&manifest); let broker_sender = client.get_broker_sender(); @@ -315,14 +317,15 @@ mod tests { ) .unwrap(); extn_manifest.provider_registrations = default_providers(); - let rules_engine: Arc>> = - Arc::new(tokio::sync::RwLock::new(Box::new(RuleEngine::build( - &extn_manifest, - )))); + let rules_engine: Arc< + ripple_sdk::tokio::sync::RwLock>, + > = Arc::new(ripple_sdk::tokio::sync::RwLock::new(Box::new( + RuleEngine::build(&extn_manifest), + ))); let api_gateway_state: Arc< - tokio::sync::Mutex>, - > = Arc::new(tokio::sync::Mutex::new(Box::new( + ripple_sdk::tokio::sync::Mutex>, + > = Arc::new(ripple_sdk::tokio::sync::Mutex::new(Box::new( ssda_service::ApiGateway::new(rules_engine.clone()), ))); Self::new( From 6c04dee8fcf176a1755aebb117361de419ee035f Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 7 Jul 2025 09:32:14 -0700 Subject: [PATCH 38/46] chore: clippy --- core/main/src/broker/service_broker.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index f7548b92b..06588e411 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -211,17 +211,17 @@ impl EndpointBroker for ServiceBroker { mod tests { use super::*; use crate::broker::endpoint_broker::BrokerOutput; - use crate::service::extn::ripple_client::RippleClient; - use crate::state::bootstrap_state::ChannelsState; + // use crate::service::extn::ripple_client::RippleClient; + // use crate::state::bootstrap_state::ChannelsState; use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; - use ripple_sdk::api::manifest::device_manifest::DeviceManifest; - use ripple_sdk::api::manifest::extn_manifest::ExtnManifest; - use ripple_sdk::api::rules_engine::{Rule, RuleEngine}; + // use ripple_sdk::api::manifest::device_manifest::DeviceManifest; + // use ripple_sdk::api::manifest::extn_manifest::ExtnManifest; + use ripple_sdk::api::rules_engine::Rule; use ripple_sdk::Mockable; - use ssda_service::ApiGateway; - use std::sync::Arc; - use tokio::sync::Mutex; - use tokio::sync::RwLock; + // use ssda_service::ApiGateway; + // use std::sync::Arc; + // use tokio::sync::Mutex; + // use tokio::sync::RwLock; #[tokio::test] pub async fn test_log_error_and_send_broker_failure_response() { From 7f597f6cb93ef55eded80ec52bda47f4809c30dd Mon Sep 17 00:00:00 2001 From: bobra200 Date: Mon, 7 Jul 2025 10:53:43 -0700 Subject: [PATCH 39/46] chore: clippy --- core/main/src/broker/service_broker.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/main/src/broker/service_broker.rs b/core/main/src/broker/service_broker.rs index 06588e411..56fa53b53 100644 --- a/core/main/src/broker/service_broker.rs +++ b/core/main/src/broker/service_broker.rs @@ -211,17 +211,9 @@ impl EndpointBroker for ServiceBroker { mod tests { use super::*; use crate::broker::endpoint_broker::BrokerOutput; - // use crate::service::extn::ripple_client::RippleClient; - // use crate::state::bootstrap_state::ChannelsState; use ripple_sdk::api::gateway::rpc_gateway_api::RpcRequest; - // use ripple_sdk::api::manifest::device_manifest::DeviceManifest; - // use ripple_sdk::api::manifest::extn_manifest::ExtnManifest; use ripple_sdk::api::rules_engine::Rule; use ripple_sdk::Mockable; - // use ssda_service::ApiGateway; - // use std::sync::Arc; - // use tokio::sync::Mutex; - // use tokio::sync::RwLock; #[tokio::test] pub async fn test_log_error_and_send_broker_failure_response() { From 5dc0abe9e3c1de0aae9719cbcd6be2d93ede25aa Mon Sep 17 00:00:00 2001 From: brendanobra Date: Wed, 9 Jul 2025 13:40:44 -0700 Subject: [PATCH 40/46] chore: adding better wildcard miss handling --- core/main/src/broker/endpoint_broker.rs | 7 +++++-- core/sdk/src/api/rules_engine/mod.rs | 17 ++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 6f98d5297..81c6086e4 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -395,8 +395,11 @@ impl From for HandleBrokerageError { fn from(value: RuleRetrievalError) -> Self { match value { RuleRetrievalError::RuleNotFound(e) => HandleBrokerageError::RuleNotFound(e), - RuleRetrievalError::RuleNotFoundAsWildcard => { - HandleBrokerageError::RuleNotFound("Rule Not found as wildcard".to_string()) + RuleRetrievalError::RuleNotFoundAsWildcard(method) => { + HandleBrokerageError::RuleNotFound(format!( + "Rule Not found as wildcard for method {}", + method + )) } RuleRetrievalError::TooManyWildcardMatches => { HandleBrokerageError::RuleNotFound("Too many wildcard matches".to_string()) diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index ae88879ae..6561b2aab 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -436,7 +436,9 @@ impl RuleEngine { match filtered_rules.len() { 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), - 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), + 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard( + method.to_string(), + )), _ => Err(RuleRetrievalError::TooManyWildcardMatches), } } @@ -491,7 +493,7 @@ impl From for Rule { #[derive(Debug)] pub enum RuleRetrievalError { RuleNotFound(String), - RuleNotFoundAsWildcard, + RuleNotFoundAsWildcard(String), TooManyWildcardMatches, } @@ -645,7 +647,9 @@ impl RuleEngineProvider for RuleEngine { match filtered_rules.len() { 1 => Ok(RuleRetrieved::WildcardMatch(filtered_rules[0].clone())), - 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard), + 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard( + method.to_string(), + )), _ => Err(RuleRetrievalError::TooManyWildcardMatches), } } @@ -854,10 +858,9 @@ mod tests { }; let result = rule_engine.get_rule(&rpc_request); - assert!(matches!( - result, - Err(RuleRetrievalError::RuleNotFoundAsWildcard) - )); + assert!( + matches!(result, Err(RuleRetrievalError::RuleNotFound(method)) if method == "nonexistent.method") + ); } #[test] From 48501cd6a064164db17bd3ac2be9c9d4c1f07b99 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Wed, 9 Jul 2025 14:17:35 -0700 Subject: [PATCH 41/46] fix: tests --- core/sdk/src/api/rules_engine/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index 6561b2aab..c1fdb5392 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -858,8 +858,9 @@ mod tests { }; let result = rule_engine.get_rule(&rpc_request); + println!("Result: {:?}", result); assert!( - matches!(result, Err(RuleRetrievalError::RuleNotFound(method)) if method == "nonexistent.method") + matches!(result, Err(RuleRetrievalError::RuleNotFoundAsWildcard(method)) if method == "nonexistent.method") ); } From 016725f7af9ab739d0fd03c1085d27929e461a55 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Wed, 9 Jul 2025 17:07:38 -0700 Subject: [PATCH 42/46] fix: better wildcard error messaging --- core/main/src/broker/endpoint_broker.rs | 7 +++++-- core/sdk/src/api/rules_engine/mod.rs | 13 +++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/main/src/broker/endpoint_broker.rs b/core/main/src/broker/endpoint_broker.rs index 81c6086e4..9020619b2 100644 --- a/core/main/src/broker/endpoint_broker.rs +++ b/core/main/src/broker/endpoint_broker.rs @@ -401,8 +401,11 @@ impl From for HandleBrokerageError { method )) } - RuleRetrievalError::TooManyWildcardMatches => { - HandleBrokerageError::RuleNotFound("Too many wildcard matches".to_string()) + RuleRetrievalError::TooManyWildcardMatches(method) => { + HandleBrokerageError::RuleNotFound(format!( + "Too many wildcard matches for method {}", + method + )) } } } diff --git a/core/sdk/src/api/rules_engine/mod.rs b/core/sdk/src/api/rules_engine/mod.rs index c1fdb5392..16d83366e 100644 --- a/core/sdk/src/api/rules_engine/mod.rs +++ b/core/sdk/src/api/rules_engine/mod.rs @@ -439,7 +439,10 @@ impl RuleEngine { 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard( method.to_string(), )), - _ => Err(RuleRetrievalError::TooManyWildcardMatches), + _ => Err(RuleRetrievalError::TooManyWildcardMatches(format!( + "too many matches for method={}. Rules that match={:?}", + method, filtered_rules + ))), } } @@ -494,7 +497,7 @@ impl From for Rule { pub enum RuleRetrievalError { RuleNotFound(String), RuleNotFoundAsWildcard(String), - TooManyWildcardMatches, + TooManyWildcardMatches(String), } /// Compiles and executes a JQ filter on a given JSON input value. @@ -650,7 +653,9 @@ impl RuleEngineProvider for RuleEngine { 0 => Err(RuleRetrievalError::RuleNotFoundAsWildcard( method.to_string(), )), - _ => Err(RuleRetrievalError::TooManyWildcardMatches), + _ => Err(RuleRetrievalError::TooManyWildcardMatches( + method.to_string(), + )), } } fn get_rule(&self, rpc_request: &RpcRequest) -> Result { @@ -890,7 +895,7 @@ mod tests { let result = rule_engine.get_rule(&rpc_request); assert!(matches!( result, - Err(RuleRetrievalError::TooManyWildcardMatches) + Err(RuleRetrievalError::TooManyWildcardMatches(_)) )); } } From 8c07121aea7e37cf79a1e4a04bdbeebb18b687dd Mon Sep 17 00:00:00 2001 From: brendanobra Date: Thu, 10 Jul 2025 07:04:46 -0700 Subject: [PATCH 43/46] feat: conditional new t2 telemetry --- core/main/src/firebolt/firebolt_ws.rs | 40 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index ef54313aa..3bf5ad960 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -32,7 +32,7 @@ use futures::SinkExt; use futures::StreamExt; use jsonrpsee::types::{error::INVALID_REQUEST_CODE, ErrorObject, ErrorResponse, Id}; use ripple_sdk::{ - api::{gateway::rpc_gateway_api::CallContext, manifest::extn_manifest::ExtnSymbol}, + api::manifest::extn_manifest::ExtnSymbol, extn::{ extn_client_message::{ExtnMessage, ExtnPayload, ExtnResponse}, extn_id::ExtnId, @@ -360,6 +360,28 @@ impl FireboltWs { guard.service_connect(service_id, ws_stream).await.unwrap(); } } + #[cfg(feature = "ssda")] + async fn send_t2_event(state: &PlatformState, payload: String) { + use ripple_sdk::api::gateway::rpc_gateway_api::CallContext; + let rpc_request = RpcRequest::new( + String::from("telemetry.event"), + serde_json::json!({ + "payload": payload, + }) + .to_string(), + CallContext::default(), + ); + + state + .endpoint_state + .handle_brokerage(rpc_request, None, None, vec![], None, vec![]) + .await; + } + #[cfg(not(feature = "ssda"))] + async fn send_t2_event(_state: &PlatformState, payload: String) { + debug!("{}", payload); + } + async fn handle_connection( _client_addr: SocketAddr, ws_stream: WebSocketStream, @@ -476,21 +498,7 @@ impl FireboltWs { stats_ref.clone(), stats.stats.get_stage_durations() ); - - let rpc_request = RpcRequest::new( - String::from("telemetry.event"), - serde_json::json!({ - "payload": split, - }) - .to_string(), - CallContext::default(), - ); - - spawn_state - .endpoint_state - .handle_brokerage(rpc_request, None, None, vec![], None, vec![]) - .await; - debug!("{}", split); + Self::send_t2_event(&spawn_state, split).await; } platform_state From 6ee55fc047562397091f26fb6465c4902555a404 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Fri, 11 Jul 2025 14:26:59 -0700 Subject: [PATCH 44/46] fix: bad merge fix --- core/main/src/firebolt/firebolt_ws.rs | 200 ++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 3bf5ad960..b026482f0 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -381,7 +381,45 @@ impl FireboltWs { async fn send_t2_event(_state: &PlatformState, payload: String) { debug!("{}", payload); } + #[cfg(not(feature = "ssda"))] + async fn handle_connection( + _client_addr: SocketAddr, + ws_stream: WebSocketStream, + connect_rx: oneshot::Receiver, + state: PlatformState, + gateway_secure: bool, + ) { + use crate::service::ripple_service::service_controller_state::ServiceControllerState; + let identity = connect_rx.await.unwrap(); + + // Generate a unique connection ID + let connection_id = Uuid::new_v4().to_string(); + if let Some(symbol) = identity.service_info.clone() { + // Handle service connection + ServiceControllerState::handle_service_connection( + _client_addr, + ws_stream, + state, + identity, + connection_id, + symbol, + ) + .await; + } else { + // Handle app connection + Self::handle_app_connection( + _client_addr, + ws_stream, + state, + identity, + connection_id, + gateway_secure, + ) + .await; + } + } + #[cfg(feature = "ssda")] async fn handle_connection( _client_addr: SocketAddr, ws_stream: WebSocketStream, @@ -595,6 +633,168 @@ impl FireboltWs { error!("Error Unregistering {:?}", e); } } + #[cfg(not(feature = "ssda"))] + async fn handle_app_connection( + _client_addr: SocketAddr, + ws_stream: WebSocketStream, + state: PlatformState, + identity: ClientIdentity, + connection_id: String, + gateway_secure: bool, + ) { + info!( + "Creating new app connection_id={} app_id={} session_id={}, gateway_secure={}, port={}", + connection_id, + identity.app_id, + identity.session_id, + gateway_secure, + _client_addr.port() + ); + + let client = state.get_client(); + let app_id = identity.app_id.clone(); + let (session_tx, mut resp_rx) = mpsc::channel(32); + let ctx = ClientContext { + session_id: identity.session_id.clone(), + app_id: app_id.clone(), + gateway_secure, + }; + let session = Session::new(identity.app_id.clone(), Some(session_tx.clone())); + let app_id_c = app_id.clone(); + let session_id_c = identity.session_id.clone(); + let connection_id_c = connection_id.clone(); + + let msg = FireboltGatewayCommand::RegisterSession { + session_id: connection_id.clone(), + session: session.clone(), + }; + if let Err(e) = client.send_gateway_command(msg) { + error!("Error registering the app connection: {:?}", e); + return; + } + + if !gateway_secure + && PermissionHandler::fetch_and_store(&state, &identity.app_id, false) + .await + .is_err() + { + error!("Couldnt pre cache permissions"); + } + + let mut context = vec![]; + if identity.rpc_v2 { + context.push(RPC_V2.to_string()); + } + + let rpc_context: Arc>> = Arc::new(RwLock::new(context)); + let (mut sender, mut receiver) = ws_stream.split(); + let mut platform_state = state.clone(); + let context_clone = ctx.clone(); + + tokio::spawn(async move { + while let Some(api_message) = resp_rx.recv().await { + let send_result = sender + .send(Message::Text(api_message.jsonrpc_msg.clone())) + .await; + match send_result { + Ok(_) => { + platform_state + .metrics + .update_api_stage(&api_message.request_id, "response"); + + LogSignal::new( + "sent_firebolt_response".to_string(), + "firebolt message sent".to_string(), + context_clone.clone(), + ) + .with_diagnostic_context_item("cid", &connection_id_c.clone()) + .with_diagnostic_context_item("result", &api_message.jsonrpc_msg.clone()) + .emit_debug(); + if let Some(stats) = platform_state + .metrics + .get_api_stats(&api_message.request_id) + { + info!( + "Sending Firebolt response: {:?},{}", + stats.stats_ref, + stats.stats.get_total_time() + ); + debug!( + "Full Firebolt Split: {:?},{}", + stats.stats_ref, + stats.stats.get_stage_durations() + ); + platform_state + .metrics + .remove_api_stats(&api_message.request_id); + } + + info!( + "Sent Firebolt response cid={} msg={}", + connection_id_c.clone(), + api_message.jsonrpc_msg + ); + } + Err(err) => error!("{:?}", err), + } + } + debug!( + "api msg rx closed {} {} {}", + app_id_c.clone(), + session_id_c.clone(), + connection_id_c.clone() + ); + }); + let session_id_c = identity.session_id.clone(); + let app_id_c = identity.app_id.clone(); + while let Some(msg) = receiver.next().await { + match msg { + Ok(msg) => { + if msg.is_text() && !msg.is_empty() { + debug!("Received JsonRpc Request {}", msg); + let req_id = Uuid::new_v4().to_string(); + let req_text = String::from(msg.to_text().unwrap()); + let context = { rpc_context.read().unwrap().clone() }; + if let Ok(request) = RpcRequest::parse( + req_text.clone(), + app_id_c.clone(), + session_id_c.clone(), + req_id.clone(), + Some(connection_id.clone()), + gateway_secure, + context, + ) { + info!("Received Firebolt request {}", request.params_json); + let msg = FireboltGatewayCommand::HandleRpc { request }; + if let Err(e) = client.clone().send_gateway_command(msg) { + error!("failed to send request {:?}", e); + } + } else if let Some(response) = JsonRpcApiResponse::get_response(&req_text) { + let msg = FireboltGatewayCommand::HandleResponse { response }; + if let Err(e) = client.clone().send_gateway_command(msg) { + error!("failed to send request {:?}", e); + } + } else { + return_invalid_format_error_message(req_id, &state, &connection_id) + .await; + error!("invalid message {}", req_text) + } + } + } + Err(e) => { + error!("ws error cid={} error={:?}", connection_id, e); + } + } + } + debug!("SESSION DEBUG Unregistering {}", connection_id); + let msg = FireboltGatewayCommand::UnregisterSession { + session_id: identity.session_id.clone(), + cid: connection_id, + }; + if let Err(e) = client.send_gateway_command(msg) { + error!("Error Unregistering {:?}", e); + } + } } async fn return_invalid_service_error_message( From 8e45840dfa3e77ee0c419ef71b34fec9aa7b0bb8 Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 19 Aug 2025 08:27:12 -0700 Subject: [PATCH 45/46] chore: merge cleanup --- Cargo.lock | 15 ++++++++++++--- core/main/src/broker/workflow_broker.rs | 2 +- core/main/src/firebolt/firebolt_ws.rs | 6 ++++-- core/main/src/state/platform_state.rs | 1 - core/sdk/Cargo.toml | 7 ++++--- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1386dd2a..75629ef1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1809,7 +1809,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -4698,7 +4698,7 @@ version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" dependencies = [ - "cfg-if", + "cfg-if 1.0.1", "core-foundation-sys", "libc", "ntapi", @@ -5534,7 +5534,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ "windows-targets 0.52.6", ] diff --git a/core/main/src/broker/workflow_broker.rs b/core/main/src/broker/workflow_broker.rs index 990d3860c..bdbd8bba3 100644 --- a/core/main/src/broker/workflow_broker.rs +++ b/core/main/src/broker/workflow_broker.rs @@ -4,7 +4,7 @@ use super::endpoint_broker::{ }; use crate::broker::endpoint_broker::{BrokerOutput, EndpointBrokerState}; -use crate::broker::rules::rules_engine::{compose_json_values, make_name_json_safe}; + use crate::state::platform_state::PlatformState; use futures::future::{join_all, BoxFuture}; use futures::FutureExt; diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index b026482f0..4e556ecf1 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -38,7 +38,6 @@ use ripple_sdk::{ extn_id::ExtnId, }, framework::ripple_contract::RippleContract, - log::trace, tokio_tungstenite::{ tungstenite::{self, Message}, WebSocketStream, @@ -506,7 +505,10 @@ impl FireboltWs { match send_result { Ok(_) => { if is_service { - trace!("Sent Service response {}", api_message.jsonrpc_msg); + ripple_sdk::log::trace!( + "Sent Service response {}", + api_message.jsonrpc_msg + ); continue; } platform_state diff --git a/core/main/src/state/platform_state.rs b/core/main/src/state/platform_state.rs index dd9d86597..03db85860 100644 --- a/core/main/src/state/platform_state.rs +++ b/core/main/src/state/platform_state.rs @@ -193,7 +193,6 @@ impl PlatformState { ) -> PlatformState { let exclusory = ExclusoryImpl::get(&manifest); let broker_sender = client.get_broker_sender(); - let rule_engine = RuleEngine::build(&extn_manifest); let extn_sdks = extn_manifest.extn_sdks.clone(); let provider_registations = extn_manifest.provider_registrations.clone(); let metrics_state = OpMetricState::default(); diff --git a/core/sdk/Cargo.toml b/core/sdk/Cargo.toml index 36b72c9c3..70c5e9d0d 100644 --- a/core/sdk/Cargo.toml +++ b/core/sdk/Cargo.toml @@ -21,8 +21,8 @@ edition = "2021" repository = "https://github.com/rdkcentral/Ripple" [features] -local_dev = ["jsonrpsee"] -default = ["jsonrpsee"] +local_dev = ["jsonrpsee", "sysinfo"] +default = [] rpc = ["jsonrpsee"] jsonrpsee-server = ["jsonrpsee"] tdk = [] @@ -79,9 +79,10 @@ jaq-parse = { version = "1.0.2", default-features = false } jaq-core = "1.5.0" jaq-std = { version = "1.5.1", default-features = false } mockall = "0.13.1" -jsonrpsee = { version = "=0.16.3", default-features = false,features = ["macros", "jsonrpsee-core","server"] ,optional = true } +jsonrpsee = { workspace = true, features=["server"], optional = true } serde_json = { version = "1.0", default-features = false} serde = { version = "1.0", features = ["derive"], default-features = false } +sysinfo = {version = "0.30", optional = true } [dev-dependencies] ripple_sdk = { path = ".", features=["tdk"]} From a1867e1c99e48d263b1865d236992c85c82d0a5d Mon Sep 17 00:00:00 2001 From: brendanobra Date: Tue, 19 Aug 2025 08:45:47 -0700 Subject: [PATCH 46/46] chore: more merge drama --- core/main/src/firebolt/firebolt_ws.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/main/src/firebolt/firebolt_ws.rs b/core/main/src/firebolt/firebolt_ws.rs index 4e556ecf1..954198c7a 100644 --- a/core/main/src/firebolt/firebolt_ws.rs +++ b/core/main/src/firebolt/firebolt_ws.rs @@ -376,10 +376,7 @@ impl FireboltWs { .handle_brokerage(rpc_request, None, None, vec![], None, vec![]) .await; } - #[cfg(not(feature = "ssda"))] - async fn send_t2_event(_state: &PlatformState, payload: String) { - debug!("{}", payload); - } + #[cfg(not(feature = "ssda"))] async fn handle_connection( _client_addr: SocketAddr, @@ -798,7 +795,7 @@ impl FireboltWs { } } } - +#[cfg(feature = "ssda")] async fn return_invalid_service_error_message( state: &PlatformState, connection_id: &str,