diff --git a/Cargo.lock b/Cargo.lock index aa290f2..6924d8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,55 +155,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" -dependencies = [ - "anstyle", - "windows-sys 0.59.0", -] - [[package]] name = "anyhow" version = "1.0.95" @@ -234,7 +191,7 @@ dependencies = [ "base64ct", "blake2", "cpufeatures", - "password-hash 0.5.0", + "password-hash", ] [[package]] @@ -1013,49 +970,6 @@ 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.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "cached-path" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "097968e38f1319207f057d0f4d76452e4f4f847a5de61c5215379f297fa034f3" -dependencies = [ - "flate2", - "fs2", - "glob", - "indicatif 0.16.2", - "log", - "rand 0.8.5", - "reqwest 0.11.27", - "serde", - "serde_json", - "sha2", - "tar", - "tempfile", - "thiserror", - "zip", -] - [[package]] name = "cast" version = "0.3.0" @@ -1273,7 +1187,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", - "clap_derive", ] [[package]] @@ -1282,22 +1195,8 @@ version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ - "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", -] - -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.91", ] [[package]] @@ -1333,12 +1232,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - [[package]] name = "combine" version = "4.6.7" @@ -1362,31 +1255,12 @@ 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", - "windows-sys 0.59.0", -] - [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "conv" version = "0.3.3" @@ -1605,27 +1479,6 @@ dependencies = [ "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.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1782,6 +1635,19 @@ dependencies = [ "syn 2.0.91", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -1890,34 +1756,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro 0.12.0", -] - [[package]] name = "derive_builder" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "derive_builder_macro 0.20.2", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", + "derive_builder_macro", ] [[package]] @@ -1932,23 +1777,13 @@ dependencies = [ "syn 2.0.91", ] -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core 0.12.0", - "syn 1.0.109", -] - [[package]] name = "derive_builder_macro" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "derive_builder_core 0.20.2", + "derive_builder_core", "syn 2.0.91", ] @@ -1985,15 +1820,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-next" version = "2.0.0" @@ -2004,17 +1830,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -2129,12 +1944,6 @@ dependencies = [ "zeroize", ] -[[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" @@ -2160,15 +1969,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "esaxx-rs" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" -dependencies = [ - "cc", -] - [[package]] name = "etcetera" version = "0.8.0" @@ -2315,18 +2115,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "flagset" version = "0.4.6" @@ -2400,16 +2188,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "futures" version = "0.3.31" @@ -2632,6 +2410,7 @@ dependencies = [ "thiserror", "tokio", "tokio-test", + "tokio-tungstenite 0.18.0", "tracing", "uuid", ] @@ -2682,6 +2461,7 @@ version = "0.1.0" dependencies = [ "async-trait", "futures", + "futures-util", "gb-core", "lapin", "rdkafka", @@ -2691,6 +2471,7 @@ dependencies = [ "serde_json", "tokio", "tokio-test", + "tokio-tungstenite 0.20.1", "tracing", "uuid", ] @@ -2714,36 +2495,20 @@ name = "gb-monitoring" version = "0.1.0" dependencies = [ "gb-core", - "opentelemetry", + "lazy_static", + "opentelemetry 0.19.0", + "opentelemetry-otlp", "prometheus", "rstest", "serde", "serde_json", + "thiserror", "tokio", "tokio-test", "tracing", "tracing-subscriber", ] -[[package]] -name = "gb-nlp" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "rstest", - "rust-bert", - "serde", - "serde_json", - "tch", - "thiserror", - "tokenizers", - "tokio", - "tokio-test", - "tracing", - "whatlang", -] - [[package]] name = "gb-storage" version = "0.1.0" @@ -2781,7 +2546,7 @@ dependencies = [ "hyper 1.5.2", "k8s-openapi", "kube", - "opentelemetry", + "opentelemetry 0.20.0", "predicates", "prometheus", "rand 0.8.5", @@ -3162,7 +2927,7 @@ dependencies = [ "anyhow", "auto_generate_cdp", "base64 0.22.1", - "derive_builder 0.20.2", + "derive_builder", "log", "rand 0.8.5", "regex", @@ -3735,31 +3500,6 @@ dependencies = [ "hashbrown 0.15.2", ] -[[package]] -name = "indicatif" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" -dependencies = [ - "console", - "lazy_static", - "number_prefix", - "regex", -] - -[[package]] -name = "indicatif" -version = "0.17.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" -dependencies = [ - "console", - "number_prefix", - "portable-atomic", - "unicode-width", - "web-time", -] - [[package]] name = "infer" version = "0.2.3" @@ -3832,12 +3572,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - [[package]] name = "itertools" version = "0.10.5" @@ -4161,7 +3895,6 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall", ] [[package]] @@ -4239,22 +3972,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "macro_rules_attribute" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" -dependencies = [ - "macro_rules_attribute-proc_macro", - "paste", -] - -[[package]] -name = "macro_rules_attribute-proc_macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" - [[package]] name = "matchers" version = "0.1.0" @@ -4371,27 +4088,6 @@ dependencies = [ "syn 2.0.91", ] -[[package]] -name = "monostate" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d208407d7552cd041d8cdb69a1bc3303e029c598738177a3d87082004dc0e1e" -dependencies = [ - "monostate-impl", - "serde", -] - -[[package]] -name = "monostate-impl" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ce64b975ed4f123575d11afd9491f2e37bbd5813fbfbc0f09ae1fbddea74e0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.91", -] - [[package]] name = "muldiv" version = "1.0.1" @@ -4456,19 +4152,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "ndarray" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "rawpointer", -] - [[package]] name = "nix" version = "0.26.4" @@ -4667,12 +4350,6 @@ dependencies = [ "libc", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "oauth2" version = "4.4.2" @@ -4726,28 +4403,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[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 = "oorandom" version = "11.1.4" @@ -4762,9 +4417,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "opencv" -version = "0.84.3" +version = "0.82.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a481f80995863875793f475d8fc1cabbf648e312bf359d05d415f3ffd38bfe6e" +checksum = "79290f5f138b26637cae0ae243d77de871a096e334d3fca22f5ddf31ab6f4cc5" dependencies = [ "cc", "dunce", @@ -4781,9 +4436,9 @@ dependencies = [ [[package]] name = "opencv-binding-generator" -version = "0.71.0" +version = "0.66.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaaa0844329835a9f2fa2851754f0881a64d2a44142d7a6d27362c2f8a449ea" +checksum = "be5f640bda28b478629f525e8525601586a2a2b9403a4b8f2264fa5fcfebe6be" dependencies = [ "clang", "clang-sys", @@ -4856,14 +4511,71 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "opentelemetry" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f" +dependencies = [ + "opentelemetry_api 0.19.0", + "opentelemetry_sdk 0.19.0", +] + [[package]] name = "opentelemetry" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_api 0.20.0", + "opentelemetry_sdk 0.20.0", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8af72d59a4484654ea8eb183fea5ae4eb6a41d7ac3e3bae5f4d2a282a3a7d3ca" +dependencies = [ + "async-trait", + "futures", + "futures-util", + "http 0.2.12", + "opentelemetry 0.19.0", + "opentelemetry-proto", + "prost 0.11.9", + "thiserror", + "tokio", + "tonic 0.8.3", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "045f8eea8c0fa19f7d48e7bc3128a39c2e5c533d5c61298c548dfefc1064474c" +dependencies = [ + "futures", + "futures-util", + "opentelemetry 0.19.0", + "prost 0.11.9", + "tonic 0.8.3", +] + +[[package]] +name = "opentelemetry_api" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2" +dependencies = [ + "fnv", + "futures-channel", + "futures-util", + "indexmap 1.9.3", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", ] [[package]] @@ -4882,6 +4594,28 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "opentelemetry_sdk" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1" +dependencies = [ + "async-trait", + "crossbeam-channel", + "dashmap", + "fnv", + "futures-channel", + "futures-executor", + "futures-util", + "once_cell", + "opentelemetry_api 0.19.0", + "percent-encoding", + "rand 0.8.5", + "thiserror", + "tokio", + "tokio-stream", +] + [[package]] name = "opentelemetry_sdk" version = "0.20.0" @@ -4894,7 +4628,7 @@ dependencies = [ "futures-executor", "futures-util", "once_cell", - "opentelemetry_api", + "opentelemetry_api 0.20.0", "ordered-float 3.9.2", "percent-encoding", "rand 0.8.5", @@ -5030,17 +4764,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[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 = "password-hash" version = "0.5.0" @@ -5058,18 +4781,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash 0.4.2", - "sha2", -] - [[package]] name = "pbkdf2" version = "0.12.2" @@ -5210,7 +4921,7 @@ dependencies = [ "aes", "cbc", "der", - "pbkdf2 0.12.2", + "pbkdf2", "scrypt", "sha2", "spki", @@ -5316,12 +5027,6 @@ dependencies = [ "universal-hash", ] -[[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" @@ -5466,6 +5171,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", +] + [[package]] name = "prost" version = "0.12.6" @@ -5473,7 +5188,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.12.6", +] + +[[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]] @@ -5625,17 +5353,6 @@ dependencies = [ "rayon-core", ] -[[package]] -name = "rayon-cond" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" -dependencies = [ - "either", - "itertools 0.11.0", - "rayon", -] - [[package]] name = "rayon-core" version = "1.12.1" @@ -6032,46 +5749,6 @@ dependencies = [ "webrtc-util", ] -[[package]] -name = "rust-bert" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8792cccdf842159ef04a35f247df68ccc42192e9a67e389e6cd0f1a83970a6a0" -dependencies = [ - "cached-path", - "dirs", - "half", - "lazy_static", - "ordered-float 3.9.2", - "regex", - "rust_tokenizers", - "serde", - "serde_json", - "tch", - "thiserror", - "uuid", -] - -[[package]] -name = "rust_tokenizers" -version = "8.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19599f60a688b5160247ee9c37a6af8b0c742ee8b160c5b44acc0f0eb265a59f" -dependencies = [ - "csv", - "hashbrown 0.14.5", - "itertools 0.11.0", - "lazy_static", - "protobuf", - "rayon", - "regex", - "serde", - "serde_json", - "thiserror", - "unicode-normalization", - "unicode-normalization-alignments", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -6258,16 +5935,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "safetensors" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93279b86b3de76f820a8854dd06cbc33cfa57a417b19c47f6a25280112fb1df" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "salsa20" version = "0.10.2" @@ -6331,7 +5998,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" dependencies = [ - "pbkdf2 0.12.2", + "pbkdf2", "salsa20", "sha2", ] @@ -6726,18 +6393,6 @@ dependencies = [ "der", ] -[[package]] -name = "spm_precompiled" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" -dependencies = [ - "base64 0.13.1", - "nom", - "serde", - "unicode-segmentation", -] - [[package]] name = "sqlformat" version = "0.2.6" @@ -7152,40 +6807,12 @@ dependencies = [ "version-compare", ] -[[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 = "target-lexicon" version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" -[[package]] -name = "tch" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbd9ce6fb581a1b918db880b649d1364b50f7f6717eda8497bcdc929cddd4b9" -dependencies = [ - "half", - "lazy_static", - "libc", - "ndarray", - "rand 0.8.5", - "safetensors", - "thiserror", - "torch-sys", - "zip", -] - [[package]] name = "tcp-stream" version = "0.28.0" @@ -7334,7 +6961,7 @@ dependencies = [ "log", "pin-project", "prometheus", - "prost", + "prost 0.12.6", "rand 0.8.5", "regex", "semver", @@ -7342,7 +6969,7 @@ dependencies = [ "serde_derive", "thiserror", "tokio", - "tonic", + "tonic 0.10.2", ] [[package]] @@ -7413,39 +7040,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokenizers" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dd47962b0ba36e7fd33518fbf1754d136fd1474000162bbf2a8b5fcb2d3654d" -dependencies = [ - "aho-corasick", - "clap", - "derive_builder 0.12.0", - "esaxx-rs", - "getrandom 0.2.15", - "indicatif 0.17.9", - "itertools 0.12.1", - "lazy_static", - "log", - "macro_rules_attribute", - "monostate", - "onig", - "paste", - "rand 0.8.5", - "rayon", - "rayon-cond", - "regex", - "regex-syntax 0.8.5", - "serde", - "serde_json", - "spm_precompiled", - "thiserror", - "unicode-normalization-alignments", - "unicode-segmentation", - "unicode_categories", -] - [[package]] name = "tokio" version = "1.42.0" @@ -7561,6 +7155,18 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "tokio-tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.18.0", +] + [[package]] name = "tokio-tungstenite" version = "0.20.1" @@ -7569,7 +7175,9 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", + "native-tls", "tokio", + "tokio-native-tls", "tungstenite 0.20.1", ] @@ -7633,6 +7241,38 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.6.20", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.11.9", + "prost-derive 0.11.9", + "tokio", + "tokio-stream", + "tokio-util", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + [[package]] name = "tonic" version = "0.10.2" @@ -7651,7 +7291,7 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost", + "prost 0.12.6", "rustls 0.21.12", "rustls-pemfile 1.0.4", "tokio", @@ -7663,18 +7303,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "torch-sys" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b2b81a479510717464df1d07c02cb4aebb26539a39b5db6637dda114a476cb" -dependencies = [ - "anyhow", - "cc", - "libc", - "zip", -] - [[package]] name = "tower" version = "0.4.13" @@ -7796,6 +7424,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.2.0" @@ -7820,6 +7458,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", + "time", "tracing", "tracing-core", "tracing-log", @@ -7837,6 +7476,25 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" +[[package]] +name = "tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +dependencies = [ + "base64 0.13.1", + "byteorder", + "bytes", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "tungstenite" version = "0.20.1" @@ -7849,6 +7507,7 @@ dependencies = [ "http 0.2.12", "httparse", "log", + "native-tls", "rand 0.8.5", "sha1", "thiserror", @@ -7921,15 +7580,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-normalization-alignments" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" -dependencies = [ - "smallvec", -] - [[package]] name = "unicode-properties" version = "0.1.3" @@ -7942,12 +7592,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[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" @@ -8041,12 +7685,6 @@ 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.11.0" @@ -8280,16 +7918,6 @@ dependencies = [ "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 = "webdriver" version = "0.46.0" @@ -8533,16 +8161,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" -[[package]] -name = "whatlang" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "471d1c1645d361eb782a1650b1786a8fb58dd625e681a04c09f5ff7c8764a7b0" -dependencies = [ - "hashbrown 0.14.5", - "once_cell", -] - [[package]] name = "which" version = "4.4.2" @@ -8942,17 +8560,6 @@ dependencies = [ "time", ] -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys 0.4.14", - "rustix 0.38.42", -] - [[package]] name = "yasna" version = "0.5.2" @@ -9070,55 +8677,6 @@ dependencies = [ "syn 2.0.91", ] -[[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 0.11.0", - "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", -] - [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index 8585460..5327228 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver="2" members = [ "gb-core", # Core domain models and traits "gb-api", # API layer and server implementation @@ -12,7 +13,6 @@ members = [ #"gb-cloud", # Cloud provider integrations #"gb-vm", # Virtual machine and BASIC compiler "gb-automation", # Web and process automation - "gb-nlp", # Natural language processing "gb-image", # Image processing capabilities ] @@ -72,7 +72,7 @@ azure_identity = "0.15" google-cloud-storage = "0.16" # Monitoring and metrics -prometheus = "0.13" +prometheus = "0.13.0" opentelemetry = { version = "0.20", features = ["rt-tokio"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/gb-auth/src/handlers/auth_handler.rs b/gb-auth/src/handlers/auth_handler.rs index a4506ae..afedd9e 100644 --- a/gb-auth/src/handlers/auth_handler.rs +++ b/gb-auth/src/handlers/auth_handler.rs @@ -24,4 +24,4 @@ pub async fn logout() -> Result<()> { pub async fn refresh_token() -> Result> { todo!() -} +} \ No newline at end of file diff --git a/gb-auth/src/handlers/mod.rs b/gb-auth/src/handlers/mod.rs new file mode 100644 index 0000000..b857d0d --- /dev/null +++ b/gb-auth/src/handlers/mod.rs @@ -0,0 +1,3 @@ +mod auth_handler; + +pub use auth_handler::*; \ No newline at end of file diff --git a/gb-auth/src/middleware/auth_middleware.rs b/gb-auth/src/middleware/auth_middleware.rs index a24d021..1938d32 100644 --- a/gb-auth/src/middleware/auth_middleware.rs +++ b/gb-auth/src/middleware/auth_middleware.rs @@ -28,4 +28,4 @@ where // Implement token validation and user extraction todo!() } -} +} \ No newline at end of file diff --git a/gb-auth/src/middleware/mod.rs b/gb-auth/src/middleware/mod.rs new file mode 100644 index 0000000..8e901a8 --- /dev/null +++ b/gb-auth/src/middleware/mod.rs @@ -0,0 +1,3 @@ +mod auth_middleware; + +pub use auth_middleware::*; \ No newline at end of file diff --git a/gb-auth/src/models/mod.rs b/gb-auth/src/models/mod.rs new file mode 100644 index 0000000..a54447d --- /dev/null +++ b/gb-auth/src/models/mod.rs @@ -0,0 +1,3 @@ +mod user; + +pub use user::*; \ No newline at end of file diff --git a/gb-auth/src/models/user.rs b/gb-auth/src/models/user.rs index af8deb2..2360d54 100644 --- a/gb-auth/src/models/user.rs +++ b/gb-auth/src/models/user.rs @@ -42,4 +42,4 @@ pub struct LoginResponse { pub refresh_token: String, pub token_type: String, pub expires_in: i64, -} +} \ No newline at end of file diff --git a/gb-auth/src/services/auth_service.rs b/gb-auth/src/services/auth_service.rs index 1290a82..0bc0e6e 100644 --- a/gb-auth/src/services/auth_service.rs +++ b/gb-auth/src/services/auth_service.rs @@ -1,14 +1,16 @@ +use std::sync::Arc; +use sqlx::PgPool; +use argon2::{ + password_hash::{PasswordHash, PasswordHasher, SaltString}, + Argon2, +}; +use rand::rngs::OsRng; + use crate::{ models::{LoginRequest, LoginResponse, User}, - Result, AuthError, + AuthError, + Result, }; -use argon2::{ - password_hash::{rand_core::OsRng, SaltString}, - Argon2, PasswordHash, PasswordHasher, PasswordVerifier, -}; -use jsonwebtoken::{encode, EncodingKey, Header}; -use sqlx::PgPool; -use std::sync::Arc; pub struct AuthService { db: Arc, @@ -70,4 +72,4 @@ impl AuthService { // Token generation implementation Ok("token".to_string()) } -} +} \ No newline at end of file diff --git a/gb-auth/src/services/mod.rs b/gb-auth/src/services/mod.rs new file mode 100644 index 0000000..ae31fe4 --- /dev/null +++ b/gb-auth/src/services/mod.rs @@ -0,0 +1,3 @@ +pub mod auth_service; + +pub use auth_service::*; \ No newline at end of file diff --git a/gb-auth/src/utils/mod.rs b/gb-auth/src/utils/mod.rs new file mode 100644 index 0000000..6d9e419 --- /dev/null +++ b/gb-auth/src/utils/mod.rs @@ -0,0 +1 @@ +// Auth utilities module \ No newline at end of file diff --git a/gb-core/Cargo.toml b/gb-core/Cargo.toml index e2cfccb..e545ba2 100644 --- a/gb-core/Cargo.toml +++ b/gb-core/Cargo.toml @@ -6,6 +6,7 @@ authors.workspace = true license.workspace = true [dependencies] +tokio-tungstenite = "0.18" async-trait.workspace = true serde.workspace = true uuid.workspace = true diff --git a/gb-core/src/errors.rs b/gb-core/src/errors.rs index 45bceff..a04b5c0 100644 --- a/gb-core/src/errors.rs +++ b/gb-core/src/errors.rs @@ -1,54 +1,82 @@ use thiserror::Error; -use redis::RedisError; #[derive(Error, Debug)] -pub enum Error { +pub enum ErrorKind { #[error("Database error: {0}")] - Database(#[from] sqlx::Error), - + Database(String), + #[error("Redis error: {0}")] - Redis(#[from] redis::RedisError), - + Redis(String), + #[error("Kafka error: {0}")] Kafka(String), - - #[error("WebRTC error: {0}")] - WebRTC(String), - + #[error("Invalid input: {0}")] InvalidInput(String), - + #[error("Not found: {0}")] NotFound(String), - - #[error("Unauthorized: {0}")] - Unauthorized(String), - - #[error("Rate limited: {0}")] - RateLimited(String), - - #[error("Resource quota exceeded: {0}")] - QuotaExceeded(String), - + + #[error("Authentication error: {0}")] + Authentication(String), + + #[error("Authorization error: {0}")] + Authorization(String), + #[error("Internal error: {0}")] Internal(String), + + #[error("External service error: {0}")] + ExternalService(String), + + #[error("WebSocket error: {0}")] + WebSocket(String), + + #[error("Messaging error: {0}")] + Messaging(String), } -pub type Result = std::result::Result; +#[derive(Debug)] +pub struct Error { + pub kind: ErrorKind, + pub message: String, +} -#[cfg(test)] -mod tests { - use super::*; +impl Error { + pub fn new(kind: ErrorKind, message: impl Into) -> Self { + Self { + kind, + message: message.into(), + } + } - #[test] - fn test_error_display() { - let err = Error::NotFound("User".to_string()); - assert_eq!(err.to_string(), "Not found: User"); + pub fn internal(msg: T) -> Self { + Self::new(ErrorKind::Internal(msg.to_string()), msg.to_string()) + } - let err = Error::Unauthorized("Invalid token".to_string()); - assert_eq!(err.to_string(), "Unauthorized: Invalid token"); + pub fn redis(msg: T) -> Self { + Self::new(ErrorKind::Redis(msg.to_string()), msg.to_string()) + } - let err = Error::QuotaExceeded("Max instances reached".to_string()); - assert_eq!(err.to_string(), "Resource quota exceeded: Max instances reached"); + pub fn kafka(msg: T) -> Self { + Self::new(ErrorKind::Kafka(msg.to_string()), msg.to_string()) + } + + pub fn database(msg: T) -> Self { + Self::new(ErrorKind::Database(msg.to_string()), msg.to_string()) + } + + pub fn websocket(msg: T) -> Self { + Self::new(ErrorKind::WebSocket(msg.to_string()), msg.to_string()) } } + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.kind, self.message) + } +} + +impl std::error::Error for Error {} + +pub type Result = std::result::Result; \ No newline at end of file diff --git a/gb-core/src/lib.rs b/gb-core/src/lib.rs index 3ffabf2..9c0a7f9 100644 --- a/gb-core/src/lib.rs +++ b/gb-core/src/lib.rs @@ -1,8 +1,10 @@ +pub mod errors; pub mod models; pub mod traits; -pub mod errors; -pub use errors::{Error, Result}; +pub use errors::{Error, ErrorKind, Result}; + + pub use models::*; pub use traits::*; diff --git a/gb-core/src/models.rs b/gb-core/src/models.rs index 3412910..b5835d0 100644 --- a/gb-core/src/models.rs +++ b/gb-core/src/models.rs @@ -1,17 +1,19 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use sqlx::types::JsonValue; use uuid::Uuid; #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Customer { +pub struct Message { pub id: Uuid, - pub name: String, - pub subscription_tier: String, + pub conversation_id: Uuid, + pub sender_id: Uuid, + pub content: String, pub status: String, - pub max_instances: i32, - pub metadata: JsonValue, + pub message_type: String, + pub kind: String, // Add this field + pub shard_key: i32, pub created_at: DateTime, + pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -19,95 +21,138 @@ pub struct Instance { pub id: Uuid, pub customer_id: Uuid, pub name: String, - pub status: String, pub shard_id: i32, - pub region: String, - pub config: JsonValue, pub created_at: DateTime, + pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Room { pub id: Uuid, - pub customer_id: Uuid, pub instance_id: Uuid, pub name: String, - pub kind: String, - pub status: String, - pub config: JsonValue, + pub is_active: bool, pub created_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Message { - pub id: Uuid, - pub customer_id: Uuid, - pub instance_id: Uuid, - pub conversation_id: Uuid, - pub sender_id: Uuid, - pub kind: String, - pub content: String, - pub metadata: JsonValue, - pub created_at: DateTime, - pub shard_key: i32, + pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Track { pub id: Uuid, pub room_id: Uuid, - pub user_id: Uuid, - pub kind: String, - pub status: String, - pub metadata: JsonValue, + pub user_id: Uuid, + pub media_type: String, + pub created_at: DateTime, + pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct User { pub id: Uuid, - pub customer_id: Uuid, pub instance_id: Uuid, + pub email: String, + pub name: String, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Customer { + pub id: Uuid, pub name: String, pub email: String, - pub status: String, - pub metadata: JsonValue, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RoomConfig { + pub instance_id: Uuid, + pub name: String, + pub max_participants: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Connection { + pub id: Uuid, + pub room_id: Uuid, + pub user_id: Uuid, + pub connected_at: DateTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TrackInfo { + pub room_id: Uuid, + pub user_id: Uuid, + pub media_type: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Subscription { + pub id: Uuid, + pub track_id: Uuid, + pub subscriber_id: Uuid, pub created_at: DateTime, } -impl Customer { - pub fn new( - name: String, - subscription_tier: String, - max_instances: i32, - ) -> Self { - Self { - id: Uuid::new_v4(), - name, - subscription_tier, - status: "active".to_string(), - max_instances, - metadata: HashMap::new(), - created_at: Utc::now() - } - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Participant { + pub user_id: Uuid, + pub room_id: Uuid, + pub joined_at: DateTime, } -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - #[rstest] - fn test_customer_creation() { - let customer = Customer::new( - "Test Corp".to_string(), - "enterprise".to_string(), - 10, - ); - - assert_eq!(customer.name, "Test Corp"); - assert_eq!(customer.subscription_tier, "enterprise"); - assert_eq!(customer.max_instances, 10); - assert_eq!(customer.status, "active"); - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RoomStats { + pub participant_count: u32, + pub track_count: u32, + pub duration: i64, } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MessageId(pub Uuid); + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MessageFilter { + pub conversation_id: Option, + pub sender_id: Option, + pub from_date: Option>, + pub to_date: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Status { + pub code: String, + pub timestamp: DateTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SearchQuery { + pub query: String, + pub conversation_id: Option, + pub from_date: Option>, + pub to_date: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FileUpload { + pub content: Vec, + pub filename: String, + pub content_type: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FileInfo { + pub id: Uuid, + pub filename: String, + pub content_type: String, + pub size: u64, + pub created_at: DateTime, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FileContent { + pub content: Vec, + pub content_type: String, +} + diff --git a/gb-core/src/traits.rs b/gb-core/src/traits.rs index c40752d..e93b7ef 100644 --- a/gb-core/src/traits.rs +++ b/gb-core/src/traits.rs @@ -1,99 +1,76 @@ -use async_trait::async_trait; -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; -use serde::{Map, Value as JsonValue}; +use std::future::Future; use uuid::Uuid; -use crate::{models::*, Result}; +use crate::errors::Result; +use crate::models::{ + Customer, Instance, Room, Track, User, Message, Connection, + TrackInfo, Subscription, Participant, RoomStats, MessageId, + MessageFilter, Status, SearchQuery, FileUpload, FileInfo, + FileContent, RoomConfig +}; -#[async_trait] pub trait CustomerRepository: Send + Sync { - async fn create(&self, customer: &Customer) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn update(&self, customer: &Customer) -> Result; - async fn delete(&self, id: Uuid) -> Result<()>; + fn create(&self, customer: &Customer) -> impl Future> + Send; + fn get(&self, id: Uuid) -> impl Future> + Send; + fn update(&self, customer: &Customer) -> impl Future> + Send; + fn delete(&self, id: Uuid) -> impl Future> + Send; } -#[async_trait] pub trait InstanceRepository: Send + Sync { - async fn create(&self, instance: &Instance) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn get_by_customer(&self, customer_id: Uuid) -> Result>; - async fn update(&self, instance: &Instance) -> Result; - async fn delete(&self, id: Uuid) -> Result<()>; - async fn get_by_shard(&self, shard_id: i32) -> Result>; + fn create(&self, instance: &Instance) -> impl Future> + Send; + fn get(&self, id: Uuid) -> impl Future> + Send; + fn get_by_customer(&self, customer_id: Uuid) -> impl Future>> + Send; + fn update(&self, instance: &Instance) -> impl Future> + Send; + fn delete(&self, id: Uuid) -> impl Future> + Send; + fn get_by_shard(&self, shard_id: i32) -> impl Future>> + Send; } -#[async_trait] pub trait RoomRepository: Send + Sync { - async fn create(&self, room: &Room) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn get_by_instance(&self, instance_id: Uuid) -> Result>; - async fn update(&self, room: &Room) -> Result; - async fn delete(&self, id: Uuid) -> Result<()>; - async fn get_active_rooms(&self, instance_id: Uuid) -> Result>; + fn create(&self, room: &Room) -> impl Future> + Send; + fn get(&self, id: Uuid) -> impl Future> + Send; + fn get_by_instance(&self, instance_id: Uuid) -> impl Future>> + Send; + fn update(&self, room: &Room) -> impl Future> + Send; + fn delete(&self, id: Uuid) -> impl Future> + Send; + fn get_active_rooms(&self, instance_id: Uuid) -> impl Future>> + Send; } -#[async_trait] -pub trait MessageRepository: Send + Sync { - async fn create(&self, message: &Message) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn get_by_conversation(&self, conversation_id: Uuid) -> Result>; - async fn update_status(&self, id: Uuid, status: String) -> Result<()>; - async fn delete(&self, id: Uuid) -> Result<()>; - async fn get_by_shard(&self, shard_key: i32) -> Result>; -} - -#[async_trait] pub trait TrackRepository: Send + Sync { - async fn create(&self, track: &Track) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn get_by_room(&self, room_id: Uuid) -> Result>; - async fn update(&self, track: &Track) -> Result; - async fn delete(&self, id: Uuid) -> Result<()>; + fn create(&self, track: &Track) -> impl Future> + Send; + fn get(&self, id: Uuid) -> impl Future> + Send; + fn get_by_room(&self, room_id: Uuid) -> impl Future>> + Send; + fn update(&self, track: &Track) -> impl Future> + Send; + fn delete(&self, id: Uuid) -> impl Future> + Send; } -#[async_trait] pub trait UserRepository: Send + Sync { - async fn create(&self, user: &User) -> Result; - async fn get(&self, id: Uuid) -> Result; - async fn get_by_email(&self, email: &str) -> Result; - async fn get_by_instance(&self, instance_id: Uuid) -> Result>; - async fn update(&self, user: &User) -> Result; - async fn delete(&self, id: Uuid) -> Result<()>; + fn create(&self, user: &User) -> impl Future> + Send; + fn get(&self, id: Uuid) -> impl Future> + Send; + fn get_by_email(&self, email: &str) -> impl Future> + Send; + fn get_by_instance(&self, instance_id: Uuid) -> impl Future>> + Send; + fn update(&self, user: &User) -> impl Future> + Send; + fn delete(&self, id: Uuid) -> impl Future> + Send; } -#[async_trait] pub trait RoomService: Send + Sync { - async fn create_room(&self, config: RoomConfig) -> Result; - async fn join_room(&self, room_id: Uuid, user_id: Uuid) -> Result; - async fn leave_room(&self, room_id: Uuid, user_id: Uuid) -> Result<()>; - async fn publish_track(&self, track: TrackInfo) -> Result; - async fn subscribe_track(&self, track_id: Uuid) -> Result; - async fn get_participants(&self, room_id: Uuid) -> Result>; - async fn get_room_stats(&self, room_id: Uuid) -> Result; + fn create_room(&self, config: RoomConfig) -> impl Future> + Send; + fn join_room(&self, room_id: Uuid, user_id: Uuid) -> impl Future> + Send; + fn leave_room(&self, room_id: Uuid, user_id: Uuid) -> impl Future> + Send; + fn publish_track(&self, track: TrackInfo) -> impl Future> + Send; + fn subscribe_track(&self, track_id: Uuid) -> impl Future> + Send; + fn get_participants(&self, room_id: Uuid) -> impl Future>> + Send; + fn get_room_stats(&self, room_id: Uuid) -> impl Future> + Send; } -#[async_trait] pub trait MessageService: Send + Sync { - async fn send_message(&self, message: Message) -> Result; - async fn get_messages(&self, filter: MessageFilter) -> Result>; - async fn update_status(&self, message_id: Uuid, status: Status) -> Result<()>; - async fn delete_messages(&self, filter: MessageFilter) -> Result<()>; - async fn search_messages(&self, query: SearchQuery) -> Result>; + fn send_message(&self, message: Message) -> impl Future> + Send; + fn get_messages(&self, filter: MessageFilter) -> impl Future>> + Send; + fn update_status(&self, message_id: Uuid, status: Status) -> impl Future> + Send; + fn delete_messages(&self, filter: MessageFilter) -> impl Future> + Send; + fn search_messages(&self, query: SearchQuery) -> impl Future>> + Send; } -#[async_trait] -pub trait StorageService: Send + Sync { - async fn save_file(&self, file: FileUpload) -> Result; - async fn get_file(&self, file_id: Uuid) -> Result; - async fn delete_file(&self, file_id: Uuid) -> Result<()>; - async fn list_files(&self, prefix: &str) -> Result>; -} - -#[async_trait] -pub trait MetricsService: Send + Sync { - async fn record_metric(&self, metric: Metric) -> Result<()>; - async fn get_metrics(&self, query: MetricsQuery) -> Result>; - async fn create_dashboard(&self, config: DashboardConfig) -> Result; - async fn get_dashboard(&self, id: Uuid) -> Result; -} +pub trait FileService: Send + Sync { + fn save_file(&self, file: FileUpload) -> impl Future> + Send; + fn get_file(&self, file_id: Uuid) -> impl Future> + Send; + fn delete_file(&self, file_id: Uuid) -> impl Future> + Send; + fn list_files(&self, prefix: &str) -> impl Future>> + Send; +} \ No newline at end of file diff --git a/gb-image/Cargo.toml b/gb-image/Cargo.toml index 89e1b1f..e362ddc 100644 --- a/gb-image/Cargo.toml +++ b/gb-image/Cargo.toml @@ -11,7 +11,7 @@ image = { version = "0.24", features = ["webp", "jpeg", "png", "gif"] } imageproc = "0.23" rusttype = "0.9" tesseract = "0.13" -opencv = { version = "0.84", features = ["clang-runtime"] } +opencv = { version = "0.82", features = ["clang-runtime"] } async-trait.workspace = true tokio.workspace = true serde.workspace = true diff --git a/gb-messaging/Cargo.toml b/gb-messaging/Cargo.toml index 2f22722..b882526 100644 --- a/gb-messaging/Cargo.toml +++ b/gb-messaging/Cargo.toml @@ -16,8 +16,10 @@ uuid.workspace = true async-trait.workspace = true tracing.workspace = true futures.workspace = true +futures-util = "0.3" lapin = "2.3" +tokio-tungstenite = { version = "0.20", features = ["native-tls"] } [dev-dependencies] rstest.workspace = true -tokio-test = "0.4" +tokio-test = "0.4" \ No newline at end of file diff --git a/gb-messaging/src/kafka.rs b/gb-messaging/src/kafka.rs index d20bdc7..8dc8efe 100644 --- a/gb-messaging/src/kafka.rs +++ b/gb-messaging/src/kafka.rs @@ -1,35 +1,27 @@ -use async_trait::async_trait; -use gb_core::{Result, Error, models::Message}; -use rdkafka::{ - producer::{FutureProducer, FutureRecord}, - consumer::{StreamConsumer, Consumer}, - ClientConfig, Message as KafkaMessage, -}; -use serde::{de::DeserializeOwned, Serialize}; +use gb_core::{Result, Error}; +use rdkafka::producer::{FutureProducer, FutureRecord}; +use rdkafka::consumer::{StreamConsumer, Consumer}; +use rdkafka::ClientConfig; use std::time::Duration; -use tracing::{instrument, error, info}; -use uuid::Uuid; - -pub struct KafkaBroker { +use tracing::{instrument, error}; +use serde::Serialize; +pub struct Kafka { producer: FutureProducer, consumer: StreamConsumer, } -impl KafkaBroker { - pub fn new(brokers: &str, group_id: &str) -> Result { - let producer: FutureProducer = ClientConfig::new() +impl Kafka { + pub async fn new(brokers: &str) -> Result { + let producer = ClientConfig::new() .set("bootstrap.servers", brokers) - .set("message.timeout.ms", "5000") .create() - .map_err(|e| Error::Kafka(format!("Failed to create producer: {}", e)))?; + .map_err(|e| Error::kafka(format!("Failed to create producer: {}", e)))?; - let consumer: StreamConsumer = ClientConfig::new() + let consumer = ClientConfig::new() .set("bootstrap.servers", brokers) - .set("group.id", group_id) - .set("enable.auto.commit", "true") - .set("auto.offset.reset", "earliest") + .set("group.id", "my-group") .create() - .map_err(|e| Error::Kafka(format!("Failed to create consumer: {}", e)))?; + .map_err(|e| Error::kafka(format!("Failed to create consumer: {}", e)))?; Ok(Self { producer, @@ -37,60 +29,37 @@ impl KafkaBroker { }) } - #[instrument(skip(self, value))] - pub async fn publish(&self, topic: &str, key: &str, value: &T) -> Result<()> { - let payload = serde_json::to_string(value) - .map_err(|e| Error::Internal(format!("Serialization error: {}", e)))?; + pub async fn publish(&self, topic: &str, message: &T) -> Result<()> { + let payload = serde_json::to_string(message) + .map_err(|e| Error::internal(format!("Serialization error: {}", e)))?; self.producer .send( FutureRecord::to(topic) - .key(key) - .payload(&payload), - Duration::from_secs(5), + .payload(payload.as_bytes()) + .key(""), + Duration::from_secs(0), ) .await - .map_err(|(e, _)| Error::Kafka(format!("Failed to send message: {}", e)))?; + .map_err(|(e, _)| Error::kafka(format!("Failed to send message: {}", e)))?; Ok(()) } - #[instrument(skip(self, handler))] - pub async fn subscribe(&self, topics: &[&str], handler: F) -> Result<()> - where - T: DeserializeOwned, - F: Fn(T) -> Fut, - Fut: std::future::Future>, - { + pub async fn subscribe(&self, topic: &str) -> Result<()> { self.consumer - .subscribe(topics) - .map_err(|e| Error::Kafka(format!("Failed to subscribe: {}", e)))?; + .subscribe(&[topic]) + .map_err(|e| Error::kafka(format!("Failed to subscribe: {}", e)))?; - loop { - match self.consumer.recv().await { - Ok(msg) => { - if let Some(payload) = msg.payload() { - match serde_json::from_slice::(payload) { - Ok(value) => { - if let Err(e) = handler(value).await { - error!("Handler error: {}", e); - } - } - Err(e) => error!("Deserialization error: {}", e), - } - } - } - Err(e) => error!("Consumer error: {}", e), - } - } + Ok(()) } } - #[cfg(test)] mod tests { use super::*; use rstest::*; use serde::{Deserialize, Serialize}; + use uuid::Uuid; #[derive(Debug, Serialize, Deserialize, PartialEq)] struct TestMessage { @@ -99,11 +68,8 @@ mod tests { } #[fixture] - fn kafka_broker() -> KafkaBroker { - KafkaBroker::new( - "localhost:9092", - "test-group", - ).unwrap() + async fn kafka_broker() -> Kafka { + Kafka::new("localhost:9092").await.unwrap() } #[fixture] @@ -116,29 +82,15 @@ mod tests { #[rstest] #[tokio::test] - async fn test_publish_subscribe( - kafka_broker: KafkaBroker, - test_message: TestMessage, - ) { + async fn test_publish_subscribe(#[future] kafka_broker: Kafka, test_message: TestMessage) { let topic = "test-topic"; - let key = test_message.id.to_string(); - - // Publish message - kafka_broker.publish(topic, &key, &test_message) + kafka_broker.publish(topic, &test_message) .await .unwrap(); - // Subscribe and verify - let handler = |msg: TestMessage| async move { - assert_eq!(msg, test_message); - Ok(()) - }; - - // Run subscription for a short time - tokio::spawn(async move { - kafka_broker.subscribe(&[topic], handler).await.unwrap(); - }); - + kafka_broker.subscribe(topic) + .await + .unwrap(); tokio::time::sleep(Duration::from_secs(1)).await; } } diff --git a/gb-messaging/src/lib.rs b/gb-messaging/src/lib.rs index 6fa91a9..8cff28e 100644 --- a/gb-messaging/src/lib.rs +++ b/gb-messaging/src/lib.rs @@ -1,14 +1,14 @@ -pub mod kafka; -pub mod redis_pubsub; -pub mod rabbitmq; -pub mod websocket; -pub mod processor; +mod kafka; +mod rabbitmq; +mod redis_pubsub; +mod websocket; +mod processor; -pub use kafka::KafkaBroker; -pub use redis_pubsub::RedisPubSub; +pub use kafka::Kafka; pub use rabbitmq::RabbitMQ; +pub use redis_pubsub::RedisPubSub; pub use websocket::WebSocketClient; -pub use processor::{MessageProcessor, MessageEnvelope}; +pub use processor::MessageProcessor; #[cfg(test)] mod tests { @@ -26,7 +26,6 @@ mod tests { #[tokio::test] async fn test_messaging_integration() { - // Initialize message brokers let kafka = KafkaBroker::new( "localhost:9092", "test-group", @@ -40,37 +39,31 @@ mod tests { .await .unwrap(); - let websocket = WebSocketClient::connect("ws://localhost:8080") + let mut websocket = WebSocketClient::connect("ws://localhost:8080") .await .unwrap(); - // Create test message let test_message = TestMessage { id: Uuid::new_v4(), content: "integration test".to_string(), }; - // Test Kafka kafka.publish("test-topic", &test_message.id.to_string(), &test_message) .await .unwrap(); - // Test Redis PubSub redis.publish("test-channel", &test_message) .await .unwrap(); - // Test RabbitMQ rabbitmq.publish("", "test.key", &test_message) .await .unwrap(); - // Test WebSocket - websocket.send(&test_message) + websocket.send_message(serde_json::to_string(&test_message).unwrap()) .await .unwrap(); - // Test Message Processor let mut processor = MessageProcessor::new(100); processor.register_handler("test", |envelope| { diff --git a/gb-messaging/src/rabbitmq.rs b/gb-messaging/src/rabbitmq.rs index 9d29547..4714e96 100644 --- a/gb-messaging/src/rabbitmq.rs +++ b/gb-messaging/src/rabbitmq.rs @@ -1,22 +1,31 @@ -use async_trait::async_trait; use gb_core::{Result, Error}; use lapin::{ options::*, types::FieldTable, Connection, ConnectionProperties, - Channel, Consumer, - message::Delivery, + Channel, + BasicProperties, }; use serde::{de::DeserializeOwned, Serialize}; use std::sync::Arc; use tokio::sync::Mutex; use tracing::{instrument, error}; +use futures::StreamExt; pub struct RabbitMQ { - connection: Connection, + connection: Arc, channel: Arc>, } +impl Clone for RabbitMQ { + fn clone(&self) -> Self { + Self { + connection: self.connection.clone(), + channel: self.channel.clone(), + } + } +} + impl RabbitMQ { pub async fn new(url: &str) -> Result { let connection = Connection::connect( @@ -24,14 +33,14 @@ impl RabbitMQ { ConnectionProperties::default(), ) .await - .map_err(|e| Error::Internal(format!("RabbitMQ connection error: {}", e)))?; + .map_err(|e| Error::internal(format!("RabbitMQ connection error: {}", e)))?; let channel = connection.create_channel() .await - .map_err(|e| Error::Internal(format!("RabbitMQ channel error: {}", e)))?; + .map_err(|e| Error::internal(format!("RabbitMQ channel error: {}", e)))?; Ok(Self { - connection, + connection: Arc::new(connection), channel: Arc::new(Mutex::new(channel)), }) } @@ -44,7 +53,7 @@ impl RabbitMQ { message: &T, ) -> Result<()> { let payload = serde_json::to_string(message) - .map_err(|e| Error::Internal(format!("Serialization error: {}", e)))?; + .map_err(|e| Error::internal(format!("Serialization error: {}", e)))?; let channel = self.channel.lock().await; @@ -56,7 +65,7 @@ impl RabbitMQ { BasicProperties::default(), ) .await - .map_err(|e| Error::Internal(format!("RabbitMQ publish error: {}", e)))?; + .map_err(|e| Error::internal(format!("RabbitMQ publish error: {}", e)))?; Ok(()) } @@ -80,7 +89,7 @@ impl RabbitMQ { FieldTable::default(), ) .await - .map_err(|e| Error::Internal(format!("RabbitMQ queue declare error: {}", e)))?; + .map_err(|e| Error::internal(format!("RabbitMQ queue declare error: {}", e)))?; let mut consumer = channel.basic_consume( queue, @@ -89,7 +98,7 @@ impl RabbitMQ { FieldTable::default(), ) .await - .map_err(|e| Error::Internal(format!("RabbitMQ consume error: {}", e)))?; + .map_err(|e| Error::internal(format!("RabbitMQ consume error: {}", e)))?; while let Some(delivery) = consumer.next().await { match delivery { @@ -122,8 +131,9 @@ mod tests { use rstest::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; + use std::time::Duration; - #[derive(Debug, Serialize, Deserialize, PartialEq)] + #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] struct TestMessage { id: Uuid, content: String, @@ -150,31 +160,29 @@ mod tests { rabbitmq: RabbitMQ, test_message: TestMessage, ) { - let queue = "test-queue"; - let routing_key = "test.key"; - - // Subscribe first + let queue = "test_queue"; + let routing_key = "test_routing_key"; + let rabbitmq_clone = rabbitmq.clone(); let test_message_clone = test_message.clone(); + let handle = tokio::spawn(async move { let handler = |msg: TestMessage| async move { assert_eq!(msg, test_message_clone); Ok(()) }; - + rabbitmq_clone.subscribe(queue, handler).await.unwrap(); }); - // Give subscription time to establish tokio::time::sleep(Duration::from_millis(100)).await; - // Publish message rabbitmq.publish("", routing_key, &test_message) .await .unwrap(); - // Wait for handler to process tokio::time::sleep(Duration::from_secs(1)).await; + handle.abort(); } -} +} \ No newline at end of file diff --git a/gb-messaging/src/redis_pubsub.rs b/gb-messaging/src/redis_pubsub.rs index 700d93c..f3b1843 100644 --- a/gb-messaging/src/redis_pubsub.rs +++ b/gb-messaging/src/redis_pubsub.rs @@ -1,80 +1,53 @@ use async_trait::async_trait; + use gb_core::{Result, Error}; -use redis::{ - aio::MultiplexedConnection, - AsyncCommands, Client, -}; +use redis::{Client, AsyncCommands}; use serde::{de::DeserializeOwned, Serialize}; use std::sync::Arc; -use tokio::sync::Mutex; -use tracing::{instrument, error}; +use tracing::instrument; pub struct RedisPubSub { - client: Client, - conn: Arc>, + client: Arc, +} + +impl Clone for RedisPubSub { + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + } + } } impl RedisPubSub { pub async fn new(url: &str) -> Result { let client = Client::open(url) - .map_err(|e| Error::Redis(e))?; + .map_err(|e| Error::redis(e.to_string()))?; - let conn = client.get_multiplexed_async_connection() + // Test connection + client.get_async_connection() .await - .map_err(|e| Error::Redis(e))?; + .map_err(|e| Error::redis(e.to_string()))?; Ok(Self { - client, - conn: Arc::new(Mutex::new(conn)), + client: Arc::new(client), }) } - #[instrument(skip(self, message))] - pub async fn publish(&self, channel: &str, message: &T) -> Result<()> { - let payload = serde_json::to_string(message) - .map_err(|e| Error::Internal(format!("Serialization error: {}", e)))?; + #[instrument(skip(self, payload))] + pub async fn publish(&self, channel: &str, payload: &T) -> Result<()> + where + T: Serialize + std::fmt::Debug, + { + let mut conn = self.client.get_async_connection() + .await + .map_err(|e| Error::redis(e.to_string()))?; + + let payload = serde_json::to_string(payload) + .map_err(|e| Error::redis(e.to_string()))?; - let mut conn = self.conn.lock().await; conn.publish(channel, payload) .await - .map_err(|e| Error::Redis(e))?; - - Ok(()) - } - - #[instrument(skip(self, handler))] - pub async fn subscribe(&self, channels: &[&str], handler: F) -> Result<()> - where - T: DeserializeOwned, - F: Fn(T) -> Fut, - Fut: std::future::Future>, - { - let mut pubsub = self.client.get_async_connection() - .await - .map_err(|e| Error::Redis(e))? - .into_pubsub(); - - for channel in channels { - pubsub.subscribe(*channel) - .await - .map_err(|e| Error::Redis(e))?; - } - - let mut stream = pubsub.on_message(); - - while let Some(msg) = stream.next().await { - let payload: String = msg.get_payload() - .map_err(|e| Error::Redis(e))?; - - match serde_json::from_str::(&payload) { - Ok(value) => { - if let Err(e) = handler(value).await { - error!("Handler error: {}", e); - } - } - Err(e) => error!("Deserialization error: {}", e), - } - } + .map_err(|e| Error::redis(e.to_string()))?; Ok(()) } @@ -86,6 +59,7 @@ mod tests { use rstest::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; + use std::time::Duration; #[derive(Debug, Serialize, Deserialize, PartialEq)] struct TestMessage { @@ -116,7 +90,6 @@ mod tests { ) { let channel = "test-channel"; - // Subscribe first let pubsub_clone = redis_pubsub.clone(); let test_message_clone = test_message.clone(); @@ -129,15 +102,12 @@ mod tests { pubsub_clone.subscribe(&[channel], handler).await.unwrap(); }); - // Give subscription time to establish tokio::time::sleep(Duration::from_millis(100)).await; - // Publish message redis_pubsub.publish(channel, &test_message) .await .unwrap(); - // Wait for handler to process tokio::time::sleep(Duration::from_secs(1)).await; handle.abort(); } diff --git a/gb-messaging/src/websocket.rs b/gb-messaging/src/websocket.rs index 35e259c..2e4994c 100644 --- a/gb-messaging/src/websocket.rs +++ b/gb-messaging/src/websocket.rs @@ -1,80 +1,33 @@ +use futures_util::SinkExt; +use tokio_tungstenite::{connect_async, tungstenite::Message}; use gb_core::{Result, Error}; -use futures::{ - stream::{SplitSink, SplitStream}, - SinkExt, StreamExt, -}; -use serde::{de::DeserializeOwned, Serialize}; -use std::sync::Arc; -use tokio::{ - net::TcpStream, - sync::Mutex, -}; -use tokio_tungstenite::{ - connect_async, - tungstenite::Message, - WebSocketStream, -}; -use tracing::{instrument, error}; pub struct WebSocketClient { - write: Arc, Message>>>, - read: Arc>>>, + stream: tokio_tungstenite::WebSocketStream< + tokio_tungstenite::MaybeTlsStream + >, } impl WebSocketClient { + fn to_gb_error(error: tokio_tungstenite::tungstenite::Error) -> Error { + Error::new( + gb_core::ErrorKind::WebSocket(error.to_string()), + error.to_string() + ) + } + pub async fn connect(url: &str) -> Result { - let (ws_stream, _) = connect_async(url) - .await - .map_err(|e| Error::Internal(format!("WebSocket connection error: {}", e)))?; - - let (write, read) = ws_stream.split(); - + let (ws_stream, _) = connect_async(url).await.map_err(Self::to_gb_error)?; Ok(Self { - write: Arc::new(Mutex::new(write)), - read: Arc::new(Mutex::new(read)), + stream: ws_stream, }) } - #[instrument(skip(self, message))] - pub async fn send(&self, message: &T) -> Result<()> { - let payload = serde_json::to_string(message) - .map_err(|e| Error::Internal(format!("Serialization error: {}", e)))?; - - let mut write = self.write.lock().await; - write.send(Message::Text(payload)) + pub async fn send_message(&mut self, payload: String) -> Result<()> { + self.stream + .send(Message::Text(payload)) .await - .map_err(|e| Error::Internal(format!("WebSocket send error: {}", e)))?; - - Ok(()) - } - - #[instrument(skip(self, handler))] - pub async fn receive(&self, handler: F) -> Result<()> - where - T: DeserializeOwned, - F: Fn(T) -> Fut, - Fut: std::future::Future>, - { - let mut read = self.read.lock().await; - - while let Some(message) = read.next().await { - match message { - Ok(Message::Text(payload)) => { - match serde_json::from_str::(&payload) { - Ok(value) => { - if let Err(e) = handler(value).await { - error!("Handler error: {}", e); - } - } - Err(e) => error!("Deserialization error: {}", e), - } - } - Ok(Message::Close(_)) => break, - Err(e) => error!("WebSocket receive error: {}", e), - _ => continue, - } - } - + .map_err(Self::to_gb_error)?; Ok(()) } } @@ -84,6 +37,7 @@ mod tests { use super::*; use rstest::*; use serde::{Deserialize, Serialize}; + use std::time::Duration; use tokio::net::TcpListener; use uuid::Uuid; @@ -96,15 +50,12 @@ mod tests { async fn create_test_server() -> String { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let addr = listener.local_addr().unwrap(); - + tokio::spawn(async move { while let Ok((stream, _)) = listener.accept().await { - let ws_stream = tokio_tungstenite::accept_async(stream) - .await - .unwrap(); - + let ws_stream = tokio_tungstenite::accept_async(stream).await.unwrap(); let (mut write, mut read) = ws_stream.split(); - + while let Some(Ok(msg)) = read.next().await { if let Message::Text(_) = msg { write.send(msg).await.unwrap(); @@ -126,30 +77,10 @@ mod tests { #[rstest] #[tokio::test] - async fn test_websocket_client(test_message: TestMessage) { + async fn test_websocket(test_message: TestMessage) { let server_url = create_test_server().await; - let client = WebSocketClient::connect(&server_url).await.unwrap(); - let test_message_clone = test_message.clone(); - - // Start receiving messages - let client_clone = client.clone(); - let handle = tokio::spawn(async move { - let handler = |msg: TestMessage| async move { - assert_eq!(msg, test_message_clone); - Ok(()) - }; - - client_clone.receive(handler).await.unwrap(); - }); - - // Give receiver time to start + let mut client = WebSocket::new(&server_url).await.unwrap(); tokio::time::sleep(Duration::from_millis(100)).await; - - // Send test message client.send(&test_message).await.unwrap(); - - // Wait for message to be processed - tokio::time::sleep(Duration::from_secs(1)).await; - handle.abort(); } } diff --git a/gb-monitoring/Cargo.toml b/gb-monitoring/Cargo.toml index 90ca4bc..c395321 100644 --- a/gb-monitoring/Cargo.toml +++ b/gb-monitoring/Cargo.toml @@ -1,17 +1,18 @@ [package] name = "gb-monitoring" -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true +version = "0.1.0" +edition = "2021" [dependencies] +opentelemetry = { version = "0.19", features = ["rt-tokio"] } +opentelemetry-otlp = { version = "0.12", features = ["tonic"] } +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter", "time"] } +thiserror = "1.0" +prometheus = "0.13" gb-core = { path = "../gb-core" } +lazy_static = "1.4" tokio.workspace = true -tracing.workspace = true -tracing-subscriber.workspace = true -prometheus.workspace = true -opentelemetry.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/gb-monitoring/src/lib.rs b/gb-monitoring/src/lib.rs index c892e3e..d87c8ba 100644 --- a/gb-monitoring/src/lib.rs +++ b/gb-monitoring/src/lib.rs @@ -1,11 +1,12 @@ -pub mod metrics; -pub mod logging; -pub mod telemetry; +mod logging; +mod metrics; +mod telemetry; -pub use metrics::Metrics; pub use logging::init_logging; +pub use metrics::Metrics; pub use telemetry::Telemetry; + #[cfg(test)] mod tests { use super::*; diff --git a/gb-monitoring/src/logging.rs b/gb-monitoring/src/logging.rs index b07edfc..06ba3ff 100644 --- a/gb-monitoring/src/logging.rs +++ b/gb-monitoring/src/logging.rs @@ -1,31 +1,28 @@ -use tracing::{subscriber::set_global_default, Subscriber}; +use tracing::subscriber::set_global_default; use tracing_subscriber::{ - fmt::{format::FmtSpan, time::ChronoUtc}, + fmt::{format::FmtSpan, time}, + EnvFilter, layer::SubscriberExt, - EnvFilter, Registry, + Registry, }; -pub fn init_logging() -> Result<(), Box> { +pub fn init_logging(service_name: &str) { let env_filter = EnvFilter::try_from_default_env() .unwrap_or_else(|_| EnvFilter::new("info")); let formatting_layer = tracing_subscriber::fmt::layer() - .with_timer(ChronoUtc::rfc3339()) - .with_thread_ids(true) - .with_thread_names(true) + .with_timer(time::time()) .with_target(true) - .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) + .with_thread_ids(true) + .with_span_events(FmtSpan::CLOSE) .with_file(true) - .with_line_number(true) - .json(); + .with_line_number(true); let subscriber = Registry::default() .with(env_filter) .with(formatting_layer); - set_global_default(subscriber)?; - - Ok(()) + set_global_default(subscriber).expect("Failed to set tracing subscriber"); } #[cfg(test)] @@ -37,7 +34,6 @@ mod tests { fn test_logging_initialization() { assert!(init_logging().is_ok()); - // Test logging info!("Test log message"); } } diff --git a/gb-monitoring/src/metrics.rs b/gb-monitoring/src/metrics.rs index 2be1385..bf5b2bf 100644 --- a/gb-monitoring/src/metrics.rs +++ b/gb-monitoring/src/metrics.rs @@ -1,146 +1,80 @@ -use gb_core::{Result, Error}; -use prometheus::{ - Counter, Gauge, Histogram, HistogramOpts, IntCounter, Registry, - opts, register_counter, register_gauge, register_histogram, -}; -use std::sync::Arc; -use tracing::{instrument, error}; +use prometheus::{IntCounter, IntGauge, Histogram, Registry}; -#[derive(Clone)] pub struct Metrics { - registry: Arc, - active_connections: Gauge, - message_count: IntCounter, - request_duration: Histogram, - active_rooms: Gauge, - media_bandwidth: Gauge, + registry: Registry, + message_counter: IntCounter, + active_connections: IntGauge, + message_processing_time: Histogram, } impl Metrics { - pub fn new() -> Result { + pub fn new() -> Self { let registry = Registry::new(); + + let message_counter = IntCounter::new( + "message_total", + "Total number of messages processed" + ).unwrap(); + + let active_connections = IntGauge::new( + "active_connections", + "Number of active connections" + ).unwrap(); + + let message_processing_time = Histogram::with_opts( + prometheus::HistogramOpts::new( + "message_processing_seconds", + "Time spent processing messages" + ).buckets(vec![0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0]) + ).unwrap(); - let active_connections = register_gauge!( - opts!("gb_active_connections", "Number of active connections"), - registry - ).map_err(|e| Error::Internal(format!("Failed to create metric: {}", e)))?; + registry.register(Box::new(message_counter.clone())).unwrap(); + registry.register(Box::new(active_connections.clone())).unwrap(); + registry.register(Box::new(message_processing_time.clone())).unwrap(); - let message_count = register_counter!( - opts!("gb_message_count", "Total number of messages processed"), - registry - ).map_err(|e| Error::Internal(format!("Failed to create metric: {}", e)))?; - - let request_duration = register_histogram!( - HistogramOpts::new( - "gb_request_duration", - "Request duration in seconds" - ), - registry - ).map_err(|e| Error::Internal(format!("Failed to create metric: {}", e)))?; - - let active_rooms = register_gauge!( - opts!("gb_active_rooms", "Number of active rooms"), - registry - ).map_err(|e| Error::Internal(format!("Failed to create metric: {}", e)))?; - - let media_bandwidth = register_gauge!( - opts!("gb_media_bandwidth", "Current media bandwidth usage in bytes/sec"), - registry - ).map_err(|e| Error::Internal(format!("Failed to create metric: {}", e)))?; - - Ok(Self { - registry: Arc::new(registry), + Self { + registry, + message_counter, active_connections, - message_count, - request_duration, - active_rooms, - media_bandwidth, - }) + message_processing_time, + } } - #[instrument(skip(self))] - pub fn increment_connections(&self) { - self.active_connections.inc(); + pub fn increment_message_count(&self) { + self.message_counter.inc(); } - #[instrument(skip(self))] - pub fn decrement_connections(&self) { - self.active_connections.dec(); + pub fn observe_processing_time(&self, duration_seconds: f64) { + self.message_processing_time.observe(duration_seconds); } - #[instrument(skip(self))] - pub fn increment_messages(&self) { - self.message_count.inc(); + pub fn set_active_connections(&self, count: i64) { + self.active_connections.set(count); } - #[instrument(skip(self))] - pub fn observe_request_duration(&self, duration: f64) { - self.request_duration.observe(duration); - } - - #[instrument(skip(self))] - pub fn set_active_rooms(&self, count: i64) { - self.active_rooms.set(count as f64); - } - - #[instrument(skip(self))] - pub fn set_media_bandwidth(&self, bytes_per_sec: f64) { - self.media_bandwidth.set(bytes_per_sec); - } - - pub fn registry(&self) -> Arc { - self.registry.clone() + pub fn registry(&self) -> &Registry { + &self.registry } } #[cfg(test)] mod tests { use super::*; - use prometheus::core::{Collector, Desc}; - + #[test] - fn test_metrics_creation() { - let metrics = Metrics::new().unwrap(); + fn test_metrics() { + let metrics = Metrics::new(); - // Test increment connections - metrics.increment_connections(); - assert_eq!( - metrics.active_connections.get(), - 1.0 - ); - - // Test decrement connections - metrics.decrement_connections(); - assert_eq!( - metrics.active_connections.get(), - 0.0 - ); - - // Test message count - metrics.increment_messages(); - assert_eq!( - metrics.message_count.get(), - 1 - ); - - // Test request duration - metrics.observe_request_duration(0.5); + metrics.increment_message_count(); + assert_eq!(metrics.message_counter.get(), 1); + + metrics.set_active_connections(10); + assert_eq!(metrics.active_connections.get(), 10); + + metrics.observe_processing_time(0.5); let mut buffer = Vec::new(); - metrics.request_duration.encode(&mut buffer).unwrap(); + let encoder = prometheus::TextEncoder::new(); + encoder.encode(&metrics.registry().gather(), &mut buffer).unwrap(); assert!(!buffer.is_empty()); - - // Test active rooms - metrics.set_active_rooms(10); - assert_eq!( - metrics.active_rooms.get(), - 10.0 - ); - - // Test media bandwidth - metrics.set_media_bandwidth(1024.0); - assert_eq!( - metrics.media_bandwidth.get(), - 1024.0 - ); } } diff --git a/gb-monitoring/src/telemetry.rs b/gb-monitoring/src/telemetry.rs index c6bc068..00db994 100644 --- a/gb-monitoring/src/telemetry.rs +++ b/gb-monitoring/src/telemetry.rs @@ -1,40 +1,48 @@ use opentelemetry::{ - runtime::Tokio, sdk::{trace, Resource}, + runtime::Tokio, KeyValue, }; -use std::time::Duration; -use tracing::error; +use opentelemetry_otlp::{Protocol, WithExportConfig}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum TelemetryError { + #[error("Failed to initialize tracer: {0}")] + Init(String), +} pub struct Telemetry { - tracer: opentelemetry::sdk::trace::Tracer, + tracer: trace::Tracer, } impl Telemetry { - pub fn new(service_name: &str) -> Result> { - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter( - opentelemetry_otlp::new_exporter() - .tonic() - .with_endpoint("http://localhost:4317") - .with_timeout(Duration::from_secs(3)) - ) - .with_trace_config( - trace::config() - .with_resource(Resource::new(vec![KeyValue::new( - "service.name", - service_name.to_string(), - )])) - .with_sampler(trace::Sampler::AlwaysOn) - ) - .install_batch(Tokio)?; - + pub async fn new(service_name: &str) -> Result { + let tracer = Self::init_tracer(service_name) + .await + .map_err(|e| TelemetryError::Init(e.to_string()))?; Ok(Self { tracer }) } - pub fn tracer(&self) -> &opentelemetry::sdk::trace::Tracer { - &self.tracer + async fn init_tracer(service_name: &str) -> Result { + let exporter = opentelemetry_otlp::new_exporter() + .tonic() + .with_protocol(Protocol::Grpc); + + let resource = Resource::new(vec![ + KeyValue::new("service.name", service_name.to_string()), + ]); + + let config = trace::config().with_resource(resource); + + let tracer = opentelemetry_otlp::new_pipeline() + .tracing() + .with_exporter(exporter) + .with_trace_config(config) + .install_batch(Tokio) + .map_err(|e| TelemetryError::Init(e.to_string()))?; + + Ok(tracer) } } @@ -48,9 +56,9 @@ impl Drop for Telemetry { mod tests { use super::*; - #[test] - fn test_telemetry_creation() { - let telemetry = Telemetry::new("test-service"); + #[tokio::test] + async fn test_telemetry_creation() { + let telemetry = Telemetry::new("test-service").await; assert!(telemetry.is_ok()); } -} +} \ No newline at end of file diff --git a/gb-nlp/Cargo.toml b/gb-nlp/Cargo.toml deleted file mode 100644 index 55a312f..0000000 --- a/gb-nlp/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "gb-nlp" -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true - -[dependencies] -gb-core = { path = "../gb-core" } -rust-bert = "0.21" -tokenizers = "0.15" -whatlang = "0.16" -async-trait.workspace = true -tokio.workspace = true -serde.workspace = true -serde_json.workspace = true -thiserror.workspace = true -tracing.workspace = true -tch = "0.13" - -[dev-dependencies] -rstest.workspace = true -tokio-test = "0.4" diff --git a/gb-nlp/src/lang.rs b/gb-nlp/src/lang.rs deleted file mode 100644 index f5faa1a..0000000 --- a/gb-nlp/src/lang.rs +++ /dev/null @@ -1,76 +0,0 @@ -use gb_core::{Result, Error}; -use tracing::instrument; -use whatlang::{Lang, Script, Detector, detect}; - -pub struct LanguageDetector { - detector: Detector, -} - -impl LanguageDetector { - pub fn new() -> Self { - Self { - detector: Detector::new(), - } - } - - #[instrument(skip(self, text))] - pub fn detect_language(&self, text: &str) -> Result { - let info = detect(text) - .ok_or_else(|| Error::Internal("Failed to detect language".to_string()))?; - - Ok(DetectedLanguage { - lang: info.lang(), - script: info.script(), - confidence: info.confidence(), - }) - } - - #[instrument(skip(self, text))] - pub fn is_language(&self, text: &str, lang: Lang) -> bool { - if let Some(info) = detect(text) { - info.lang() == lang - } else { - false - } - } -} - -#[derive(Debug, Clone)] -pub struct DetectedLanguage { - pub lang: Lang, - pub script: Script, - pub confidence: f64, -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - #[fixture] - fn detector() -> LanguageDetector { - LanguageDetector::new() - } - - #[rstest] - fn test_detect_english(detector: LanguageDetector) { - let text = "Hello, this is a test sentence in English."; - let result = detector.detect_language(text).unwrap(); - assert_eq!(result.lang, Lang::Eng); - assert!(result.confidence > 0.9); - } - - #[rstest] - fn test_detect_spanish(detector: LanguageDetector) { - let text = "Hola, esta es una prueba en espaƱol."; - let result = detector.detect_language(text).unwrap(); - assert_eq!(result.lang, Lang::Spa); - assert!(result.confidence > 0.9); - } - - #[rstest] - fn test_is_language(detector: LanguageDetector) { - let text = "Hello world"; - assert!(detector.is_language(text, Lang::Eng)); - } -} diff --git a/gb-nlp/src/lib.rs b/gb-nlp/src/lib.rs deleted file mode 100644 index 316f7bb..0000000 --- a/gb-nlp/src/lib.rs +++ /dev/null @@ -1,42 +0,0 @@ -pub mod lang; -pub mod text; - -pub use lang::{LanguageDetector, DetectedLanguage}; -pub use text::{TextProcessor, Sentiment, Entity, Answer}; - -#[cfg(test)] -mod tests { - use super::*; - use gb_core::Result; - - #[tokio::test] - async fn test_nlp_integration() -> Result<()> { - // Initialize NLP components - let lang_detector = LanguageDetector::new(); - let text_processor = TextProcessor::new().await?; - - // Test language detection - let text = "This is a test sentence in English."; - let lang = lang_detector.detect_language(text)?; - assert_eq!(lang.lang, whatlang::Lang::Eng); - - // Test sentiment analysis - let sentiment = text_processor.analyze_sentiment(text).await?; - assert!(sentiment.score > 0.0); - - // Test entity extraction - let text = "OpenAI released GPT-4 in March 2023."; - let entities = text_processor.extract_entities(text).await?; - - // Test summarization - let text = "Artificial intelligence has made significant advances in recent years. Machine learning models can now perform tasks that were once thought to be exclusive to humans. This has led to both excitement and concern about the future of AI."; - let summary = text_processor.summarize(text).await?; - - // Test question answering - let context = "Rust is a systems programming language focused on safety and performance."; - let question = "What is Rust?"; - let answer = text_processor.answer_question(context, question).await?; - - Ok(()) - } -} diff --git a/gb-nlp/src/text.rs b/gb-nlp/src/text.rs deleted file mode 100644 index 2dcb08d..0000000 --- a/gb-nlp/src/text.rs +++ /dev/null @@ -1,168 +0,0 @@ -use gb_core::{Result, Error}; -use rust_bert::pipelines::{ - sentiment::SentimentModel, - ner::NERModel, - summarization::SummarizationModel, - question_answering::{QaModel, QuestionAnsweringModel}, -}; -use std::sync::Arc; -use tokio::sync::Mutex; -use tracing::{instrument, error}; - -pub struct TextProcessor { - sentiment_model: Arc>, - ner_model: Arc>, - summarization_model: Arc>, - qa_model: Arc>, -} - -impl TextProcessor { - #[instrument] - pub async fn new() -> Result { - let sentiment_model = SentimentModel::new(Default::default()) - .map_err(|e| Error::Internal(format!("Failed to load sentiment model: {}", e)))?; - - let ner_model = NERModel::new(Default::default()) - .map_err(|e| Error::Internal(format!("Failed to load NER model: {}", e)))?; - - let summarization_model = SummarizationModel::new(Default::default()) - .map_err(|e| Error::Internal(format!("Failed to load summarization model: {}", e)))?; - - let qa_model = QuestionAnsweringModel::new(Default::default()) - .map_err(|e| Error::Internal(format!("Failed to load QA model: {}", e)))?; - - Ok(Self { - sentiment_model: Arc::new(Mutex::new(sentiment_model)), - ner_model: Arc::new(Mutex::new(ner_model)), - summarization_model: Arc::new(Mutex::new(summarization_model)), - qa_model: Arc::new(Mutex::new(qa_model)), - }) - } - - #[instrument(skip(self, text))] - pub async fn analyze_sentiment(&self, text: &str) -> Result { - let model = self.sentiment_model.lock().await; - let output = model.predict(&[text]) - .map_err(|e| Error::Internal(format!("Sentiment analysis failed: {}", e)))?; - - Ok(Sentiment { - score: output[0].score, - label: output[0].label.clone(), - }) - } - - #[instrument(skip(self, text))] - pub async fn extract_entities(&self, text: &str) -> Result> { - let model = self.ner_model.lock().await; - let output = model.predict(&[text]) - .map_err(|e| Error::Internal(format!("Entity extraction failed: {}", e)))?; - - Ok(output[0].iter().map(|entity| Entity { - text: entity.word.clone(), - label: entity.entity.clone(), - score: entity.score, - }).collect()) - } - - #[instrument(skip(self, text))] - pub async fn summarize(&self, text: &str) -> Result { - let model = self.summarization_model.lock().await; - let output = model.summarize(&[text]) - .map_err(|e| Error::Internal(format!("Summarization failed: {}", e)))?; - - Ok(output[0].clone()) - } - - #[instrument(skip(self, context, question))] - pub async fn answer_question(&self, context: &str, question: &str) -> Result { - let model = self.qa_model.lock().await; - let output = model.predict(&[QaModel { - context, - question, - }]) - .map_err(|e| Error::Internal(format!("Question answering failed: {}", e)))?; - - Ok(Answer { - text: output[0].answer.clone(), - score: output[0].score, - start: output[0].start, - end: output[0].end, - }) - } -} - -#[derive(Debug, Clone)] -pub struct Sentiment { - pub score: f64, - pub label: String, -} - -#[derive(Debug, Clone)] -pub struct Entity { - pub text: String, - pub label: String, - pub score: f64, -} - -#[derive(Debug, Clone)] -pub struct Answer { - pub text: String, - pub score: f64, - pub start: usize, - pub end: usize, -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - #[fixture] - async fn processor() -> TextProcessor { - TextProcessor::new().await.unwrap() - } - - #[rstest] - #[tokio::test] - async fn test_sentiment_analysis(processor: TextProcessor) -> Result<()> { - let text = "I love this product! It's amazing!"; - let sentiment = processor.analyze_sentiment(text).await?; - assert!(sentiment.score > 0.5); - assert_eq!(sentiment.label, "positive"); - Ok(()) - } - - #[rstest] - #[tokio::test] - async fn test_entity_extraction(processor: TextProcessor) -> Result<()> { - let text = "John Smith works at Microsoft in Seattle."; - let entities = processor.extract_entities(text).await?; - - assert!(entities.iter().any(|e| e.text == "John Smith" && e.label == "PERSON")); - assert!(entities.iter().any(|e| e.text == "Microsoft" && e.label == "ORG")); - assert!(entities.iter().any(|e| e.text == "Seattle" && e.label == "LOC")); - - Ok(()) - } - - #[rstest] - #[tokio::test] - async fn test_summarization(processor: TextProcessor) -> Result<()> { - let text = "The quick brown fox jumps over the lazy dog. This is a classic pangram that contains every letter of the English alphabet. It has been used for typing practice and font displays for many years."; - let summary = processor.summarize(text).await?; - assert!(summary.len() < text.len()); - Ok(()) - } - - #[rstest] - #[tokio::test] - async fn test_question_answering(processor: TextProcessor) -> Result<()> { - let context = "The capital of France is Paris. It is known as the City of Light."; - let question = "What is the capital of France?"; - - let answer = processor.answer_question(context, question).await?; - assert_eq!(answer.text, "Paris"); - assert!(answer.score > 0.8); - Ok(()) - } -} diff --git a/gb-testing/Cargo.toml b/gb-testing/Cargo.toml index ecbe154..fe9ce2f 100644 --- a/gb-testing/Cargo.toml +++ b/gb-testing/Cargo.toml @@ -34,7 +34,7 @@ sqlx.workspace = true redis.workspace = true # Metrics & Monitoring -prometheus = { version = "0.13", features = ["process"] } +prometheus = { version = "0.13.0", features = ["process"] } tracing.workspace = true opentelemetry.workspace = true diff --git a/install.sh b/install.sh index 9cf8b2c..b36069a 100755 --- a/install.sh +++ b/install.sh @@ -6,10 +6,6 @@ set -e sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common gnupg -# Update package lists -echo "Updating package lists..." - - echo "Repository fixes completed!" # Install system dependencies @@ -89,9 +85,9 @@ sudo systemctl start postgresql sudo systemctl enable postgresql # Create database and user (with error handling) -sudo -u postgres psql -c "CREATE DATABASE generalbots;" 2>/dev/null || echo "Database might already exist" -sudo -u postgres psql -c "CREATE USER gbuser WITH PASSWORD 'gbpassword';" 2>/dev/null || echo "User might already exist" -sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE generalbots TO gbuser;" 2>/dev/null || echo "Privileges might already be granted" + sudo -u postgres psql -c "CREATE DATABASE generalbots;" 2>/dev/null || echo "Database might already exist" + sudo -u postgres psql -c "CREATE USER gbuser WITH PASSWORD 'gbpassword';" 2>/dev/null || echo "User might already exist" + sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE generalbots TO gbuser;" 2>/dev/null || echo "Privileges might already be granted" # Start Redis echo "Starting Redis service..." @@ -110,4 +106,7 @@ echo -e "\nService Status:" echo "PostgreSQL status:" sudo systemctl status postgresql --no-pager echo -e "\nRedis status:" -sudo systemctl status redis-server --no-pager \ No newline at end of file +sudo systemctl status redis-server --no-pager + +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8771ADB0816950D8 && sudo apt-get update && sudo apt-get install -y libglib2.0-dev build-essential pkg-config +sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio && export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig:$PKG_CONFIG_PATH && echo 'export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc && source ~/.bashrc