From 69d989da8138550b393f80df1150f5e05174cf14 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Tue, 25 Jan 2022 02:23:51 +0530 Subject: [PATCH 01/16] Basic Framework Structure --- .gitignore | 1 + Cargo.lock | 7 ++ Cargo.toml | 8 ++ src/bin/entrypoint.rs | 1 + src/lib.rs | 1 + src/registry/action_catalog.rs | 68 ++++++++++++++++ src/registry/action_endpoint.rs | 48 ++++++++++++ src/registry/endpoint_list.rs | 132 ++++++++++++++++++++++++++++++++ src/registry/event_endpoint.rs | 27 +++++++ src/registry/mod.rs | 86 +++++++++++++++++++++ 10 files changed, 379 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/bin/entrypoint.rs create mode 100644 src/lib.rs create mode 100644 src/registry/action_catalog.rs create mode 100644 src/registry/action_endpoint.rs create mode 100644 src/registry/endpoint_list.rs create mode 100644 src/registry/event_endpoint.rs create mode 100644 src/registry/mod.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a580b33 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "molecular-rust" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4784b09 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "molecular-rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/bin/entrypoint.rs b/src/bin/entrypoint.rs new file mode 100644 index 0000000..f328e4d --- /dev/null +++ b/src/bin/entrypoint.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..97ac64f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod registry; \ No newline at end of file diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs new file mode 100644 index 0000000..139a823 --- /dev/null +++ b/src/registry/action_catalog.rs @@ -0,0 +1,68 @@ +use std::{collections::HashMap}; + +use super::*; + +pub struct ActionCatalog { + registry: Arc, + broker: Arc, + strategy: Strategy, + logger: Arc, + actions: HashMap, +} + +impl ActionCatalog { + fn new(registry: Arc, broker: Arc, strategy: Strategy) -> Self { + let logger = registry.logger(); + let logger = Arc::clone(logger); + + Self { + registry, + strategy, + broker, + logger, + actions: HashMap::new(), + } + } + fn add(&mut self, node: Arc, service: Arc, action: Action) { + let list = self.actions.get_mut(&action.name); + match list { + Some(list) => list.add(node, service, action), + None => { + let name = action.name.clone(); + let mut list = EndpointList::new( + Arc::clone(&self.registry), + Arc::clone(&self.broker), + name, + None, + ); + let name = action.name.clone(); + list.add(node, service, action); + self.actions.insert(name, list); + } + } + } + fn get(&self, action_name: &String) -> Option<&EndpointList> { + self.actions.get(action_name) + } + fn is_available(&self, action_name: &String) -> bool { + match self.actions.get(action_name) { + Some(el) => el.has_available(), + None => false, + } + } + fn remove_by_service(&mut self, service: &ServiceItem) { + self.actions.iter_mut().for_each(|item| { + let (key, el) = item; + el.remove_by_service(service); + }); + } + fn remove(&mut self, action_name: &String, node_id: &String) { + let list = self.actions.get_mut(action_name); + if let Some(el) = list { + el.remove_by_node_id(node_id); + } + } + fn list(&self) { + todo!() + } +} diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs new file mode 100644 index 0000000..5effefc --- /dev/null +++ b/src/registry/action_endpoint.rs @@ -0,0 +1,48 @@ +use super::*; + +#[derive(Clone)] +pub struct ActionEndpoint { + endpoint: Endpoint, + action: Action, + name: String, +} +impl ActionEndpoint { + pub fn new( + registry: Arc, + broker: Arc, + node: Arc, + service: Arc, + action: Action, + ) -> Self { + let endpoint = Endpoint::new(registry, broker, node, service); + let name = format!("{}:{}", endpoint.id, action.name); + ActionEndpoint { + action, + endpoint, + name, + } + } + + pub fn is_available(&self) -> bool { + self.endpoint.state + } + pub fn is_local(&self) -> bool { + self.endpoint.local + } + pub fn update(&mut self, action: Action) { + self.action = action + } + pub fn node(&self) -> &Node { + &self.endpoint.node + } + + pub fn service(&self) -> &ServiceItem { + &self.endpoint.service + } + pub fn name(&self) -> &String { + &self.name + } + pub fn id(&self) -> &String { + &self.endpoint.id + } +} diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs new file mode 100644 index 0000000..f6e1176 --- /dev/null +++ b/src/registry/endpoint_list.rs @@ -0,0 +1,132 @@ +use std::sync::Arc; + +use super::*; +use action_endpoint::ActionEndpoint; + +pub struct EndpointList { + registry: Arc, + broker: Arc, + name: String, + group: Option, + internal: bool, + endpoints: Vec, + local_endpoints: Vec, +} + +impl EndpointList { + pub fn new( + registry: Arc, + broker: Arc, + name: String, + group: Option, + ) -> Self { + let internal = name.starts_with("$"); + let endpoints = Vec::new(); + let local_endpoints = Vec::new(); + + Self { + registry, + broker, + name, + group, + endpoints, + local_endpoints, + internal, + } + } + + pub fn add(&mut self, node: Arc, service: Arc, data: Action) { + let entry = self + .endpoints + .iter_mut() + .find(|x| x.node() == &*node && x.service().name == service.name); + + match entry { + Some(found) => { + found.update(data); + return; + } + None => {} + } + let ep = ActionEndpoint::new( + Arc::clone(&self.registry), + Arc::clone(&self.broker), + Arc::clone(&node), + Arc::clone(&service), + data, + ); + + self.endpoints.push(ep.clone()); + if ep.is_local() { + self.local_endpoints.push(ep) + } + } + fn get_first(&self) -> Option<&ActionEndpoint> { + self.endpoints.get(0) + } + + fn select(&self) -> &ActionEndpoint { + todo!() + } + + fn next(&self) -> &ActionEndpoint { + todo!() + } + fn next_local(&self) -> &ActionEndpoint { + todo!() + } + + pub fn has_available(&self) -> bool { + for ep in self.endpoints.iter() { + if ep.is_available() { + return true; + } + } + return false; + } + fn has_local(&self) -> bool { + self.local_endpoints.len() > 0 + } + + fn update_local_endpoints(&mut self) { + let mut local: Vec = Vec::new(); + for ep in &self.endpoints { + if ep.is_local() { + let e = ep.clone(); + local.push(e); + } + } + std::mem::swap(&mut local, &mut self.local_endpoints); + drop(local); + } + + fn count(&self) -> usize { + self.endpoints.len() + } + fn get_endpoint_by_node_id(&self, node_id: &String) -> Option<&ActionEndpoint> { + self.endpoints + .iter() + .find(|e| e.id() == node_id && e.is_available()) + } + fn has_node_id(&self, node_id: &String) -> bool { + match self.endpoints.iter().find(|e| e.id() == node_id) { + Some(_) => true, + None => false, + } + } + pub fn remove_by_service(&mut self, service: &ServiceItem) { + self.endpoints.retain(|ep| { + let delete = ep.service() == service; + !delete + }); + self.update_local_endpoints(); + } + + pub fn remove_by_node_id(&mut self, node_id: &String) { + self.endpoints.retain(|ep| { + let delete = ep.id() == node_id; + !delete + }); + self.update_local_endpoints(); + } +} diff --git a/src/registry/event_endpoint.rs b/src/registry/event_endpoint.rs new file mode 100644 index 0000000..0618e0a --- /dev/null +++ b/src/registry/event_endpoint.rs @@ -0,0 +1,27 @@ +// use super::{Broker, Endpoint, Node, Registry, ServiceItem, Event}; + +// pub struct EventEndpoint { +// endpoint: Endpoint, +// event: Event, +// } +// impl EventEndpoint { +// fn new( +// registry: , +// broker: Broker, +// node: Node, +// service: ServiceItem, +// event: Event, +// ) -> Self { +// let endpoint = Endpoint::new(registry, broker, node, service); + +// Self { event, endpoint } +// } + +// fn is_available(&self) -> bool { +// self.endpoint.state +// } + +// fn update(&mut self, event: Event) { +// self.event = event +// } +// } diff --git a/src/registry/mod.rs b/src/registry/mod.rs new file mode 100644 index 0000000..ac9f226 --- /dev/null +++ b/src/registry/mod.rs @@ -0,0 +1,86 @@ +pub mod action_catalog; +pub mod action_endpoint; +pub mod endpoint_list; +pub mod event_endpoint; +pub use std::sync::Arc; + +pub use action_endpoint::ActionEndpoint; +pub use endpoint_list::EndpointList; +// pub use event_endpoint::EventEndpoint; + +pub struct Logger {} +pub struct Broker { + node_id: String, +} +pub struct Registry { + logger: Arc, +} +impl Registry { + pub fn logger(&self) -> &Arc { + &self.logger + } +} +#[derive(PartialEq, Eq)] +pub struct Node { + id: String, +} +#[derive(PartialEq, Eq)] +pub struct ServiceItem { + name: String, +} + +trait FnType {} + +#[derive(Clone)] +pub struct Action { + name: String, +} +impl FnType for Action {} +struct Event {} +impl FnType for Event {} +pub struct Strategy {} + +trait EndpointTrait { + fn node(&self) -> Node; + fn service(&self) -> ServiceItem; + fn update(&mut self, data: F) + where + F: FnType; +} + +#[derive(Clone)] +struct Endpoint { + registry: Arc, + broker: Arc, + node: Arc, + service: Arc, + state: bool, + id: String, + local: bool, +} + +impl Endpoint { + fn new( + registry: Arc, + broker: Arc, + node: Arc, + service: Arc, + ) -> Self { + let local = node.id == broker.node_id; + let id = node.id.clone(); + Self { + registry, + broker, + node, + service, + state: true, + id: id, + local, + } + } +} + +enum EndpointType { + Action, + Event, +} From 77dd2d6ad66171f11581f0c34f5b3a38d596dfd6 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Wed, 26 Jan 2022 02:44:50 +0530 Subject: [PATCH 02/16] node and node catalog implemented --- Cargo.lock | 86 +++++++++++++++++++++++ Cargo.toml | 1 + src/registry/action_catalog.rs | 10 +-- src/registry/action_endpoint.rs | 7 +- src/registry/endpoint_list.rs | 6 +- src/registry/mod.rs | 16 +++-- src/registry/node.rs | 117 ++++++++++++++++++++++++++++++++ src/registry/node_catalog.rs | 108 +++++++++++++++++++++++++++++ 8 files changed, 331 insertions(+), 20 deletions(-) create mode 100644 src/registry/node.rs create mode 100644 src/registry/node_catalog.rs diff --git a/Cargo.lock b/Cargo.lock index a580b33..53e1b5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,92 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "libc" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" + [[package]] name = "molecular-rust" version = "0.1.0" +dependencies = [ + "chrono", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[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-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 4784b09..42b3536 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = "0.4.19" \ No newline at end of file diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index 139a823..b28802a 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -1,8 +1,8 @@ -use std::{collections::HashMap}; +use std::collections::HashMap; use super::*; -pub struct ActionCatalog { +struct ActionCatalog { registry: Arc, broker: Arc, strategy: Strategy, @@ -41,10 +41,10 @@ impl ActionCatalog { } } } - fn get(&self, action_name: &String) -> Option<&EndpointList> { + fn get(&self, action_name: &str) -> Option<&EndpointList> { self.actions.get(action_name) } - fn is_available(&self, action_name: &String) -> bool { + fn is_available(&self, action_name: &str) -> bool { match self.actions.get(action_name) { Some(el) => el.has_available(), None => false, @@ -56,7 +56,7 @@ impl ActionCatalog { el.remove_by_service(service); }); } - fn remove(&mut self, action_name: &String, node_id: &String) { + fn remove(&mut self, action_name: &str, node_id: &str) { let list = self.actions.get_mut(action_name); if let Some(el) = list { el.remove_by_node_id(node_id); diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index 5effefc..99faf0e 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -4,7 +4,7 @@ use super::*; pub struct ActionEndpoint { endpoint: Endpoint, action: Action, - name: String, + pub name: String, } impl ActionEndpoint { pub fn new( @@ -39,10 +39,7 @@ impl ActionEndpoint { pub fn service(&self) -> &ServiceItem { &self.endpoint.service } - pub fn name(&self) -> &String { - &self.name - } - pub fn id(&self) -> &String { + pub fn id(&self) -> &str { &self.endpoint.id } } diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index f6e1176..69dbab6 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -103,12 +103,12 @@ impl EndpointList { fn count(&self) -> usize { self.endpoints.len() } - fn get_endpoint_by_node_id(&self, node_id: &String) -> Option<&ActionEndpoint> { + fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&ActionEndpoint> { self.endpoints .iter() .find(|e| e.id() == node_id && e.is_available()) } - fn has_node_id(&self, node_id: &String) -> bool { + fn has_node_id(&self, node_id: &str) -> bool { match self.endpoints.iter().find(|e| e.id() == node_id) { Some(_) => true, None => false, @@ -122,7 +122,7 @@ impl EndpointList { self.update_local_endpoints(); } - pub fn remove_by_node_id(&mut self, node_id: &String) { + pub fn remove_by_node_id(&mut self, node_id: &str) { self.endpoints.retain(|ep| { let delete = ep.id() == node_id; !delete diff --git a/src/registry/mod.rs b/src/registry/mod.rs index ac9f226..b83128f 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -2,15 +2,20 @@ pub mod action_catalog; pub mod action_endpoint; pub mod endpoint_list; pub mod event_endpoint; +pub mod node; +pub mod node_catalog; pub use std::sync::Arc; pub use action_endpoint::ActionEndpoint; pub use endpoint_list::EndpointList; +pub use node::{Client, Node}; // pub use event_endpoint::EventEndpoint; pub struct Logger {} pub struct Broker { node_id: String, + instance_id: String, + moleculer_version: String, } pub struct Registry { logger: Arc, @@ -20,11 +25,8 @@ impl Registry { &self.logger } } -#[derive(PartialEq, Eq)] -pub struct Node { - id: String, -} -#[derive(PartialEq, Eq)] + +#[derive(PartialEq, Eq, Clone)] pub struct ServiceItem { name: String, } @@ -66,8 +68,8 @@ impl Endpoint { node: Arc, service: Arc, ) -> Self { - let local = node.id == broker.node_id; - let id = node.id.clone(); + let local = node.id() == broker.node_id; + let id = node.id().to_string(); Self { registry, broker, diff --git a/src/registry/node.rs b/src/registry/node.rs new file mode 100644 index 0000000..cba01c5 --- /dev/null +++ b/src/registry/node.rs @@ -0,0 +1,117 @@ +use std::net::IpAddr; + +use chrono::Duration; + +use super::ServiceItem; + +#[derive(PartialEq, Eq, Clone)] +pub struct Node { + id: String, + instance_id: Option, + available: bool, + local: bool, + last_heartbeat_time: Duration, + /* feields that need to be added later. + config + + metadata + */ + client: Option, + ip_list: Vec, + port: Option, + hostname: Option, + udp_address: Option, + /* + raw_info + cpu + cpuseq + */ + services: Vec, + pub seq: usize, + offline_since: Option, +} + +impl Node { + pub fn new(id: String) -> Self { + Self { + id: id, + instance_id: None, + available: true, + local: false, + client: None, + /* + change this later with actual process uptime. + */ + last_heartbeat_time: Duration::seconds(1), + ip_list: Vec::new(), + port: None, + hostname: None, + udp_address: None, + services: Vec::new(), + seq: 0, + offline_since: None, + } + } + pub fn update(&mut self) { + todo!() + } + pub fn update_local_info(&mut self) { + todo!() + } + pub fn hearbeat(&mut self) { + if !self.available { + self.available = true; + self.offline_since = None; + } + todo!() + } + pub fn disconnect(&mut self) { + if self.available { + self.seq = self.seq.saturating_add(1); + /* update this with process uptime + self.offline_since = + */ + } + self.available = false; + } + pub fn id(&self) -> &str { + &self.id + } + pub fn available(&self) -> bool { + self.available + } + pub fn services_len(&self) -> usize { + self.services.len() + } + pub fn set_local(mut self, value: bool) -> Self { + self.local = value; + self + } + pub fn set_ip_list(mut self, ip_list: Vec) -> Self { + self.ip_list = ip_list; + self + } + pub fn set_instance_id(mut self, instance_id: String) -> Self { + self.instance_id = Some(instance_id); + self + } + pub fn set_hostname(mut self, hostname: String) -> Self { + self.hostname = Some(hostname); + self + } + pub fn set_client(mut self, client: Client) -> Self { + self.client = Some(client); + self + } + pub fn set_seq(mut self, seq: usize) -> Self { + self.seq = seq; + self + } +} +#[derive(PartialEq, Eq, Clone)] + +pub struct Client { + pub(crate) client_type: String, + pub(crate) version: String, + pub(crate) lang_version: String, +} diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs new file mode 100644 index 0000000..fa3700e --- /dev/null +++ b/src/registry/node_catalog.rs @@ -0,0 +1,108 @@ +use std::{collections::HashMap, net::IpAddr, sync::Arc}; + +use super::{node, Broker, Client, Logger, Node, Registry}; + +pub struct NodeCatalog { + registry: Arc, + broker: Arc, + logger: Arc, + nodes: HashMap, + local_node: Option, +} +impl NodeCatalog { + pub fn new(registry: Arc, broker: Arc) -> Self { + let logger = registry.logger(); + let logger = Arc::clone(logger); + Self { + broker, + logger, + registry, + nodes: HashMap::new(), + local_node: None, + } + } + ///Create a local node + fn create_local_node(&mut self) -> Node { + let client = Client { + client_type: "rust".to_string(), + lang_version: "1.56.1".to_string(), + version: self.broker.moleculer_version.clone(), + }; + let node = Node::new(self.broker.node_id.clone()) + .set_local(true) + .set_ip_list(get_ip_list()) + .set_instance_id(self.broker.instance_id.clone()) + .set_hostname(get_hostname()) + .set_seq(1) + .set_client(client); + + self.nodes.insert(node.id().to_string(), node.clone()); + self.local_node = Some(node.clone()); + return node; + todo!() + /* + node.metadata = self.broker.metadata.clone() + */ + } + pub fn add(&mut self, id: &str, node: Node) { + self.nodes.insert(id.to_string(), node); + } + pub fn had_node(&self, id: &str) -> bool { + match self.nodes.get(id) { + Some(_) => true, + None => false, + } + } + pub fn get_node(&self, id: &str) -> Option<&Node> { + self.nodes.get(id) + } + pub fn get_node_mut(&mut self, id: &str) -> Option<&mut Node> { + self.nodes.get_mut(id) + } + pub fn delete(&mut self, id: &str) -> Option { + self.nodes.remove(id) + } + pub fn count(&self) -> usize { + self.nodes.len() + } + pub fn online_count(&self) -> usize { + let mut count: usize = 0; + self.nodes.iter().for_each(|node_item| { + let (_, node) = node_item; + if node.available() { + count = count.saturating_add(1); + } + }); + count + } + pub fn process_node_info(&self) { + todo!() + } + pub fn disconnect(&mut self) { + todo!() + } + + pub fn list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { + let mut nodes = Vec::new(); + self.nodes.iter().for_each(|node_item| { + let (_, node) = node_item; + if only_available && !node.available() { + return; + } + if with_services && node.services_len() <= 0 { + return; + } + nodes.push(node); + }); + nodes + } + pub fn nodes_vec(&self) -> Vec<&Node> { + self.nodes.values().collect() + } +} +fn get_ip_list() -> Vec { + todo!() +} +fn get_hostname() -> String { + todo!() +} From 3b30a7cad8077f13b267fda4d5d35fb40b3a6355 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Wed, 26 Jan 2022 05:17:03 +0530 Subject: [PATCH 03/16] service item and service item catalog --- src/registry/action_catalog.rs | 2 +- src/registry/action_endpoint.rs | 5 ++- src/registry/endpoint_list.rs | 7 ++- src/registry/mod.rs | 33 ++++++++++---- src/registry/node.rs | 11 ++--- src/registry/node_catalog.rs | 45 +++++++++++++------ src/registry/service_catalog.rs | 79 +++++++++++++++++++++++++++++++++ src/registry/service_item.rs | 54 ++++++++++++++++++++++ 8 files changed, 199 insertions(+), 37 deletions(-) create mode 100644 src/registry/service_catalog.rs create mode 100644 src/registry/service_item.rs diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index b28802a..d4b17ab 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -7,7 +7,7 @@ struct ActionCatalog { broker: Arc, strategy: Strategy, logger: Arc, - actions: HashMap, + actions: ActionsMap, } impl ActionCatalog { diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index 99faf0e..adc9195 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Clone)] +#[derive(PartialEq, Eq, Clone)] pub struct ActionEndpoint { endpoint: Endpoint, action: Action, @@ -42,4 +42,7 @@ impl ActionEndpoint { pub fn id(&self) -> &str { &self.endpoint.id } + pub fn service_name(&self) -> &str { + &self.endpoint.service.name + } } diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index 69dbab6..cf5c743 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -1,12 +1,11 @@ use std::sync::Arc; use super::*; -use action_endpoint::ActionEndpoint; - +#[derive(PartialEq, Eq, Clone)] pub struct EndpointList { registry: Arc, broker: Arc, - name: String, + pub name: String, group: Option, internal: bool, endpoints: Vec, @@ -39,7 +38,7 @@ impl EndpointList { let entry = self .endpoints .iter_mut() - .find(|x| x.node() == &*node && x.service().name == service.name); + .find(|x| x.node() == &*node && x.service_name() == service.name); match entry { Some(found) => { diff --git a/src/registry/mod.rs b/src/registry/mod.rs index b83128f..f10bd53 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -4,19 +4,29 @@ pub mod endpoint_list; pub mod event_endpoint; pub mod node; pub mod node_catalog; +pub mod service_catalog; +pub mod service_item; +use std::collections::HashMap; pub use std::sync::Arc; pub use action_endpoint::ActionEndpoint; pub use endpoint_list::EndpointList; pub use node::{Client, Node}; +use service_item::ServiceItem; // pub use event_endpoint::EventEndpoint; +type ActionsMap = HashMap; + +#[derive(PartialEq, Eq)] pub struct Logger {} +#[derive(PartialEq, Eq)] pub struct Broker { node_id: String, instance_id: String, moleculer_version: String, } + +#[derive(PartialEq, Eq)] pub struct Registry { logger: Arc, } @@ -26,14 +36,9 @@ impl Registry { } } -#[derive(PartialEq, Eq, Clone)] -pub struct ServiceItem { - name: String, -} - trait FnType {} -#[derive(Clone)] +#[derive(PartialEq, Eq, Clone)] pub struct Action { name: String, } @@ -50,7 +55,7 @@ trait EndpointTrait { F: FnType; } -#[derive(Clone)] +#[derive(PartialEq, Eq, Clone)] struct Endpoint { registry: Arc, broker: Arc, @@ -68,8 +73,8 @@ impl Endpoint { node: Arc, service: Arc, ) -> Self { - let local = node.id() == broker.node_id; - let id = node.id().to_string(); + let local = node.id == broker.node_id; + let id = node.id.to_string(); Self { registry, broker, @@ -86,3 +91,13 @@ enum EndpointType { Action, Event, } + +pub struct Service { + name: String, + full_name: String, + version: String, + /* + settings , + metadata + */ +} diff --git a/src/registry/node.rs b/src/registry/node.rs index cba01c5..e7868c9 100644 --- a/src/registry/node.rs +++ b/src/registry/node.rs @@ -6,9 +6,9 @@ use super::ServiceItem; #[derive(PartialEq, Eq, Clone)] pub struct Node { - id: String, + pub id: String, instance_id: Option, - available: bool, + pub available: bool, local: bool, last_heartbeat_time: Duration, /* feields that need to be added later. @@ -74,12 +74,7 @@ impl Node { } self.available = false; } - pub fn id(&self) -> &str { - &self.id - } - pub fn available(&self) -> bool { - self.available - } + pub fn services_len(&self) -> usize { self.services.len() } diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index fa3700e..962ba18 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -36,7 +36,7 @@ impl NodeCatalog { .set_seq(1) .set_client(client); - self.nodes.insert(node.id().to_string(), node.clone()); + self.nodes.insert(node.id.to_string(), node.clone()); self.local_node = Some(node.clone()); return node; todo!() @@ -69,7 +69,7 @@ impl NodeCatalog { let mut count: usize = 0; self.nodes.iter().for_each(|node_item| { let (_, node) = node_item; - if node.available() { + if node.available { count = count.saturating_add(1); } }); @@ -83,22 +83,39 @@ impl NodeCatalog { } pub fn list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { - let mut nodes = Vec::new(); - self.nodes.iter().for_each(|node_item| { - let (_, node) = node_item; - if only_available && !node.available() { - return; - } - if with_services && node.services_len() <= 0 { - return; - } - nodes.push(node); - }); - nodes + self.nodes + .values() + .filter(|node| { + if only_available && !node.available { + return false; + } + if with_services && node.services_len() <= 0 { + return false; + } + return true; + }) + .collect() + } + pub fn list_mut(&mut self, only_available: bool, with_services: bool) -> Vec<&mut Node> { + self.nodes + .values_mut() + .filter(|node| { + if only_available && !node.available { + return false; + } + if with_services && node.services_len() <= 0 { + return false; + } + return true; + }) + .collect() } pub fn nodes_vec(&self) -> Vec<&Node> { self.nodes.values().collect() } + pub fn nodes_vec_mut(&mut self) -> Vec<&mut Node> { + self.nodes.values_mut().collect() + } } fn get_ip_list() -> Vec { todo!() diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs new file mode 100644 index 0000000..8847db3 --- /dev/null +++ b/src/registry/service_catalog.rs @@ -0,0 +1,79 @@ +use super::*; + +pub struct ServiceCatalog { + registry: Arc, + broker: Arc, + logger: Arc, + services: Vec, +} + +impl ServiceCatalog { + pub fn new(registry: Arc, broker: Arc) -> Self { + let logger = ®istry.logger; + let logger = Arc::clone(&logger); + Self { + broker, + registry, + logger, + services: Vec::new(), + } + } + ///Add a new service + pub fn add(&mut self, node: Arc, service: Arc, local: bool) { + let service_item = ServiceItem::new(node, service, local); + self.services.push(service_item); + } + ///Check the service exsists + pub fn has(&self, full_name: &str, node_id: Option<&str>) -> bool { + let svc = self + .services + .iter() + .find(|svc| svc.equals(full_name, node_id)); + match svc { + Some(_) => true, + None => false, + } + } + pub fn get(&self, full_name: &str, node_id: Option<&str>) -> Option<&ServiceItem> { + self.services + .iter() + .find(|svc| svc.equals(full_name, node_id)) + } + pub fn get_mut(&mut self, full_name: &str, node_id: Option<&str>) -> Option<&mut ServiceItem> { + self.services + .iter_mut() + .find(|svc| svc.equals(full_name, node_id)) + } + pub fn list(&self) { + todo!() + } + pub fn get_local_node_service(&self) { + todo!() + } + //remove all endpoints by node_id. + pub fn remove_by_node_id(&mut self, node_id: &str) { + let services: Vec<&ServiceItem> = self + .services + .iter() + .filter(|svc| { + if svc.node.id == node_id { + todo!("remove actions and events in registry"); + return false; + } + true + }) + .collect(); + todo!("updat the service") + } + + pub fn remove(&mut self, full_name: &str, node_id: Option<&str>) { + self.services.retain(|svc| { + if svc.equals(full_name, node_id) { + todo!("remove actions and events in registry"); + + return false; + } + return true; + }) + } +} diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs new file mode 100644 index 0000000..b50c9a4 --- /dev/null +++ b/src/registry/service_item.rs @@ -0,0 +1,54 @@ +use super::*; + +#[derive(PartialEq, Eq, Clone)] +pub struct ServiceItem { + pub name: String, + pub node: Arc, + local: bool, + full_name: String, + version: String, + actions: ActionsMap, + /* + eventsmap + metadata + settings + */ +} +impl ServiceItem { + pub fn new(node: Arc, service: Arc, local: bool) -> Self { + Self { + node, + local, + actions: HashMap::new(), + full_name: service.full_name.to_string(), + version: service.version.to_string(), + name: service.name.to_string(), + } + } + pub fn equals(&self, full_name: &str, node_id: Option<&str>) -> bool { + match node_id { + Some(id) => self.node.id == id && self.full_name == full_name, + None => self.full_name == full_name, + } + } + + ///Update service properties + pub fn update(&mut self, service: &Service) { + self.full_name = service.full_name.to_string(); + self.version = service.version.to_string(); + /* + settings + metadata + */ + todo!() + } + ///Add action to service + pub fn add_action(&mut self, action: EndpointList) { + let name = action.name.clone(); + self.actions.insert(name, action); + todo!("Decide if we want an arc of action or make a copy of that actions") + } + pub fn add_event(&mut self, event: EndpointList) { + todo!("Implement the events map") + } +} From 019eeb396bb174a0100113a005e0cbd194a8a0f1 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Wed, 26 Jan 2022 07:24:19 +0530 Subject: [PATCH 04/16] round robin selection strategy --- src/lib.rs | 3 ++- src/strategies/mod.rs | 16 +++++++++++++++ src/strategies/round_robin.rs | 37 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/strategies/mod.rs create mode 100644 src/strategies/round_robin.rs diff --git a/src/lib.rs b/src/lib.rs index 97ac64f..de71c00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ -pub mod registry; \ No newline at end of file +pub mod registry; +pub mod strategies; \ No newline at end of file diff --git a/src/strategies/mod.rs b/src/strategies/mod.rs new file mode 100644 index 0000000..9f2f206 --- /dev/null +++ b/src/strategies/mod.rs @@ -0,0 +1,16 @@ +use std::sync::Arc; + +use crate::registry::{ActionEndpoint, Broker, Registry}; +mod round_robin; + +trait Strategy { + fn new(registry: Arc, broker: Arc, opts: Opts) -> Self; + fn select<'a>( + &mut self, + list: Vec<&'a ActionEndpoint>, + ctx: Option, + ) -> Option<&'a ActionEndpoint>; +} + +struct Context {} +struct Opts {} diff --git a/src/strategies/round_robin.rs b/src/strategies/round_robin.rs new file mode 100644 index 0000000..459579f --- /dev/null +++ b/src/strategies/round_robin.rs @@ -0,0 +1,37 @@ +use super::*; +use std::sync::Arc; + +struct RoundRobinStrategy { + registry: Arc, + broker: Arc, + opts: Opts, + counter: usize, +} + +impl RoundRobinStrategy { + // fn new() -> Self {} +} +impl Strategy for RoundRobinStrategy { + fn new(registry: Arc, broker: Arc, opts: Opts) -> Self { + Self { + broker, + registry, + opts, + counter: 0, + } + } + fn select<'a>( + &mut self, + list: Vec<&'a ActionEndpoint>, + ctx: Option, + ) -> Option<&'a ActionEndpoint> { + if self.counter >= list.len() { + self.counter = 0; + } + self.counter = self.counter.saturating_add(1); + if let Some(ep) = list.get(self.counter) { + return Some(*ep); + } + None + } +} From 40548048b9e01d1c10ea5572ad82d8843e26f190 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Thu, 27 Jan 2022 01:33:56 +0530 Subject: [PATCH 05/16] made endpoint list generic over trait endpoint_trait --- src/registry/action_catalog.rs | 2 +- src/registry/endpoint_list.rs | 29 +++++++++++++++-------------- src/registry/mod.rs | 32 +++++++++++++++++++++++--------- src/registry/service_item.rs | 4 ++-- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index d4b17ab..f9173d8 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -41,7 +41,7 @@ impl ActionCatalog { } } } - fn get(&self, action_name: &str) -> Option<&EndpointList> { + fn get(&self, action_name: &str) -> Option<&EndpointList> { self.actions.get(action_name) } fn is_available(&self, action_name: &str) -> bool { diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index cf5c743..df6f5d4 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -2,17 +2,17 @@ use std::sync::Arc; use super::*; #[derive(PartialEq, Eq, Clone)] -pub struct EndpointList { + pub struct EndpointList { registry: Arc, broker: Arc, - pub name: String, + pub name: String, group: Option, internal: bool, - endpoints: Vec, - local_endpoints: Vec, + endpoints: Vec, + local_endpoints: Vec, } -impl EndpointList { +impl EndpointList { pub fn new( registry: Arc, broker: Arc, @@ -34,11 +34,11 @@ impl EndpointList { } } - pub fn add(&mut self, node: Arc, service: Arc, data: Action) { + pub fn add(&mut self, node: Arc, service: Arc, data:T::Data ) { let entry = self .endpoints .iter_mut() - .find(|x| x.node() == &*node && x.service_name() == service.name); + .find(|x| x.node() == &*node && x.service().name == service.name); match entry { Some(found) => { @@ -47,7 +47,8 @@ impl EndpointList { } None => {} } - let ep = ActionEndpoint::new( + + let ep = T::new( Arc::clone(&self.registry), Arc::clone(&self.broker), Arc::clone(&node), @@ -60,18 +61,18 @@ impl EndpointList { self.local_endpoints.push(ep) } } - fn get_first(&self) -> Option<&ActionEndpoint> { + fn get_first(&self) -> Option<&T> { self.endpoints.get(0) } - fn select(&self) -> &ActionEndpoint { + fn select(&self) -> &T { todo!() } - fn next(&self) -> &ActionEndpoint { + fn next(&self) -> &T { todo!() } - fn next_local(&self) -> &ActionEndpoint { + fn next_local(&self) -> &T { todo!() } @@ -88,7 +89,7 @@ impl EndpointList { } fn update_local_endpoints(&mut self) { - let mut local: Vec = Vec::new(); + let mut local: Vec = Vec::new(); for ep in &self.endpoints { if ep.is_local() { let e = ep.clone(); @@ -102,7 +103,7 @@ impl EndpointList { fn count(&self) -> usize { self.endpoints.len() } - fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&ActionEndpoint> { + fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { self.endpoints .iter() .find(|e| e.id() == node_id && e.is_available()) diff --git a/src/registry/mod.rs b/src/registry/mod.rs index f10bd53..7ff7b48 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -10,12 +10,13 @@ use std::collections::HashMap; pub use std::sync::Arc; pub use action_endpoint::ActionEndpoint; +use event_endpoint::EventEndpoint; pub use endpoint_list::EndpointList; pub use node::{Client, Node}; use service_item::ServiceItem; // pub use event_endpoint::EventEndpoint; -type ActionsMap = HashMap; +type ActionsMap = HashMap>; #[derive(PartialEq, Eq)] pub struct Logger {} @@ -42,17 +43,30 @@ trait FnType {} pub struct Action { name: String, } -impl FnType for Action {} -struct Event {} + +#[derive(PartialEq, Eq,Clone)] +pub struct Event {} impl FnType for Event {} pub struct Strategy {} -trait EndpointTrait { - fn node(&self) -> Node; - fn service(&self) -> ServiceItem; - fn update(&mut self, data: F) - where - F: FnType; +///Endpoint trait for endpoint list +pub trait EndpointTrait { + ///Data is eiter an Action struct or Event structs + type Data; + fn new( + registry: Arc, + broker: Arc, + node: Arc, + service: Arc, + data: Self::Data, + ) -> Self; + fn node(&self) -> &Node; + fn service(&self) -> &ServiceItem; + fn update(&mut self, data: Self::Data); + fn is_local(&self) -> bool; + fn is_available(&self)->bool; + fn id(&self)->&str; + fn service_name(&self)->&str; } #[derive(PartialEq, Eq, Clone)] diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs index b50c9a4..5332fcb 100644 --- a/src/registry/service_item.rs +++ b/src/registry/service_item.rs @@ -43,12 +43,12 @@ impl ServiceItem { todo!() } ///Add action to service - pub fn add_action(&mut self, action: EndpointList) { + pub fn add_action(&mut self, action: EndpointList) { let name = action.name.clone(); self.actions.insert(name, action); todo!("Decide if we want an arc of action or make a copy of that actions") } - pub fn add_event(&mut self, event: EndpointList) { + pub fn add_event(&mut self, event: EndpointList) { todo!("Implement the events map") } } From 5068a165c43245ffbaf8fda8ab933da9f0ddfa54 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Thu, 27 Jan 2022 01:34:35 +0530 Subject: [PATCH 06/16] impl endpoint_trait for action_ep & event_ep --- src/registry/action_endpoint.rs | 40 ++++++++++---------- src/registry/event_endpoint.rs | 67 ++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index adc9195..8053907 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -6,43 +6,45 @@ pub struct ActionEndpoint { action: Action, pub name: String, } -impl ActionEndpoint { - pub fn new( + +impl EndpointTrait for ActionEndpoint { + type Data = Action; + fn update(&mut self, data: Self::Data) { + self.action = data; + } + fn new( registry: Arc, broker: Arc, node: Arc, service: Arc, - action: Action, + data: Self::Data, ) -> Self { let endpoint = Endpoint::new(registry, broker, node, service); - let name = format!("{}:{}", endpoint.id, action.name); - ActionEndpoint { - action, + let name = format!("{}:{}", endpoint.id, data.name); + Self { endpoint, name, + action: data, } } - pub fn is_available(&self) -> bool { - self.endpoint.state - } - pub fn is_local(&self) -> bool { - self.endpoint.local - } - pub fn update(&mut self, action: Action) { - self.action = action - } - pub fn node(&self) -> &Node { + fn node(&self) -> &Node { &self.endpoint.node } - pub fn service(&self) -> &ServiceItem { + fn service(&self) -> &ServiceItem { &self.endpoint.service } - pub fn id(&self) -> &str { + fn is_local(&self) -> bool { + self.endpoint.local + } + fn is_available(&self) -> bool { + self.endpoint.state + } + fn id(&self) -> &str { &self.endpoint.id } - pub fn service_name(&self) -> &str { + fn service_name(&self) -> &str { &self.endpoint.service.name } } diff --git a/src/registry/event_endpoint.rs b/src/registry/event_endpoint.rs index 0618e0a..cb4d106 100644 --- a/src/registry/event_endpoint.rs +++ b/src/registry/event_endpoint.rs @@ -1,27 +1,48 @@ -// use super::{Broker, Endpoint, Node, Registry, ServiceItem, Event}; +use super::*; -// pub struct EventEndpoint { -// endpoint: Endpoint, -// event: Event, -// } -// impl EventEndpoint { -// fn new( -// registry: , -// broker: Broker, -// node: Node, -// service: ServiceItem, -// event: Event, -// ) -> Self { -// let endpoint = Endpoint::new(registry, broker, node, service); +#[derive(Clone)] +pub struct EventEndpoint { + endpoint: Endpoint, + event: Event, +} -// Self { event, endpoint } -// } +impl EndpointTrait for EventEndpoint { + type Data = Event; + fn update(&mut self, data: Self::Data) { + self.event = data; + } + fn new( + registry: Arc, + broker: Arc, + node: Arc, + service: Arc, + data: Self::Data, + ) -> Self { + let endpoint = Endpoint::new(registry, broker, node, service); + Self { + endpoint, -// fn is_available(&self) -> bool { -// self.endpoint.state -// } + event: data, + } + } -// fn update(&mut self, event: Event) { -// self.event = event -// } -// } + fn node(&self) -> &Node { + &self.endpoint.node + } + + fn service(&self) -> &ServiceItem { + &self.endpoint.service + } + fn is_local(&self) -> bool { + self.endpoint.local + } + fn is_available(&self) -> bool { + self.endpoint.state + } + fn id(&self) -> &str { + &self.endpoint.id + } + fn service_name(&self) -> &str { + &self.endpoint.service.name + } +} From 003064f190966e0278e6ebabad26945f41c9e1cd Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Thu, 27 Jan 2022 22:43:06 +0530 Subject: [PATCH 07/16] boilerplate for registry --- src/registry/action_catalog.rs | 16 ++-- src/registry/endpoint_list.rs | 2 +- src/registry/mod.rs | 41 ++++++---- src/registry/node.rs | 2 +- src/registry/node_catalog.rs | 5 +- src/registry/registry.rs | 132 ++++++++++++++++++++++++++++++++ src/registry/service_catalog.rs | 7 +- src/strategies/mod.rs | 12 +-- src/strategies/round_robin.rs | 4 +- 9 files changed, 183 insertions(+), 38 deletions(-) create mode 100644 src/registry/registry.rs diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index f9173d8..75ef4a4 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -2,22 +2,22 @@ use std::collections::HashMap; use super::*; -struct ActionCatalog { +#[derive(PartialEq, Eq)] +pub struct ActionCatalog { registry: Arc, broker: Arc, - strategy: Strategy, + logger: Arc, actions: ActionsMap, } impl ActionCatalog { - fn new(registry: Arc, broker: Arc, strategy: Strategy) -> Self { - let logger = registry.logger(); - let logger = Arc::clone(logger); + pub fn new(registry: Arc, broker: Arc) -> Self { + let logger = ®istry.logger; + let logger = Arc::clone(&logger); Self { registry, - strategy, broker, logger, actions: HashMap::new(), @@ -41,7 +41,7 @@ impl ActionCatalog { } } } - fn get(&self, action_name: &str) -> Option<&EndpointList> { + pub fn get(&self, action_name: &str) -> Option<&EndpointList> { self.actions.get(action_name) } fn is_available(&self, action_name: &str) -> bool { @@ -56,7 +56,7 @@ impl ActionCatalog { el.remove_by_service(service); }); } - fn remove(&mut self, action_name: &str, node_id: &str) { + pub fn remove(&mut self, action_name: &str, node_id: &str) { let list = self.actions.get_mut(action_name); if let Some(el) = list { el.remove_by_node_id(node_id); diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index df6f5d4..0129472 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -103,7 +103,7 @@ impl EndpointList { fn count(&self) -> usize { self.endpoints.len() } - fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { + pub fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { self.endpoints .iter() .find(|e| e.id() == node_id && e.is_available()) diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 7ff7b48..888a93b 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -4,15 +4,22 @@ pub mod endpoint_list; pub mod event_endpoint; pub mod node; pub mod node_catalog; +pub mod registry; pub mod service_catalog; pub mod service_item; + use std::collections::HashMap; -pub use std::sync::Arc; +use std::sync::Arc; +use crate::strategies::Strategy; +use action_catalog::ActionCatalog; pub use action_endpoint::ActionEndpoint; -use event_endpoint::EventEndpoint; pub use endpoint_list::EndpointList; +pub use event_endpoint::EventEndpoint; pub use node::{Client, Node}; +use node_catalog::NodeCatalog; +pub use registry::Registry; +use service_catalog::ServiceCatalog; use service_item::ServiceItem; // pub use event_endpoint::EventEndpoint; @@ -25,29 +32,27 @@ pub struct Broker { node_id: String, instance_id: String, moleculer_version: String, -} - -#[derive(PartialEq, Eq)] -pub struct Registry { logger: Arc, } -impl Registry { - pub fn logger(&self) -> &Arc { - &self.logger - } -} trait FnType {} #[derive(PartialEq, Eq, Clone)] pub struct Action { name: String, + visibility: Visibility, } -#[derive(PartialEq, Eq,Clone)] +#[derive(PartialEq, Eq, Clone)] +enum Visibility { + Published, + Public, + Protected, + Private, +} +#[derive(PartialEq, Eq, Clone)] pub struct Event {} impl FnType for Event {} -pub struct Strategy {} ///Endpoint trait for endpoint list pub trait EndpointTrait { @@ -64,9 +69,9 @@ pub trait EndpointTrait { fn service(&self) -> &ServiceItem; fn update(&mut self, data: Self::Data); fn is_local(&self) -> bool; - fn is_available(&self)->bool; - fn id(&self)->&str; - fn service_name(&self)->&str; + fn is_available(&self) -> bool; + fn id(&self) -> &str; + fn service_name(&self) -> &str; } #[derive(PartialEq, Eq, Clone)] @@ -115,3 +120,7 @@ pub struct Service { metadata */ } +#[derive(PartialEq, Eq)] +pub struct Opts { + strategy: T, +} diff --git a/src/registry/node.rs b/src/registry/node.rs index e7868c9..2bd7fff 100644 --- a/src/registry/node.rs +++ b/src/registry/node.rs @@ -9,7 +9,7 @@ pub struct Node { pub id: String, instance_id: Option, pub available: bool, - local: bool, + pub local: bool, last_heartbeat_time: Duration, /* feields that need to be added later. config diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index 962ba18..b8998fb 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -2,6 +2,7 @@ use std::{collections::HashMap, net::IpAddr, sync::Arc}; use super::{node, Broker, Client, Logger, Node, Registry}; +#[derive(PartialEq, Eq)] pub struct NodeCatalog { registry: Arc, broker: Arc, @@ -11,8 +12,8 @@ pub struct NodeCatalog { } impl NodeCatalog { pub fn new(registry: Arc, broker: Arc) -> Self { - let logger = registry.logger(); - let logger = Arc::clone(logger); + let logger = ®istry.logger; + let logger = Arc::clone(&logger); Self { broker, logger, diff --git a/src/registry/registry.rs b/src/registry/registry.rs new file mode 100644 index 0000000..f54905b --- /dev/null +++ b/src/registry/registry.rs @@ -0,0 +1,132 @@ +use super::*; +#[derive(PartialEq, Eq)] +pub struct Registry { + pub logger: Arc, + broker: Arc, + nodes: NodeCatalog, + services: ServiceCatalog, + actions: ActionCatalog, + /* + metrics + strategy factor + discoverer + opts + events + */ +} + +impl Registry { + pub fn new(broker: Arc) -> Self { + let logger = &broker.logger; + let logger = Arc::clone(&logger); + todo!() + } + + fn init() { + todo!("initialze discoverer") + } + fn stop() { + todo!("stop discoverre") + } + + fn register_moleculer_metrics(&self) { + todo!("register molecular metrics") + } + fn update_metrics(&self) { + todo!("update metrics") + } + pub fn register_local_service(svc: Service) { + todo!("after service has been done") + } + pub fn register_services() { + todo!("add remote serice support") + } + fn check_action_visibility(action: &Action, node: &Arc) -> bool { + match action.visibility { + Visibility::Published => true, + Visibility::Public => true, + Visibility::Protected => node.local, + _ => false, + } + } + fn register_actions() { + todo!() + } + fn create_private_action_endpoint(action: Action) { + todo!() + } + pub fn has_services(&self, full_name: &str, node_id: Option<&str>) -> bool { + self.services.has(full_name, node_id) + } + pub fn get_action_endpoints(&self, action_name: &str) -> Option<&EndpointList> { + self.actions.get(action_name) + } + pub fn get_action_endpoint_by_node_id( + &self, + action_name: &str, + node_id: &str, + ) -> Option<&EndpointList> { + let list = self.actions.get(action_name); + if let Some(list) = list { + list.get_endpoint_by_node_id(node_id); + } + None + } + fn unregister_service(&mut self, full_name: &str, node_id: Option<&str>) { + let id = match node_id { + Some(node_id) => node_id.to_string(), + None => self.broker.node_id.clone(), + }; + self.services.remove(full_name, &id); + match node_id { + Some(id) => { + if id == self.broker.node_id { + self.regenerate_local_raw_info(true); + } + } + None => self.regenerate_local_raw_info(true), + } + } + fn unregister_service_by_node_id(&mut self, node_id: &str) { + self.services.remove_all_by_node_id(node_id); + } + fn unregiste_action(&mut self, node_id: &str, action_name: &str) { + self.actions.remove(action_name, node_id); + } + + fn register_events() { + todo!() + } + fn unregister_event(&mut self, node_id: &str, event_name: &str) { + todo!() + } + + fn regenerate_local_raw_info(&self, incSeq: bool) { + todo!() + } + + fn get_local_node_info(&self, force: bool) { + todo!() + } + fn get_node_info(&self, node_id: &str) -> Option { + todo!() + } + fn process_node_info(&self) { + todo!() + } + fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { + self.nodes.list(only_available, with_services) + } + fn get_services_list(&self)->Vec<&ServiceItem>{ + todo!() + } + fn get_actions_list(&self)->Vec<&ActionEndpoint>{ + todo!() + } + fn get_event_list(&self)->Vec<&EventEndpoint>{ + todo!() + } + fn get_node_raw_list(&self){ + todo!() + } +} diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 8847db3..9499b7b 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(PartialEq, Eq)] pub struct ServiceCatalog { registry: Arc, broker: Arc, @@ -51,7 +52,7 @@ impl ServiceCatalog { todo!() } //remove all endpoints by node_id. - pub fn remove_by_node_id(&mut self, node_id: &str) { + pub fn remove_all_by_node_id(&mut self, node_id: &str) { let services: Vec<&ServiceItem> = self .services .iter() @@ -66,9 +67,9 @@ impl ServiceCatalog { todo!("updat the service") } - pub fn remove(&mut self, full_name: &str, node_id: Option<&str>) { + pub fn remove(&mut self, full_name: &str, node_id: &str) { self.services.retain(|svc| { - if svc.equals(full_name, node_id) { + if svc.equals(full_name, Some(node_id)) { todo!("remove actions and events in registry"); return false; diff --git a/src/strategies/mod.rs b/src/strategies/mod.rs index 9f2f206..ca52e2c 100644 --- a/src/strategies/mod.rs +++ b/src/strategies/mod.rs @@ -1,10 +1,11 @@ use std::sync::Arc; -use crate::registry::{ActionEndpoint, Broker, Registry}; +use crate::registry::{ActionEndpoint, Broker, Registry , Opts}; mod round_robin; -trait Strategy { - fn new(registry: Arc, broker: Arc, opts: Opts) -> Self; + +pub trait Strategy { + fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self; fn select<'a>( &mut self, list: Vec<&'a ActionEndpoint>, @@ -12,5 +13,6 @@ trait Strategy { ) -> Option<&'a ActionEndpoint>; } -struct Context {} -struct Opts {} +pub struct Context {} + +pub struct StrategyOpts{} \ No newline at end of file diff --git a/src/strategies/round_robin.rs b/src/strategies/round_robin.rs index 459579f..bb7b6c3 100644 --- a/src/strategies/round_robin.rs +++ b/src/strategies/round_robin.rs @@ -4,7 +4,7 @@ use std::sync::Arc; struct RoundRobinStrategy { registry: Arc, broker: Arc, - opts: Opts, + opts: StrategyOpts, counter: usize, } @@ -12,7 +12,7 @@ impl RoundRobinStrategy { // fn new() -> Self {} } impl Strategy for RoundRobinStrategy { - fn new(registry: Arc, broker: Arc, opts: Opts) -> Self { + fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self { Self { broker, registry, From 1e3e5fb376ca847093db79d979e77a7a73828717 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Sat, 29 Jan 2022 22:05:19 +0530 Subject: [PATCH 08/16] Service class work start --- src/lib.rs | 3 +- src/registry/mod.rs | 29 ++++++--- src/service.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 11 deletions(-) create mode 100644 src/service.rs diff --git a/src/lib.rs b/src/lib.rs index de71c00..861566c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod registry; -pub mod strategies; \ No newline at end of file +pub mod strategies; +pub mod service; \ No newline at end of file diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 888a93b..73b605c 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -11,6 +11,7 @@ pub mod service_item; use std::collections::HashMap; use std::sync::Arc; +use super::service::Service; use crate::strategies::Strategy; use action_catalog::ActionCatalog; pub use action_endpoint::ActionEndpoint; @@ -39,8 +40,25 @@ trait FnType {} #[derive(PartialEq, Eq, Clone)] pub struct Action { - name: String, + pub name: String, visibility: Visibility, + handler: fn(), + service: Option, +} + +impl Action { + pub fn new(name: String, handler: fn()) -> Self { + Self { + name, + visibility: Visibility::Protected, + handler, + service: None, + } + } + pub fn set_service(mut self , service : Service)->Action{ + self.service = Some(service); + self + } } #[derive(PartialEq, Eq, Clone)] @@ -111,15 +129,6 @@ enum EndpointType { Event, } -pub struct Service { - name: String, - full_name: String, - version: String, - /* - settings , - metadata - */ -} #[derive(PartialEq, Eq)] pub struct Opts { strategy: T, diff --git a/src/service.rs b/src/service.rs new file mode 100644 index 0000000..3e516d7 --- /dev/null +++ b/src/service.rs @@ -0,0 +1,144 @@ +use std::{collections::HashMap, sync::Arc}; + +use chrono::Duration; + +use crate::registry::{Action, Logger, Event}; + +#[derive(PartialEq, Eq, Clone)] +pub struct Service { + pub name: String, + pub full_name: String, + pub version: String, + settings: HashMap, + logger: Arc, + schema: Schema, + original_schema: Option, + metadata: HashMap, + actions : HashMap, + events : HashMap +} +#[derive(PartialEq, Eq, Clone)] +struct Schema { + mixins: Option>, + actions: Option>, + events: Option>, + merged: SchemaMerged, + name: Option, + version: Option, + settings: HashMap, + metadata: Option>, +} + +#[derive(PartialEq, Eq, Clone)] +struct SchemaMixins {} + +#[derive(PartialEq, Eq, Clone)] +struct SchemaActions {} + +#[derive(PartialEq, Eq, Clone)] +struct SchemaEvents {} +#[derive(PartialEq, Eq, Clone)] +enum SchemaMerged { + MergedFn(fn()), + MergedFnVec(Vec), +} + +impl Service { + fn parse_service_schema(&mut self, schema: Schema) { + self.original_schema = Some(schema.clone()); + + match schema.merged { + SchemaMerged::MergedFn(func) => { + + //TODO research about functions + } + SchemaMerged::MergedFnVec(func_vec) => { + for func in func_vec { + //TODO resarch more about functions + } + } + } + + if let None = schema.name { + //TODO throw error if no name available + } + self.name = schema.name.unwrap().clone(); + self.version = match schema.version { + Some(v) => v, + None => "0.0.1".to_string(), + }; + self.settings = schema.settings; + self.metadata = match schema.metadata { + Some(metadata) => metadata, + None => HashMap::new(), + }; + //TODO: + //self.schema = schema; + let version = self.settings.get("$noVersionPrefix"); + + self.full_name = Service::get_versioned_full_name(&self.name, version); + //TODO: get the logger from the broker. + //self.logger = + + + + //TODO:register methods. + + + + + + todo!("add service specification") + + + } + + fn init() { + todo!("call broker to initialise the service and call the init method of service") + } + + fn start() { + todo!("call the broker to start the services and call the start method of services") + } + + fn stop() { + todo!("call the broker to stop the service and call the stop method of service") + } + + fn create_action(&self, action_def: fn(), name: &str) -> Action { + let mut action = Action::new(name.to_string(), action_def); + let name_prefix = self.settings.get("$noServiceNamePrefix"); + if let Some(name_prefix) = name_prefix { + let name_prefix: bool = name_prefix.parse().unwrap(); + if name_prefix { + action.name = format!("{}.{}", self.full_name.to_string(), action.name); + } + } + //TODO add caching settings from settins + //TODO better way to handle this instead of clone. + action = action.set_service(self.clone()); + action + } + + /// create an interal service method. + fn create_method() { + todo!() + } + + ///create an event subscription for broker + fn create_event() { + todo!() + } + + fn wait_for_services(&self, service_names: Vec, timout: Duration, interval: Duration) { + todo!("call broker to wait for services") + } + + fn get_versioned_full_name(name: &str, version: Option<&String>) -> String { + let mut name = name.to_string(); + if let Some(v) = version { + name = format!("{}.{}", v, name); + } + name + } +} From 56533e1d0a02b2c3370af18cd2a77788fb798357 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Sat, 29 Jan 2022 23:49:23 +0530 Subject: [PATCH 09/16] broker renamed --- Cargo.lock | 106 ++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- src/broker.rs | 47 ++++++++++++++ src/packet.rs | 0 src/registry/action_catalog.rs | 4 +- src/registry/action_endpoint.rs | 2 +- src/registry/endpoint_list.rs | 4 +- src/registry/event_endpoint.rs | 2 +- src/registry/mod.rs | 8 +-- src/registry/node_catalog.rs | 6 +- src/registry/registry.rs | 4 +- src/registry/service_catalog.rs | 4 +- src/strategies/mod.rs | 4 +- src/strategies/round_robin.rs | 4 +- 14 files changed, 177 insertions(+), 22 deletions(-) create mode 100644 src/broker.rs create mode 100644 src/packet.rs diff --git a/Cargo.lock b/Cargo.lock index 53e1b5c..3609b14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,38 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[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.19" @@ -21,17 +47,62 @@ dependencies = [ "winapi", ] +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "libc" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + [[package]] name = "molecular-rust" version = "0.1.0" dependencies = [ "chrono", + "env_logger", + "log", ] [[package]] @@ -53,6 +124,32 @@ dependencies = [ "autocfg", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "time" version = "0.1.44" @@ -86,6 +183,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 42b3536..30cf703 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4.19" \ No newline at end of file +chrono = "0.4.19" +env_logger = "0.9.0" +log= "0.4.14" \ No newline at end of file diff --git a/src/broker.rs b/src/broker.rs new file mode 100644 index 0000000..03ecdce --- /dev/null +++ b/src/broker.rs @@ -0,0 +1,47 @@ +use std::{ + collections::HashMap, + sync::mpsc::{Receiver, Sender}, +}; + +use chrono::{DateTime, Utc}; + +use crate::{Registry, Service}; + +struct ServiceBroker { + reciever: Receiver, + started: bool, + namespace: Option, + metdata: HashMap, + node_id: String, + instance: String, + services: Vec, + /* + local bus + options + logger + metricss + middlewere + cacher + serializer + error generator + validator + tracer + transporter + */ + registry: Option, +} + +impl ServiceBroker { + fn start(&mut self) { + let time = Utc::now(); + self.started = true; + + } + + fn add_local_service(&mut self , service : Service){ + self.services.push(service); + } + +} + +enum ServiceBrokerAction {} diff --git a/src/packet.rs b/src/packet.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index 75ef4a4..a0f5530 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -5,14 +5,14 @@ use super::*; #[derive(PartialEq, Eq)] pub struct ActionCatalog { registry: Arc, - broker: Arc, + broker: Arc, logger: Arc, actions: ActionsMap, } impl ActionCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { + pub fn new(registry: Arc, broker: Arc) -> Self { let logger = ®istry.logger; let logger = Arc::clone(&logger); diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index 8053907..da27e2d 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -14,7 +14,7 @@ impl EndpointTrait for ActionEndpoint { } fn new( registry: Arc, - broker: Arc, + broker: Arc, node: Arc, service: Arc, data: Self::Data, diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index 0129472..b9068e8 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -4,7 +4,7 @@ use super::*; #[derive(PartialEq, Eq, Clone)] pub struct EndpointList { registry: Arc, - broker: Arc, + broker: Arc, pub name: String, group: Option, internal: bool, @@ -15,7 +15,7 @@ use super::*; impl EndpointList { pub fn new( registry: Arc, - broker: Arc, + broker: Arc, name: String, group: Option, ) -> Self { diff --git a/src/registry/event_endpoint.rs b/src/registry/event_endpoint.rs index cb4d106..c14702e 100644 --- a/src/registry/event_endpoint.rs +++ b/src/registry/event_endpoint.rs @@ -13,7 +13,7 @@ impl EndpointTrait for EventEndpoint { } fn new( registry: Arc, - broker: Arc, + broker: Arc, node: Arc, service: Arc, data: Self::Data, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 73b605c..877c129 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -29,7 +29,7 @@ type ActionsMap = HashMap>; #[derive(PartialEq, Eq)] pub struct Logger {} #[derive(PartialEq, Eq)] -pub struct Broker { +pub struct ServiceBroker { node_id: String, instance_id: String, moleculer_version: String, @@ -78,7 +78,7 @@ pub trait EndpointTrait { type Data; fn new( registry: Arc, - broker: Arc, + broker: Arc, node: Arc, service: Arc, data: Self::Data, @@ -95,7 +95,7 @@ pub trait EndpointTrait { #[derive(PartialEq, Eq, Clone)] struct Endpoint { registry: Arc, - broker: Arc, + broker: Arc, node: Arc, service: Arc, state: bool, @@ -106,7 +106,7 @@ struct Endpoint { impl Endpoint { fn new( registry: Arc, - broker: Arc, + broker: Arc, node: Arc, service: Arc, ) -> Self { diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index b8998fb..54974fa 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -1,17 +1,17 @@ use std::{collections::HashMap, net::IpAddr, sync::Arc}; -use super::{node, Broker, Client, Logger, Node, Registry}; +use super::{node, ServiceBroker, Client, Logger, Node, Registry}; #[derive(PartialEq, Eq)] pub struct NodeCatalog { registry: Arc, - broker: Arc, + broker: Arc, logger: Arc, nodes: HashMap, local_node: Option, } impl NodeCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { + pub fn new(registry: Arc, broker: Arc) -> Self { let logger = ®istry.logger; let logger = Arc::clone(&logger); Self { diff --git a/src/registry/registry.rs b/src/registry/registry.rs index f54905b..035b35c 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -2,7 +2,7 @@ use super::*; #[derive(PartialEq, Eq)] pub struct Registry { pub logger: Arc, - broker: Arc, + broker: Arc, nodes: NodeCatalog, services: ServiceCatalog, actions: ActionCatalog, @@ -16,7 +16,7 @@ pub struct Registry { } impl Registry { - pub fn new(broker: Arc) -> Self { + pub fn new(broker: Arc) -> Self { let logger = &broker.logger; let logger = Arc::clone(&logger); todo!() diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 9499b7b..06644e0 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -3,13 +3,13 @@ use super::*; #[derive(PartialEq, Eq)] pub struct ServiceCatalog { registry: Arc, - broker: Arc, + broker: Arc, logger: Arc, services: Vec, } impl ServiceCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { + pub fn new(registry: Arc, broker: Arc) -> Self { let logger = ®istry.logger; let logger = Arc::clone(&logger); Self { diff --git a/src/strategies/mod.rs b/src/strategies/mod.rs index ca52e2c..4b7b873 100644 --- a/src/strategies/mod.rs +++ b/src/strategies/mod.rs @@ -1,11 +1,11 @@ use std::sync::Arc; -use crate::registry::{ActionEndpoint, Broker, Registry , Opts}; +use crate::registry::{ActionEndpoint, ServiceBroker, Registry , Opts}; mod round_robin; pub trait Strategy { - fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self; + fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self; fn select<'a>( &mut self, list: Vec<&'a ActionEndpoint>, diff --git a/src/strategies/round_robin.rs b/src/strategies/round_robin.rs index bb7b6c3..b61ae23 100644 --- a/src/strategies/round_robin.rs +++ b/src/strategies/round_robin.rs @@ -3,7 +3,7 @@ use std::sync::Arc; struct RoundRobinStrategy { registry: Arc, - broker: Arc, + broker: Arc, opts: StrategyOpts, counter: usize, } @@ -12,7 +12,7 @@ impl RoundRobinStrategy { // fn new() -> Self {} } impl Strategy for RoundRobinStrategy { - fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self { + fn new(registry: Arc, broker: Arc, opts: StrategyOpts) -> Self { Self { broker, registry, From 066220dca1690714c1524eda9d6235614358c83d Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Sun, 30 Jan 2022 17:23:09 +0530 Subject: [PATCH 10/16] service broker init --- Cargo.lock | 37 +++++++++++++++++++++++ Cargo.toml | 4 ++- src/broker.rs | 64 ++++++++++++++++++++++++++++++++++++---- src/lib.rs | 7 ++++- src/logger.rs | 7 +++++ src/packet.rs | 23 +++++++++++++++ src/registry/registry.rs | 12 ++++---- src/service.rs | 24 +++++---------- 8 files changed, 149 insertions(+), 29 deletions(-) create mode 100644 src/logger.rs diff --git a/Cargo.lock b/Cargo.lock index 3609b14..ef91d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" + [[package]] name = "atty" version = "0.2.14" @@ -75,6 +81,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "libc" version = "0.2.114" @@ -100,9 +112,11 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" name = "molecular-rust" version = "0.1.0" dependencies = [ + "anyhow", "chrono", "env_logger", "log", + "serde_json", ] [[package]] @@ -141,6 +155,29 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" + +[[package]] +name = "serde_json" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "termcolor" version = "1.1.2" diff --git a/Cargo.toml b/Cargo.toml index 30cf703..f252c4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,6 @@ edition = "2021" [dependencies] chrono = "0.4.19" env_logger = "0.9.0" -log= "0.4.14" \ No newline at end of file +log= "0.4.14" +serde_json = "1.0.0" +anyhow = "1.0.53" \ No newline at end of file diff --git a/src/broker.rs b/src/broker.rs index 03ecdce..fa2941d 100644 --- a/src/broker.rs +++ b/src/broker.rs @@ -1,11 +1,14 @@ use std::{ + any, collections::HashMap, sync::mpsc::{Receiver, Sender}, }; +use anyhow::{bail, Error, Result}; + use chrono::{DateTime, Utc}; -use crate::{Registry, Service}; +use crate::{registry::service_item::ServiceItem, service, Registry, Service}; struct ServiceBroker { reciever: Receiver, @@ -28,20 +31,71 @@ struct ServiceBroker { tracer transporter */ - registry: Option, + registry: Registry, } impl ServiceBroker { fn start(&mut self) { let time = Utc::now(); self.started = true; - } - fn add_local_service(&mut self , service : Service){ + fn add_local_service(&mut self, service: Service) { self.services.push(service); } - + fn register_local_service(&mut self, service: ServiceItem) { + self.registry.register_local_service(service); + } + + fn destroy_service(&mut self, name: &str, version: &str) -> Result<()> { + let service_index = self.get_local_service_index(name, version); + if let None = service_index { + bail!( + "no service with the name {} and version {} found", + name, + version + ); + } + let service_index = service_index.unwrap(); + let mut full_name = "".to_string(); + + { + let service = self.services.get_mut(service_index).unwrap(); + full_name = service.full_name.clone(); + service.stop(); + } + { + self.services.remove(service_index); + } + + self.registry + .unregister_service(&full_name, Some(&self.node_id)); + self.services_changed(true); + Ok(()) + } + + fn services_changed(&self, local_service: bool) { + if (self.started && local_service) { + todo!("notifify remote nodes") + } + } + fn get_local_service_index(&self, name: &str, version: &str) -> Option { + self.services.iter().position(|s| { + if s.name == name && s.version == version { + return true; + } + return false; + }) + } } enum ServiceBrokerAction {} + +fn remove_from_list(list: &mut Vec, value: &T) { + list.retain(|t| { + if t == value { + return false; + } + return true; + }); +} diff --git a/src/lib.rs b/src/lib.rs index 861566c..a3c42b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,8 @@ pub mod registry; pub mod strategies; -pub mod service; \ No newline at end of file +pub mod service; +pub mod broker; +pub mod logger; +pub mod packet; +pub use service::Service; +pub use registry::Registry; diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..5ae7983 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,7 @@ +use log::{debug, error, info, log_enabled, Level}; + +trait LoggerTrait { + fn init(); + fn stop(); + fn get_log_handler(); +} diff --git a/src/packet.rs b/src/packet.rs index e69de29..036a771 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -0,0 +1,23 @@ +use core::fmt; + + + + +enum PacketType { + Unknown, + Event, + Request, + Response, + Discover, + Info , + Disconnect , + Heartbeat, + Ping, + Pong, +} + +impl From for String { + fn from(p: PacketType) -> Self { + "as".to_string() + } +} diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 035b35c..6f70b5a 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -35,7 +35,7 @@ impl Registry { fn update_metrics(&self) { todo!("update metrics") } - pub fn register_local_service(svc: Service) { + pub fn register_local_service(&mut self, svc: ServiceItem) { todo!("after service has been done") } pub fn register_services() { @@ -72,7 +72,7 @@ impl Registry { } None } - fn unregister_service(&mut self, full_name: &str, node_id: Option<&str>) { + pub fn unregister_service(&mut self, full_name: &str, node_id: Option<&str>) { let id = match node_id { Some(node_id) => node_id.to_string(), None => self.broker.node_id.clone(), @@ -117,16 +117,16 @@ impl Registry { fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { self.nodes.list(only_available, with_services) } - fn get_services_list(&self)->Vec<&ServiceItem>{ + fn get_services_list(&self) -> Vec<&ServiceItem> { todo!() } - fn get_actions_list(&self)->Vec<&ActionEndpoint>{ + fn get_actions_list(&self) -> Vec<&ActionEndpoint> { todo!() } - fn get_event_list(&self)->Vec<&EventEndpoint>{ + fn get_event_list(&self) -> Vec<&EventEndpoint> { todo!() } - fn get_node_raw_list(&self){ + fn get_node_raw_list(&self) { todo!() } } diff --git a/src/service.rs b/src/service.rs index 3e516d7..ece0895 100644 --- a/src/service.rs +++ b/src/service.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::Arc}; use chrono::Duration; -use crate::registry::{Action, Logger, Event}; +use crate::registry::{Action, Event, Logger}; #[derive(PartialEq, Eq, Clone)] pub struct Service { @@ -14,8 +14,8 @@ pub struct Service { schema: Schema, original_schema: Option, metadata: HashMap, - actions : HashMap, - events : HashMap + actions: HashMap, + events: HashMap, } #[derive(PartialEq, Eq, Clone)] struct Schema { @@ -75,33 +75,25 @@ impl Service { //TODO: //self.schema = schema; let version = self.settings.get("$noVersionPrefix"); - + self.full_name = Service::get_versioned_full_name(&self.name, version); //TODO: get the logger from the broker. - //self.logger = - - + //self.logger = //TODO:register methods. - - - - todo!("add service specification") - - } - fn init() { + pub fn init(&mut self) { todo!("call broker to initialise the service and call the init method of service") } - fn start() { + pub fn start(&mut self) { todo!("call the broker to start the services and call the start method of services") } - fn stop() { + pub fn stop(&mut self) { todo!("call the broker to stop the service and call the stop method of service") } From e3003d1e9cd6854b93bf88bc92f235e629ad5154 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Tue, 1 Feb 2022 10:38:44 +0530 Subject: [PATCH 11/16] removed broker and registry dependecies on catalogs --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 3 ++- src/broker.rs | 6 ++++-- src/packet.rs | 9 +++------ src/registry/action_catalog.rs | 19 ++----------------- src/registry/action_endpoint.rs | 10 ++-------- src/registry/endpoint_list.rs | 27 ++++++--------------------- src/registry/event_endpoint.rs | 10 ++-------- src/registry/mod.rs | 23 ++++------------------- src/registry/node_catalog.rs | 21 ++++++++------------- src/registry/registry.rs | 9 +++++++-- src/registry/service_catalog.rs | 10 +--------- src/registry/service_item.rs | 2 +- 13 files changed, 58 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef91d5c..754678a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,6 +117,7 @@ dependencies = [ "env_logger", "log", "serde_json", + "tokio", ] [[package]] @@ -138,6 +139,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + [[package]] name = "regex" version = "1.5.4" @@ -198,6 +205,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "tokio" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +dependencies = [ + "pin-project-lite", +] + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index f252c4b..5a05252 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,5 @@ chrono = "0.4.19" env_logger = "0.9.0" log= "0.4.14" serde_json = "1.0.0" -anyhow = "1.0.53" \ No newline at end of file +anyhow = "1.0.53" +tokio = "1.16.1" \ No newline at end of file diff --git a/src/broker.rs b/src/broker.rs index fa2941d..cc0bff4 100644 --- a/src/broker.rs +++ b/src/broker.rs @@ -11,7 +11,7 @@ use chrono::{DateTime, Utc}; use crate::{registry::service_item::ServiceItem, service, Registry, Service}; struct ServiceBroker { - reciever: Receiver, + reciever: Receiver, started: bool, namespace: Option, metdata: HashMap, @@ -89,7 +89,9 @@ impl ServiceBroker { } } -enum ServiceBrokerAction {} +enum ServiceBrokerMessage { + +} fn remove_from_list(list: &mut Vec, value: &T) { list.retain(|t| { diff --git a/src/packet.rs b/src/packet.rs index 036a771..a0d7749 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,19 +1,16 @@ use core::fmt; - - - enum PacketType { Unknown, Event, Request, Response, Discover, - Info , - Disconnect , + Info, + Disconnect, Heartbeat, Ping, - Pong, + Pongs, } impl From for String { diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index a0f5530..4b6919c 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -4,22 +4,12 @@ use super::*; #[derive(PartialEq, Eq)] pub struct ActionCatalog { - registry: Arc, - broker: Arc, - - logger: Arc, actions: ActionsMap, } impl ActionCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { - let logger = ®istry.logger; - let logger = Arc::clone(&logger); - + pub fn new() -> Self { Self { - registry, - broker, - logger, actions: HashMap::new(), } } @@ -29,12 +19,7 @@ impl ActionCatalog { Some(list) => list.add(node, service, action), None => { let name = action.name.clone(); - let mut list = EndpointList::new( - Arc::clone(&self.registry), - Arc::clone(&self.broker), - name, - None, - ); + let mut list = EndpointList::new(name, None); let name = action.name.clone(); list.add(node, service, action); self.actions.insert(name, list); diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index da27e2d..1d9cc7a 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -12,14 +12,8 @@ impl EndpointTrait for ActionEndpoint { fn update(&mut self, data: Self::Data) { self.action = data; } - fn new( - registry: Arc, - broker: Arc, - node: Arc, - service: Arc, - data: Self::Data, - ) -> Self { - let endpoint = Endpoint::new(registry, broker, node, service); + fn new(node: Arc, service: Arc, data: Self::Data) -> Self { + let endpoint = Endpoint::new(node, service); let name = format!("{}:{}", endpoint.id, data.name); Self { endpoint, diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index b9068e8..59f61cd 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -2,9 +2,7 @@ use std::sync::Arc; use super::*; #[derive(PartialEq, Eq, Clone)] - pub struct EndpointList { - registry: Arc, - broker: Arc, +pub struct EndpointList { pub name: String, group: Option, internal: bool, @@ -12,20 +10,13 @@ use super::*; local_endpoints: Vec, } -impl EndpointList { - pub fn new( - registry: Arc, - broker: Arc, - name: String, - group: Option, - ) -> Self { +impl EndpointList { + pub fn new(name: String, group: Option) -> Self { let internal = name.starts_with("$"); let endpoints = Vec::new(); let local_endpoints = Vec::new(); Self { - registry, - broker, name, group, endpoints, @@ -34,7 +25,7 @@ impl EndpointList { } } - pub fn add(&mut self, node: Arc, service: Arc, data:T::Data ) { + pub fn add(&mut self, node: Arc, service: Arc, data: T::Data) { let entry = self .endpoints .iter_mut() @@ -48,13 +39,7 @@ impl EndpointList { None => {} } - let ep = T::new( - Arc::clone(&self.registry), - Arc::clone(&self.broker), - Arc::clone(&node), - Arc::clone(&service), - data, - ); + let ep = T::new(Arc::clone(&node), Arc::clone(&service), data); self.endpoints.push(ep.clone()); if ep.is_local() { @@ -103,7 +88,7 @@ impl EndpointList { fn count(&self) -> usize { self.endpoints.len() } - pub fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { + pub fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { self.endpoints .iter() .find(|e| e.id() == node_id && e.is_available()) diff --git a/src/registry/event_endpoint.rs b/src/registry/event_endpoint.rs index c14702e..d8cd7d6 100644 --- a/src/registry/event_endpoint.rs +++ b/src/registry/event_endpoint.rs @@ -11,14 +11,8 @@ impl EndpointTrait for EventEndpoint { fn update(&mut self, data: Self::Data) { self.event = data; } - fn new( - registry: Arc, - broker: Arc, - node: Arc, - service: Arc, - data: Self::Data, - ) -> Self { - let endpoint = Endpoint::new(registry, broker, node, service); + fn new(node: Arc, service: Arc, data: Self::Data) -> Self { + let endpoint = Endpoint::new(node, service); Self { endpoint, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 877c129..e6c8b3f 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -55,7 +55,7 @@ impl Action { service: None, } } - pub fn set_service(mut self , service : Service)->Action{ + pub fn set_service(mut self, service: Service) -> Action { self.service = Some(service); self } @@ -76,13 +76,7 @@ impl FnType for Event {} pub trait EndpointTrait { ///Data is eiter an Action struct or Event structs type Data; - fn new( - registry: Arc, - broker: Arc, - node: Arc, - service: Arc, - data: Self::Data, - ) -> Self; + fn new(node : Arc , service: Arc, data: Self::Data) -> Self; fn node(&self) -> &Node; fn service(&self) -> &ServiceItem; fn update(&mut self, data: Self::Data); @@ -94,8 +88,6 @@ pub trait EndpointTrait { #[derive(PartialEq, Eq, Clone)] struct Endpoint { - registry: Arc, - broker: Arc, node: Arc, service: Arc, state: bool, @@ -104,17 +96,10 @@ struct Endpoint { } impl Endpoint { - fn new( - registry: Arc, - broker: Arc, - node: Arc, - service: Arc, - ) -> Self { - let local = node.id == broker.node_id; + fn new(node: Arc, service: Arc) -> Self { let id = node.id.to_string(); + let local = service.local; Self { - registry, - broker, node, service, state: true, diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index 54974fa..54f01c6 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -4,35 +4,30 @@ use super::{node, ServiceBroker, Client, Logger, Node, Registry}; #[derive(PartialEq, Eq)] pub struct NodeCatalog { - registry: Arc, - broker: Arc, - logger: Arc, + nodes: HashMap, local_node: Option, } impl NodeCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { - let logger = ®istry.logger; - let logger = Arc::clone(&logger); + pub fn new() -> Self { + Self { - broker, - logger, - registry, + nodes: HashMap::new(), local_node: None, } } ///Create a local node - fn create_local_node(&mut self) -> Node { + fn create_local_node(&mut self , version : String , node_id : String , instance_id : String) -> Node { let client = Client { client_type: "rust".to_string(), lang_version: "1.56.1".to_string(), - version: self.broker.moleculer_version.clone(), + version: version }; - let node = Node::new(self.broker.node_id.clone()) + let node = Node::new(node_id) .set_local(true) .set_ip_list(get_ip_list()) - .set_instance_id(self.broker.instance_id.clone()) + .set_instance_id(instance_id) .set_hostname(get_hostname()) .set_seq(1) .set_client(client); diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 6f70b5a..92ee670 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,8 +1,13 @@ +use crate::ServiceBrokerMessage; + use super::*; -#[derive(PartialEq, Eq)] +use tokio::sync::mpsc::{Sender}; + + pub struct Registry { pub logger: Arc, - broker: Arc, + broker_sender: Sender, + broker : Arc, nodes: NodeCatalog, services: ServiceCatalog, actions: ActionCatalog, diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 06644e0..72e9c3b 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -2,20 +2,12 @@ use super::*; #[derive(PartialEq, Eq)] pub struct ServiceCatalog { - registry: Arc, - broker: Arc, - logger: Arc, services: Vec, } impl ServiceCatalog { - pub fn new(registry: Arc, broker: Arc) -> Self { - let logger = ®istry.logger; - let logger = Arc::clone(&logger); + pub fn new() -> Self { Self { - broker, - registry, - logger, services: Vec::new(), } } diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs index 5332fcb..216346d 100644 --- a/src/registry/service_item.rs +++ b/src/registry/service_item.rs @@ -4,7 +4,7 @@ use super::*; pub struct ServiceItem { pub name: String, pub node: Arc, - local: bool, + pub local: bool, full_name: String, version: String, actions: ActionsMap, From 64b2b56848161969a48057fb8d3a433925cfe538 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Thu, 3 Feb 2022 23:51:09 +0530 Subject: [PATCH 12/16] registry prototype --- Cargo.lock | 196 ++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- src/broker.rs | 16 ++- src/lib.rs | 2 + src/registry/action_catalog.rs | 37 +++++- src/registry/action_endpoint.rs | 2 +- src/registry/endpoint_list.rs | 6 +- src/registry/mod.rs | 29 +++-- src/registry/node.rs | 8 +- src/registry/node_catalog.rs | 22 ++-- src/registry/registry.rs | 81 +++++++++---- src/registry/service_catalog.rs | 42 +++++-- src/registry/service_item.rs | 4 +- src/service.rs | 9 +- src/strategies/mod.rs | 3 +- 15 files changed, 393 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 754678a..d62240c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,6 +34,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + [[package]] name = "cfg-if" version = "1.0.0" @@ -81,18 +93,42 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -108,6 +144,28 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + [[package]] name = "molecular-rust" version = "0.1.0" @@ -115,11 +173,22 @@ dependencies = [ "anyhow", "chrono", "env_logger", + "lazy_static", "log", + "regex", "serde_json", "tokio", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -139,12 +208,80 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "pin-project-lite" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.5.4" @@ -168,6 +305,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.136" @@ -185,6 +328,32 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -211,9 +380,36 @@ version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", ] +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 5a05252..66202d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,6 @@ env_logger = "0.9.0" log= "0.4.14" serde_json = "1.0.0" anyhow = "1.0.53" -tokio = "1.16.1" \ No newline at end of file +tokio = { version = "1.16.1", features = ["full"] } +regex = "1.5.4" +lazy_static = "1.3.0" \ No newline at end of file diff --git a/src/broker.rs b/src/broker.rs index cc0bff4..6950b77 100644 --- a/src/broker.rs +++ b/src/broker.rs @@ -1,23 +1,25 @@ use std::{ any, collections::HashMap, - sync::mpsc::{Receiver, Sender}, + sync::{mpsc::{Receiver, Sender}, Arc}, }; use anyhow::{bail, Error, Result}; use chrono::{DateTime, Utc}; -use crate::{registry::service_item::ServiceItem, service, Registry, Service}; +use crate::{registry::{service_item::ServiceItem, Logger}, service, Registry, Service}; -struct ServiceBroker { +pub struct ServiceBroker { reciever: Receiver, started: bool, namespace: Option, metdata: HashMap, - node_id: String, + pub node_id: String, instance: String, services: Vec, + pub transit : Option, + pub logger : Arc, /* local bus options @@ -34,6 +36,8 @@ struct ServiceBroker { registry: Registry, } +pub struct Transit{} + impl ServiceBroker { fn start(&mut self) { let time = Utc::now(); @@ -43,7 +47,7 @@ impl ServiceBroker { fn add_local_service(&mut self, service: Service) { self.services.push(service); } - fn register_local_service(&mut self, service: ServiceItem) { + fn register_local_service(&mut self, service: Service) { self.registry.register_local_service(service); } @@ -89,7 +93,7 @@ impl ServiceBroker { } } -enum ServiceBrokerMessage { +pub enum ServiceBrokerMessage { } diff --git a/src/lib.rs b/src/lib.rs index a3c42b1..a33a840 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,5 @@ pub mod logger; pub mod packet; pub use service::Service; pub use registry::Registry; +pub use broker::ServiceBrokerMessage; +pub use broker::ServiceBroker; \ No newline at end of file diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index 4b6919c..3675d77 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -13,7 +13,7 @@ impl ActionCatalog { actions: HashMap::new(), } } - fn add(&mut self, node: Arc, service: Arc, action: Action) { + pub fn add(&mut self, node: Arc, service: Arc, action: Action) { let list = self.actions.get_mut(&action.name); match list { Some(list) => list.add(node, service, action), @@ -47,7 +47,38 @@ impl ActionCatalog { el.remove_by_node_id(node_id); } } - fn list(&self) { - todo!() + pub fn list(&self, opts: ListOptions) -> Vec<&EndpointList> { + let res: HashMap<&String, &EndpointList> = self + .actions + .iter() + .filter(|item| { + let (name, ep_list) = item; + if opts.skip_internal && get_internal_service_regex_match(&name) { + return false; + } + if opts.only_local && !ep_list.has_local() { + return false; + } + if opts.only_available && !ep_list.has_available() { + return false; + } + if ep_list.count() > 0 { + let ep = ep_list.endpoints.get(0); + if let Some(ep) = ep { + if ep.action.visibility == Visibility::Protected { + return false; + } + } + } + return true; + }) + .collect(); + let res = res + .values() + .map(|ep| { + return ep.to_owned(); + }) + .collect(); + res } } diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index 1d9cc7a..948ba8c 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -3,7 +3,7 @@ use super::*; #[derive(PartialEq, Eq, Clone)] pub struct ActionEndpoint { endpoint: Endpoint, - action: Action, + pub action: Action, pub name: String, } diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index 59f61cd..f0d2715 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -6,7 +6,7 @@ pub struct EndpointList { pub name: String, group: Option, internal: bool, - endpoints: Vec, + pub endpoints: Vec, local_endpoints: Vec, } @@ -69,7 +69,7 @@ impl EndpointList { } return false; } - fn has_local(&self) -> bool { + pub fn has_local(&self) -> bool { self.local_endpoints.len() > 0 } @@ -85,7 +85,7 @@ impl EndpointList { drop(local); } - fn count(&self) -> usize { + pub fn count(&self) -> usize { self.endpoints.len() } pub fn get_endpoint_by_node_id(&self, node_id: &str) -> Option<&T> { diff --git a/src/registry/mod.rs b/src/registry/mod.rs index e6c8b3f..3977e18 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -19,22 +19,27 @@ pub use endpoint_list::EndpointList; pub use event_endpoint::EventEndpoint; pub use node::{Client, Node}; use node_catalog::NodeCatalog; +use regex::Regex; pub use registry::Registry; use service_catalog::ServiceCatalog; use service_item::ServiceItem; +use lazy_static::lazy_static; // pub use event_endpoint::EventEndpoint; + type ActionsMap = HashMap>; +fn get_internal_service_regex_match(text: &str) -> bool { + lazy_static! { + static ref RE: Regex = Regex::new(r"^\$").unwrap(); + + } + RE.is_match(text) +} + + #[derive(PartialEq, Eq)] pub struct Logger {} -#[derive(PartialEq, Eq)] -pub struct ServiceBroker { - node_id: String, - instance_id: String, - moleculer_version: String, - logger: Arc, -} trait FnType {} @@ -76,7 +81,7 @@ impl FnType for Event {} pub trait EndpointTrait { ///Data is eiter an Action struct or Event structs type Data; - fn new(node : Arc , service: Arc, data: Self::Data) -> Self; + fn new(node: Arc, service: Arc, data: Self::Data) -> Self; fn node(&self) -> &Node; fn service(&self) -> &ServiceItem; fn update(&mut self, data: Self::Data); @@ -118,3 +123,11 @@ enum EndpointType { pub struct Opts { strategy: T, } +pub struct ListOptions { + only_local: bool, + only_available: bool, + skip_internal: bool, + with_actions: bool, + with_events: bool, + grouping: bool, +} diff --git a/src/registry/node.rs b/src/registry/node.rs index 2bd7fff..8fdc6ad 100644 --- a/src/registry/node.rs +++ b/src/registry/node.rs @@ -1,6 +1,7 @@ -use std::net::IpAddr; +use std::{net::IpAddr, sync::Arc}; use chrono::Duration; +use serde_json::Value; use super::ServiceItem; @@ -21,12 +22,12 @@ pub struct Node { port: Option, hostname: Option, udp_address: Option, + pub raw_info: Option, /* - raw_info cpu cpuseq */ - services: Vec, + pub services: Vec>, pub seq: usize, offline_since: Option, } @@ -39,6 +40,7 @@ impl Node { available: true, local: false, client: None, + raw_info: None, /* change this later with actual process uptime. */ diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index 54f01c6..be80799 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -1,28 +1,27 @@ use std::{collections::HashMap, net::IpAddr, sync::Arc}; -use super::{node, ServiceBroker, Client, Logger, Node, Registry}; +use std::sync::RwLock; + +use super::{node, Client, Logger, Node, Registry}; + -#[derive(PartialEq, Eq)] pub struct NodeCatalog { - nodes: HashMap, - local_node: Option, + pub local_node: Option>, } impl NodeCatalog { pub fn new() -> Self { - Self { - nodes: HashMap::new(), local_node: None, } } ///Create a local node - fn create_local_node(&mut self , version : String , node_id : String , instance_id : String) -> Node { + fn create_local_node(&mut self, version: String, node_id: String, instance_id: String) -> Arc { let client = Client { client_type: "rust".to_string(), lang_version: "1.56.1".to_string(), - version: version + version: version, }; let node = Node::new(node_id) .set_local(true) @@ -33,8 +32,10 @@ impl NodeCatalog { .set_client(client); self.nodes.insert(node.id.to_string(), node.clone()); - self.local_node = Some(node.clone()); - return node; + let node = Arc::new(node); + let node_c = Arc::clone(&node); + self.local_node = Some(node); + return node_c; todo!() /* node.metadata = self.broker.metadata.clone() @@ -119,3 +120,4 @@ fn get_ip_list() -> Vec { fn get_hostname() -> String { todo!() } + diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 92ee670..aa65ca6 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,16 +1,17 @@ -use crate::ServiceBrokerMessage; +use crate::{ServiceBrokerMessage, service::SchemaActions, ServiceBroker}; use super::*; -use tokio::sync::mpsc::{Sender}; - +use serde_json::Value; +use tokio::sync::mpsc::Sender; pub struct Registry { pub logger: Arc, broker_sender: Sender, - broker : Arc, + broker: Arc, nodes: NodeCatalog, services: ServiceCatalog, actions: ActionCatalog, + /* metrics strategy factor @@ -19,7 +20,6 @@ pub struct Registry { events */ } - impl Registry { pub fn new(broker: Arc) -> Self { let logger = &broker.logger; @@ -40,8 +40,26 @@ impl Registry { fn update_metrics(&self) { todo!("update metrics") } - pub fn register_local_service(&mut self, svc: ServiceItem) { - todo!("after service has been done") + pub fn register_local_service(&mut self, svc: Service) { + if !self + .services + .has(&svc.full_name, Some(&self.broker.node_id)) + { + let service = self.services.add( + Arc::clone(&self.nodes.local_node.as_ref().unwrap()), + &svc, + true, + ); + if let Some(actions) = svc.actions { + let local_node = Arc::clone(&self.nodes.local_node.as_ref().unwrap()); + self.register_actions(local_node , Arc::clone(&service) , actions); + } + if let Some(events) = svc.events { + self.register_events(); + } + //TODO:Add service to the local node. + //self.nodes.local_node.unwrap().services.push(Arc::clone(&service)); + } } pub fn register_services() { todo!("add remote serice support") @@ -54,8 +72,25 @@ impl Registry { _ => false, } } - fn register_actions() { - todo!() + fn register_actions(&mut self , node : Arc , service: Arc , actions : Vec) { + actions.iter().for_each(|action|{ + if !Registry::check_action_visibility(action, &node){ + return; + } + if node.local{ + //TODO:stuff with middleware and handlers. + + + }else if let Some(_) = self.broker.transit { + //TODO: for remote services + return; + } + let node = Arc::clone(&node); + let service = Arc::clone(&service); + self.actions.add(node, service, action.to_owned()); + //TODO: + //add the action to the service. + }); } fn create_private_action_endpoint(action: Action) { todo!() @@ -86,10 +121,10 @@ impl Registry { match node_id { Some(id) => { if id == self.broker.node_id { - self.regenerate_local_raw_info(true); + self.regenerate_local_raw_info(Some(true)); } } - None => self.regenerate_local_raw_info(true), + None => {self.regenerate_local_raw_info(Some(true));}, } } fn unregister_service_by_node_id(&mut self, node_id: &str) { @@ -99,19 +134,26 @@ impl Registry { self.actions.remove(action_name, node_id); } - fn register_events() { + fn register_events(&mut self) { todo!() } fn unregister_event(&mut self, node_id: &str, event_name: &str) { todo!() } - fn regenerate_local_raw_info(&self, incSeq: bool) { + fn regenerate_local_raw_info(&self, incSeq: Option)->Value { todo!() } - fn get_local_node_info(&self, force: bool) { - todo!() + fn get_local_node_info(&self, force: bool)->Value { + if let None = self.nodes.local_node{ + return self.regenerate_local_raw_info(None); + } + if force { + return self.regenerate_local_raw_info(None); + } + let value = self.nodes.local_node.as_ref().unwrap().raw_info.to_owned(); + value.unwrap() } fn get_node_info(&self, node_id: &str) -> Option { todo!() @@ -119,13 +161,14 @@ impl Registry { fn process_node_info(&self) { todo!() } - fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { + pub fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { self.nodes.list(only_available, with_services) } - fn get_services_list(&self) -> Vec<&ServiceItem> { - todo!() + pub fn get_services_list(&self, opts: ListOptions) -> Vec<&Arc> { + self.services.list(opts) } - fn get_actions_list(&self) -> Vec<&ActionEndpoint> { + fn get_actions_list(&self , opts:ListOptions) -> Vec<&ActionEndpoint> { + //self.actions.list(opts) todo!() } fn get_event_list(&self) -> Vec<&EventEndpoint> { diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 72e9c3b..8b8e83a 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -1,8 +1,8 @@ use super::*; - +use regex::Regex; #[derive(PartialEq, Eq)] pub struct ServiceCatalog { - services: Vec, + services: Vec>, } impl ServiceCatalog { @@ -12,9 +12,13 @@ impl ServiceCatalog { } } ///Add a new service - pub fn add(&mut self, node: Arc, service: Arc, local: bool) { + pub fn add(&mut self, node: Arc, service: &Service, local: bool) -> Arc { let service_item = ServiceItem::new(node, service, local); + let service_item = Arc::new(service_item); + + let item = Arc::clone(&service_item); self.services.push(service_item); + item } ///Check the service exsists pub fn has(&self, full_name: &str, node_id: Option<&str>) -> bool { @@ -27,25 +31,47 @@ impl ServiceCatalog { None => false, } } - pub fn get(&self, full_name: &str, node_id: Option<&str>) -> Option<&ServiceItem> { + pub fn get(&self, full_name: &str, node_id: Option<&str>) -> Option<&Arc> { self.services .iter() .find(|svc| svc.equals(full_name, node_id)) } - pub fn get_mut(&mut self, full_name: &str, node_id: Option<&str>) -> Option<&mut ServiceItem> { + pub fn get_mut( + &mut self, + full_name: &str, + node_id: Option<&str>, + ) -> Option<&mut Arc> { self.services .iter_mut() .find(|svc| svc.equals(full_name, node_id)) } - pub fn list(&self) { - todo!() + pub fn list( + &self, + opts : ListOptions + ) -> Vec<&Arc> { + + self.services.iter().filter(|svc| { + if opts.skip_internal && get_internal_service_regex_match(&svc.name) { + return false; + } + if opts.only_local && !svc.local { + return false; + } + if opts.only_available && !svc.node.available { + return false; + } + + return true; + }).collect() + // TODO:("implement grouping and all that stuff") + } pub fn get_local_node_service(&self) { todo!() } //remove all endpoints by node_id. pub fn remove_all_by_node_id(&mut self, node_id: &str) { - let services: Vec<&ServiceItem> = self + let services: Vec<&Arc> = self .services .iter() .filter(|svc| { diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs index 216346d..9bdb3e1 100644 --- a/src/registry/service_item.rs +++ b/src/registry/service_item.rs @@ -5,7 +5,7 @@ pub struct ServiceItem { pub name: String, pub node: Arc, pub local: bool, - full_name: String, + pub full_name: String, version: String, actions: ActionsMap, /* @@ -15,7 +15,7 @@ pub struct ServiceItem { */ } impl ServiceItem { - pub fn new(node: Arc, service: Arc, local: bool) -> Self { + pub fn new(node: Arc, service: &Service, local: bool) -> Self { Self { node, local, diff --git a/src/service.rs b/src/service.rs index ece0895..ecd8982 100644 --- a/src/service.rs +++ b/src/service.rs @@ -14,8 +14,8 @@ pub struct Service { schema: Schema, original_schema: Option, metadata: HashMap, - actions: HashMap, - events: HashMap, + pub actions: Option>, + pub events: Option>, } #[derive(PartialEq, Eq, Clone)] struct Schema { @@ -33,7 +33,10 @@ struct Schema { struct SchemaMixins {} #[derive(PartialEq, Eq, Clone)] -struct SchemaActions {} +pub struct SchemaActions { + name:String, + handler:fn() +} #[derive(PartialEq, Eq, Clone)] struct SchemaEvents {} diff --git a/src/strategies/mod.rs b/src/strategies/mod.rs index 4b7b873..6e71fa7 100644 --- a/src/strategies/mod.rs +++ b/src/strategies/mod.rs @@ -1,6 +1,7 @@ use std::sync::Arc; -use crate::registry::{ActionEndpoint, ServiceBroker, Registry , Opts}; +use crate::registry::{ActionEndpoint, Registry , Opts}; +use crate::ServiceBroker; mod round_robin; From 0be6872bd21fd2567a36881a2bb7861c7a9fa310 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Fri, 4 Feb 2022 00:44:37 +0530 Subject: [PATCH 13/16] service lifecycyle methods --- src/broker.rs | 29 ++++++-- src/registry/mod.rs | 12 +-- src/registry/registry.rs | 4 +- src/registry/service_catalog.rs | 4 +- src/registry/service_item.rs | 4 +- src/service.rs | 125 ++++++++++++++++++++++++++++---- 6 files changed, 146 insertions(+), 32 deletions(-) diff --git a/src/broker.rs b/src/broker.rs index 6950b77..9c265ef 100644 --- a/src/broker.rs +++ b/src/broker.rs @@ -1,25 +1,32 @@ use std::{ any, collections::HashMap, - sync::{mpsc::{Receiver, Sender}, Arc}, + sync::{ + mpsc::{Receiver, Sender}, + Arc, + }, }; use anyhow::{bail, Error, Result}; use chrono::{DateTime, Utc}; -use crate::{registry::{service_item::ServiceItem, Logger}, service, Registry, Service}; +use crate::{ + registry::{service_item::ServiceItem, Logger}, + service::{self, ServiceSpec}, + Registry, Service, +}; pub struct ServiceBroker { reciever: Receiver, started: bool, namespace: Option, metdata: HashMap, - pub node_id: String, + pub node_id: String, instance: String, services: Vec, - pub transit : Option, - pub logger : Arc, + pub transit: Option, + pub logger: Arc, /* local bus options @@ -36,7 +43,7 @@ pub struct ServiceBroker { registry: Registry, } -pub struct Transit{} +pub struct Transit {} impl ServiceBroker { fn start(&mut self) { @@ -47,7 +54,7 @@ impl ServiceBroker { fn add_local_service(&mut self, service: Service) { self.services.push(service); } - fn register_local_service(&mut self, service: Service) { + fn register_local_service(&mut self, service: ServiceSpec) { self.registry.register_local_service(service); } @@ -94,7 +101,13 @@ impl ServiceBroker { } pub enum ServiceBrokerMessage { - + AddLocalService(Service), + RegisterLocalService(ServiceSpec), + WaitForServices { + dependencies: Vec, + timeout: i64, + interval: i64, + }, } fn remove_from_list(list: &mut Vec, value: &T) { diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 3977e18..cbf6ba6 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -48,7 +48,7 @@ pub struct Action { pub name: String, visibility: Visibility, handler: fn(), - service: Option, + // service: Option, } impl Action { @@ -57,13 +57,13 @@ impl Action { name, visibility: Visibility::Protected, handler, - service: None, + // service: None, } } - pub fn set_service(mut self, service: Service) -> Action { - self.service = Some(service); - self - } + // pub fn set_service(mut self, service: Service) -> Action { + // self.service = Some(service); + // self + // } } #[derive(PartialEq, Eq, Clone)] diff --git a/src/registry/registry.rs b/src/registry/registry.rs index aa65ca6..281d217 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,4 +1,4 @@ -use crate::{ServiceBrokerMessage, service::SchemaActions, ServiceBroker}; +use crate::{ServiceBrokerMessage, service::{SchemaActions, ServiceSpec}, ServiceBroker}; use super::*; use serde_json::Value; @@ -40,7 +40,7 @@ impl Registry { fn update_metrics(&self) { todo!("update metrics") } - pub fn register_local_service(&mut self, svc: Service) { + pub fn register_local_service(&mut self, svc: ServiceSpec) { if !self .services .has(&svc.full_name, Some(&self.broker.node_id)) diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 8b8e83a..2a97001 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -1,3 +1,5 @@ +use crate::service::ServiceSpec; + use super::*; use regex::Regex; #[derive(PartialEq, Eq)] @@ -12,7 +14,7 @@ impl ServiceCatalog { } } ///Add a new service - pub fn add(&mut self, node: Arc, service: &Service, local: bool) -> Arc { + pub fn add(&mut self, node: Arc, service: &ServiceSpec, local: bool) -> Arc { let service_item = ServiceItem::new(node, service, local); let service_item = Arc::new(service_item); diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs index 9bdb3e1..9e2be8f 100644 --- a/src/registry/service_item.rs +++ b/src/registry/service_item.rs @@ -1,3 +1,5 @@ +use crate::service::ServiceSpec; + use super::*; #[derive(PartialEq, Eq, Clone)] @@ -15,7 +17,7 @@ pub struct ServiceItem { */ } impl ServiceItem { - pub fn new(node: Arc, service: &Service, local: bool) -> Self { + pub fn new(node: Arc, service: &ServiceSpec, local: bool) -> Self { Self { node, local, diff --git a/src/service.rs b/src/service.rs index ecd8982..85d1d9d 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,10 +1,14 @@ use std::{collections::HashMap, sync::Arc}; +use crate::{ + registry::{Action, Event, Logger}, + ServiceBrokerMessage, +}; use chrono::Duration; +use log::info; +use tokio::sync::mpsc::Sender; -use crate::registry::{Action, Event, Logger}; - -#[derive(PartialEq, Eq, Clone)] +#[derive(Clone)] pub struct Service { pub name: String, pub full_name: String, @@ -16,7 +20,9 @@ pub struct Service { metadata: HashMap, pub actions: Option>, pub events: Option>, + broker_sender: Sender, } + #[derive(PartialEq, Eq, Clone)] struct Schema { mixins: Option>, @@ -27,6 +33,10 @@ struct Schema { version: Option, settings: HashMap, metadata: Option>, + created: Option, + started: Option, + stopped: Option, + dependencies: Option>, } #[derive(PartialEq, Eq, Clone)] @@ -34,8 +44,8 @@ struct SchemaMixins {} #[derive(PartialEq, Eq, Clone)] pub struct SchemaActions { - name:String, - handler:fn() + name: String, + handler: fn(), } #[derive(PartialEq, Eq, Clone)] @@ -45,8 +55,32 @@ enum SchemaMerged { MergedFn(fn()), MergedFnVec(Vec), } +pub struct ServiceSpec { + pub(crate) name: String, + pub(crate) version: String, + pub(crate) full_name: String, + pub(crate) settings: HashMap, + /* + pub(crate)metadata + pub(crate)*/ + pub(crate) actions: Option>, + pub(crate) events: Option>, +} impl Service { + fn get_service_spec(&self) -> ServiceSpec { + //TODO: do something about actions and events + let service_spec = ServiceSpec { + name: self.name.clone(), + full_name: self.full_name.clone(), + settings: Service::get_public_settings(&self.settings), + version: self.version.clone(), + actions: None, + events: None, + }; + service_spec + } + fn parse_service_schema(&mut self, schema: Schema) { self.original_schema = Some(schema.clone()); @@ -88,16 +122,71 @@ impl Service { todo!("add service specification") } - pub fn init(&mut self) { - todo!("call broker to initialise the service and call the init method of service") + fn get_public_settings(settings: &HashMap) -> HashMap { + settings.clone() } - pub fn start(&mut self) { - todo!("call the broker to start the services and call the start method of services") + pub async fn init(&self) { + info!("Service {} is createing....", self.full_name); + if let Some(created) = self.schema.created { + created(); + } + let _result = self + .broker_sender + .send(ServiceBrokerMessage::AddLocalService(self.clone())) + .await; + info!("Service {} created.", self.full_name); + + todo!("call broker middlware") } - pub fn stop(&mut self) { - todo!("call the broker to stop the service and call the stop method of service") + pub async fn start(&self) { + info!("Service {} is starting...", self.full_name); + + if let Some(dependencies) = &self.schema.dependencies { + let timeout: i64 = match self.settings.get("$dependencyTimeout") { + //TODO:raise an error rateher than default. + Some(val) => val.parse().unwrap_or(0), + None => 0, + }; + //TODO: get interal from broker options + let interval: i64 = match self.settings.get("$dependencyInterval") { + Some(val) => val.parse().unwrap_or(0), + None => 0, + }; + + self.wait_for_services(dependencies, timeout, interval) + .await; + } + + if let Some(started) = &self.schema.started { + started(); + } + + let _result = self + .broker_sender + .send(ServiceBrokerMessage::RegisterLocalService( + Service::get_service_spec(&self), + )) + .await; + + info!("Service {} started.", self.full_name); + + todo!("call service starting middleware"); + todo!("call service started middleware") + } + + pub async fn stop(&self) { + info!("Service {} is stopping...", self.full_name); + + if let Some(stopped) = self.schema.stopped { + stopped(); + } + + info!("Service {} stopped.", self.full_name); + + todo!("call service stopping middlewares"); + todo!("call service stopped middleware"); } fn create_action(&self, action_def: fn(), name: &str) -> Action { @@ -111,7 +200,8 @@ impl Service { } //TODO add caching settings from settins //TODO better way to handle this instead of clone. - action = action.set_service(self.clone()); + //TODO see if it is even necessary to give action access to the service. + // action = action.set_service(self.clone()); action } @@ -125,8 +215,15 @@ impl Service { todo!() } - fn wait_for_services(&self, service_names: Vec, timout: Duration, interval: Duration) { - todo!("call broker to wait for services") + async fn wait_for_services(&self, service_names: &Vec, timeout: i64, interval: i64) { + let _result = self + .broker_sender + .send(ServiceBrokerMessage::WaitForServices { + dependencies: service_names.clone(), + interval, + timeout, + }) + .await; } fn get_versioned_full_name(name: &str, version: Option<&String>) -> String { From c2d5fc695371a476fb08754799236932ebaf4a3a Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Fri, 4 Feb 2022 10:20:41 +0530 Subject: [PATCH 14/16] service tests --- makefile | 4 + src/broker.rs | 13 +- src/logger.rs | 1 - src/packet.rs | 1 - src/registry/mod.rs | 6 +- src/registry/registry.rs | 63 +++++--- src/service.rs | 311 ++++++++++++++++++++++++++++++++++----- src/strategies/mod.rs | 2 +- 8 files changed, 331 insertions(+), 70 deletions(-) create mode 100644 makefile diff --git a/makefile b/makefile new file mode 100644 index 0000000..d7ea6f4 --- /dev/null +++ b/makefile @@ -0,0 +1,4 @@ +#Run library test while suppressing the warnings +test: + RUSTFLAGS=-Awarnings cargo test --lib -- --nocapture +.PHONY: test \ No newline at end of file diff --git a/src/broker.rs b/src/broker.rs index 9c265ef..9d8d1e2 100644 --- a/src/broker.rs +++ b/src/broker.rs @@ -1,19 +1,18 @@ use std::{ - any, collections::HashMap, sync::{ - mpsc::{Receiver, Sender}, + mpsc::{Receiver, }, Arc, }, }; -use anyhow::{bail, Error, Result}; +use anyhow::{bail, Result}; -use chrono::{DateTime, Utc}; +use chrono:: Utc; use crate::{ - registry::{service_item::ServiceItem, Logger}, - service::{self, ServiceSpec}, + registry:: Logger, + service::ServiceSpec, Registry, Service, }; @@ -99,7 +98,7 @@ impl ServiceBroker { }) } } - +#[derive(PartialEq ,Debug)] pub enum ServiceBrokerMessage { AddLocalService(Service), RegisterLocalService(ServiceSpec), diff --git a/src/logger.rs b/src/logger.rs index 5ae7983..993ea22 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,4 +1,3 @@ -use log::{debug, error, info, log_enabled, Level}; trait LoggerTrait { fn init(); diff --git a/src/packet.rs b/src/packet.rs index a0d7749..74bfdaf 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,4 +1,3 @@ -use core::fmt; enum PacketType { Unknown, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index cbf6ba6..6e7dd8c 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -43,7 +43,7 @@ pub struct Logger {} trait FnType {} -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone , Debug)] pub struct Action { pub name: String, visibility: Visibility, @@ -66,14 +66,14 @@ impl Action { // } } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone , Debug)] enum Visibility { Published, Public, Protected, Private, } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone ,Debug)] pub struct Event {} impl FnType for Event {} diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 281d217..7b1b0f5 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,4 +1,7 @@ -use crate::{ServiceBrokerMessage, service::{SchemaActions, ServiceSpec}, ServiceBroker}; +use crate::{ + service::{SchemaActions, ServiceSpec}, + ServiceBroker, ServiceBrokerMessage, +}; use super::*; use serde_json::Value; @@ -11,7 +14,6 @@ pub struct Registry { nodes: NodeCatalog, services: ServiceCatalog, actions: ActionCatalog, - /* metrics strategy factor @@ -21,10 +23,20 @@ pub struct Registry { */ } impl Registry { - pub fn new(broker: Arc) -> Self { + pub fn new(broker: Arc, broker_sender: Sender) -> Self { let logger = &broker.logger; let logger = Arc::clone(&logger); - todo!() + let nodes = NodeCatalog::new(); + let services = ServiceCatalog::new(); + let actions = ActionCatalog::new(); + Registry { + logger, + broker_sender, + broker, + nodes, + services, + actions, + } } fn init() { @@ -52,7 +64,7 @@ impl Registry { ); if let Some(actions) = svc.actions { let local_node = Arc::clone(&self.nodes.local_node.as_ref().unwrap()); - self.register_actions(local_node , Arc::clone(&service) , actions); + self.register_actions(local_node, Arc::clone(&service), actions); } if let Some(events) = svc.events { self.register_events(); @@ -72,16 +84,19 @@ impl Registry { _ => false, } } - fn register_actions(&mut self , node : Arc , service: Arc , actions : Vec) { - actions.iter().for_each(|action|{ - if !Registry::check_action_visibility(action, &node){ + fn register_actions( + &mut self, + node: Arc, + service: Arc, + actions: Vec, + ) { + actions.iter().for_each(|action| { + if !Registry::check_action_visibility(action, &node) { return; } - if node.local{ + if node.local { //TODO:stuff with middleware and handlers. - - - }else if let Some(_) = self.broker.transit { + } else if let Some(_) = self.broker.transit { //TODO: for remote services return; } @@ -124,7 +139,9 @@ impl Registry { self.regenerate_local_raw_info(Some(true)); } } - None => {self.regenerate_local_raw_info(Some(true));}, + None => { + self.regenerate_local_raw_info(Some(true)); + } } } fn unregister_service_by_node_id(&mut self, node_id: &str) { @@ -141,19 +158,19 @@ impl Registry { todo!() } - fn regenerate_local_raw_info(&self, incSeq: Option)->Value { + fn regenerate_local_raw_info(&self, incSeq: Option) -> Value { todo!() } - fn get_local_node_info(&self, force: bool)->Value { - if let None = self.nodes.local_node{ + fn get_local_node_info(&self, force: bool) -> Value { + if let None = self.nodes.local_node { return self.regenerate_local_raw_info(None); } if force { return self.regenerate_local_raw_info(None); } - let value = self.nodes.local_node.as_ref().unwrap().raw_info.to_owned(); - value.unwrap() + let value = self.nodes.local_node.as_ref().unwrap().raw_info.to_owned(); + value.unwrap() } fn get_node_info(&self, node_id: &str) -> Option { todo!() @@ -161,13 +178,13 @@ impl Registry { fn process_node_info(&self) { todo!() } - pub fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { + pub fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { self.nodes.list(only_available, with_services) } - pub fn get_services_list(&self, opts: ListOptions) -> Vec<&Arc> { + pub fn get_services_list(&self, opts: ListOptions) -> Vec<&Arc> { self.services.list(opts) } - fn get_actions_list(&self , opts:ListOptions) -> Vec<&ActionEndpoint> { + fn get_actions_list(&self, opts: ListOptions) -> Vec<&ActionEndpoint> { //self.actions.list(opts) todo!() } @@ -178,3 +195,7 @@ impl Registry { todo!() } } +#[cfg(test)] +mod tests { + +} diff --git a/src/service.rs b/src/service.rs index 85d1d9d..dd0649e 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,35 +1,47 @@ -use std::{collections::HashMap, sync::Arc}; +use std::collections::HashMap; use crate::{ - registry::{Action, Event, Logger}, + registry::{Action, Event}, ServiceBrokerMessage, }; -use chrono::Duration; use log::info; -use tokio::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Service { pub name: String, pub full_name: String, pub version: String, settings: HashMap, - logger: Arc, schema: Schema, original_schema: Option, metadata: HashMap, pub actions: Option>, pub events: Option>, - broker_sender: Sender, + broker_sender: UnboundedSender, } -#[derive(PartialEq, Eq, Clone)] +impl PartialEq for Service { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + && self.full_name == other.full_name + && self.version == other.version + && self.settings == other.settings + && self.schema == other.schema + && self.original_schema == other.original_schema + && self.metadata == other.metadata + && self.actions == other.actions + && self.events == other.events + } +} + +#[derive(PartialEq, Eq, Clone, Debug)] struct Schema { mixins: Option>, actions: Option>, events: Option>, merged: SchemaMerged, - name: Option, + name: String, version: Option, settings: HashMap, metadata: Option>, @@ -39,27 +51,28 @@ struct Schema { dependencies: Option>, } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] struct SchemaMixins {} -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct SchemaActions { name: String, handler: fn(), } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] struct SchemaEvents {} -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] enum SchemaMerged { MergedFn(fn()), MergedFnVec(Vec), } +#[derive(PartialEq, Debug)] pub struct ServiceSpec { pub(crate) name: String, pub(crate) version: String, pub(crate) full_name: String, - pub(crate) settings: HashMap, + settings: HashMap, /* pub(crate)metadata pub(crate)*/ @@ -73,7 +86,7 @@ impl Service { let service_spec = ServiceSpec { name: self.name.clone(), full_name: self.full_name.clone(), - settings: Service::get_public_settings(&self.settings), + settings: self.get_public_settings(), version: self.version.clone(), actions: None, events: None, @@ -85,21 +98,15 @@ impl Service { self.original_schema = Some(schema.clone()); match schema.merged { - SchemaMerged::MergedFn(func) => { - - //TODO research about functions - } + SchemaMerged::MergedFn(merged) => merged(), SchemaMerged::MergedFnVec(func_vec) => { for func in func_vec { - //TODO resarch more about functions + func() } } } - if let None = schema.name { - //TODO throw error if no name available - } - self.name = schema.name.unwrap().clone(); + self.name = schema.name; self.version = match schema.version { Some(v) => v, None => "0.0.1".to_string(), @@ -122,8 +129,8 @@ impl Service { todo!("add service specification") } - fn get_public_settings(settings: &HashMap) -> HashMap { - settings.clone() + fn get_public_settings(&self) -> HashMap { + self.settings.clone() } pub async fn init(&self) { @@ -133,11 +140,10 @@ impl Service { } let _result = self .broker_sender - .send(ServiceBrokerMessage::AddLocalService(self.clone())) - .await; + .send(ServiceBrokerMessage::AddLocalService(self.clone())); info!("Service {} created.", self.full_name); - todo!("call broker middlware") + // todo!("call broker middlware") } pub async fn start(&self) { @@ -167,13 +173,12 @@ impl Service { .broker_sender .send(ServiceBrokerMessage::RegisterLocalService( Service::get_service_spec(&self), - )) - .await; + )); info!("Service {} started.", self.full_name); - todo!("call service starting middleware"); - todo!("call service started middleware") + // todo!("call service starting middleware"); + //todo!("call service started middleware") } pub async fn stop(&self) { @@ -194,7 +199,7 @@ impl Service { let name_prefix = self.settings.get("$noServiceNamePrefix"); if let Some(name_prefix) = name_prefix { let name_prefix: bool = name_prefix.parse().unwrap(); - if name_prefix { + if !name_prefix { action.name = format!("{}.{}", self.full_name.to_string(), action.name); } } @@ -222,8 +227,7 @@ impl Service { dependencies: service_names.clone(), interval, timeout, - }) - .await; + }); } fn get_versioned_full_name(name: &str, version: Option<&String>) -> String { @@ -234,3 +238,238 @@ impl Service { name } } +#[cfg(test)] +mod tests { + use tokio::sync::mpsc::{self, UnboundedSender}; + + use super::*; + fn test_merge_func() { + println!("test merge function"); + } + fn test_started_func() { + println!("test start func"); + } + fn test_created_func() { + println!("test created func"); + } + fn test_stop_func() { + println!("test stop func"); + } + fn action_func() { + println!("action_func"); + } + + fn get_test_schema(dependencies: Option>) -> Schema { + let merged = SchemaMerged::MergedFn(test_merge_func); + let schema = Schema { + mixins: None, + actions: None, + events: None, + merged, + name: "test_service".to_string(), + version: None, + settings: HashMap::new(), + metadata: None, + created: Some(test_created_func), + started: Some(test_started_func), + stopped: Some(test_stop_func), + dependencies: dependencies, + }; + + schema + } + + fn get_test_service( + schema: Option, + settings: Option>, + actions: Option>, + broker_sender: Option>, + ) -> Service { + let name = "test_service".to_string(); + let version = "1.0".to_string(); + let full_name = Service::get_versioned_full_name(&name, Some(&version)); + let settings = match settings { + Some(settings) => settings, + None => HashMap::new(), + }; + let schema = match schema { + Some(schema) => schema, + None => get_test_schema(None), + }; + + let original_schema = get_test_schema(None); + let broker_sender = match broker_sender { + Some(sender) => sender, + None => { + let (sender, recv) = mpsc::unbounded_channel::(); + sender + } + }; + let service = Service { + name, + full_name, + version, + settings, + schema, + original_schema: Some(original_schema), + metadata: HashMap::new(), + actions: actions, + events: None, + broker_sender, + }; + service + } + #[test] + fn service_get_service_spec() { + let service = get_test_service(None, None, None, None); + let service_spec = ServiceSpec { + name: service.name.clone(), + version: service.version.clone(), + full_name: service.full_name.clone(), + settings: service.settings.clone(), + actions: None, + events: None, + }; + + let service_spec_gen = service.get_service_spec(); + assert_eq!(service_spec_gen, service_spec) + } + #[test] + fn service_get_public_settings() { + let mut settings = HashMap::new(); + settings.insert("test".to_string(), "settings".to_string()); + let service = get_test_service(None, Some(settings.clone()), None, None); + assert_eq!(service.get_public_settings(), settings); + } + #[test] + fn service_init() { + let (sender, mut recv) = mpsc::unbounded_channel::(); + let service = get_test_service(None, None, None, Some(sender)); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + rt.block_on(async { service.init().await }); + rt.block_on(async { + let result = recv.recv().await; + + let expected_result = ServiceBrokerMessage::AddLocalService(service); + assert_eq!(result, Some(expected_result)); + }); + } + #[test] + fn service_start() { + let (sender, mut recv) = mpsc::unbounded_channel::(); + let service = get_test_service(None, None, None, Some(sender)); + let service_spec = service.get_service_spec(); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + rt.block_on(async { service.start().await }); + rt.block_on(async { + let result = recv.recv().await; + let expected_result = ServiceBrokerMessage::RegisterLocalService(service_spec); + assert_eq!(result, Some(expected_result)); + }); + } + #[test] + fn service_start_with_dependencies() { + let (sender, mut recv) = mpsc::unbounded_channel::(); + let service_names: Vec = + vec!["Service one".to_string(), " Service two".to_string()]; + + let schema = get_test_schema(Some(service_names.clone())); + let service = get_test_service(Some(schema), None, None, Some(sender)); + let service_spec = service.get_service_spec(); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + rt.block_on(async { service.start().await }); + rt.block_on(async { + let result = recv.recv().await; + let expected_result = ServiceBrokerMessage::WaitForServices { + dependencies: service_names, + timeout: 0, + interval: 0, + }; + assert_eq!(result, Some(expected_result)); + + let result = recv.recv().await; + let expected_result = ServiceBrokerMessage::RegisterLocalService(service_spec); + assert_eq!(result, Some(expected_result)); + }); + } + #[test] + fn service_create_action_name() { + let no_service_name_prefix = "$noServiceNamePrefix".to_string(); + let name = "action_func"; + let mut settings = HashMap::new(); + settings.insert(no_service_name_prefix.clone(), "true".to_string()); + let service = get_test_service(None, Some(settings.clone()), None, None); + let action = service.create_action(action_func, name); + let expected_action = Action::new(name.to_string(), action_func); + assert_eq!(action, expected_action); + settings.insert(no_service_name_prefix.clone(), "false".to_string()); + let service = get_test_service(None, Some(settings), None, None); + let action_2 = service.create_action(action_func, name); + let name = format!("{}.{}", service.full_name, name); + let expected_action_2 = Action::new(name, action_func); + assert_eq!(action_2, expected_action_2); + let service = get_test_service(None, None, None, None); + let name = "action_func"; + let expected_action_3 = Action::new(name.to_string(), action_func); + let action_3 = service.create_action(action_func, name); + assert_eq!(action_3, expected_action_3); + } + #[test] + #[should_panic] + fn service_create_action_name_panic() { + let no_service_name_prefix = "$noServiceNamePrefix".to_string(); + let mut settings = HashMap::new(); + let name = "action_func"; + settings.insert(no_service_name_prefix, "non_bool_value".to_string()); + let service = get_test_service(None, Some(settings), None, None); + let action = service.create_action(action_func, name); + } + #[test] + fn service_wait_for_service() { + let (sender, mut recv) = mpsc::unbounded_channel::(); + let service = get_test_service(None, None, None, Some(sender)); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let service_names: Vec = + vec!["Service one".to_string(), " Service two".to_string()]; + let timeout = 10; + let interval = 20; + rt.block_on(async { + let _result = service + .wait_for_services(&service_names, timeout, interval) + .await; + }); + rt.block_on(async { + let result = recv.recv().await; + let expected_result = ServiceBrokerMessage::WaitForServices { + dependencies: service_names, + timeout, + interval, + }; + assert_eq!(result, Some(expected_result)); + }); + } + #[test] + fn service_get_versioned_full_name() { + let version = "1.0"; + let name = "test_service"; + let expected_full_name = format!("{}.{}", version, name); + let version = "1.0".to_string(); + let version = Some(&version); + let full_name = Service::get_versioned_full_name(name, version); + assert_eq!(full_name , expected_full_name); + let full_name_2 = Service::get_versioned_full_name(name, None); + assert_eq!(full_name_2 , name); + } +} diff --git a/src/strategies/mod.rs b/src/strategies/mod.rs index 6e71fa7..deb40c0 100644 --- a/src/strategies/mod.rs +++ b/src/strategies/mod.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::registry::{ActionEndpoint, Registry , Opts}; +use crate::registry::{ActionEndpoint, Registry , }; use crate::ServiceBroker; mod round_robin; From d39d5d3b20825e1e0ae8b843ace67b7b701265d7 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Sat, 5 Feb 2022 09:41:33 +0530 Subject: [PATCH 15/16] feat: private action ep --- Cargo.lock | 56 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 ++- src/registry/registry.rs | 44 +++++++++++++++++++++---------- src/service.rs | 1 - 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d62240c..edf474a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + [[package]] name = "env_logger" version = "0.9.0" @@ -172,11 +191,13 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "derive_more", "env_logger", "lazy_static", "log", "regex", "serde_json", + "thiserror", "tokio", ] @@ -299,6 +320,15 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "ryu" version = "1.0.9" @@ -311,6 +341,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" + [[package]] name = "serde" version = "1.0.136" @@ -363,6 +399,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.1.44" diff --git a/Cargo.toml b/Cargo.toml index 66202d2..b81d0a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,6 @@ serde_json = "1.0.0" anyhow = "1.0.53" tokio = { version = "1.16.1", features = ["full"] } regex = "1.5.4" -lazy_static = "1.3.0" \ No newline at end of file +lazy_static = "1.3.0" +derive_more = "0.99.17" +thiserror = "1.0" \ No newline at end of file diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 7b1b0f5..9c52a3d 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,9 +1,8 @@ -use crate::{ - service::{SchemaActions, ServiceSpec}, - ServiceBroker, ServiceBrokerMessage, -}; +use crate::{service::ServiceSpec, ServiceBroker, ServiceBrokerMessage}; +use derive_more::Display; use super::*; +use anyhow::{bail, Error}; use serde_json::Value; use tokio::sync::mpsc::Sender; @@ -107,8 +106,15 @@ impl Registry { //add the action to the service. }); } - fn create_private_action_endpoint(action: Action) { - todo!() + fn create_private_action_endpoint(&self, action: Action) -> anyhow::Result { + let local_node = match &self.nodes.local_node { + Some(node) => node, + None => bail!("No local node available"), + }; + let node = Arc::clone(local_node); + todo!("add service to action") + // let action_ep = ActionEndpoint::new(node, service, action); + // Ok(action_ep) } pub fn has_services(&self, full_name: &str, node_id: Option<&str>) -> bool { self.services.has(full_name, node_id) @@ -162,15 +168,21 @@ impl Registry { todo!() } - fn get_local_node_info(&self, force: bool) -> Value { + fn get_local_node_info(&self, force: bool) -> Result { if let None = self.nodes.local_node { - return self.regenerate_local_raw_info(None); + return Ok(self.regenerate_local_raw_info(None)); } if force { - return self.regenerate_local_raw_info(None); + return Ok(self.regenerate_local_raw_info(None)); + } + if let None = self.nodes.local_node { + return Err(RegistryError::NoLocalNodeFound); } let value = self.nodes.local_node.as_ref().unwrap().raw_info.to_owned(); - value.unwrap() + match value { + Some(value) => Ok(value), + None => Err(RegistryError::NoLocalNodeFound), + } } fn get_node_info(&self, node_id: &str) -> Option { todo!() @@ -195,7 +207,13 @@ impl Registry { todo!() } } -#[cfg(test)] -mod tests { - +use thiserror::Error; +#[derive(Error, Debug)] +enum RegistryError { + #[error("No local node found")] + NoLocalNodeFound, } + +#[cfg(test)] + +mod tests {} diff --git a/src/service.rs b/src/service.rs index dd0649e..c7dfda6 100644 --- a/src/service.rs +++ b/src/service.rs @@ -204,7 +204,6 @@ impl Service { } } //TODO add caching settings from settins - //TODO better way to handle this instead of clone. //TODO see if it is even necessary to give action access to the service. // action = action.set_service(self.clone()); action From 1fe5dca74aa133ffe9dffafa5d7787aca5ff13f8 Mon Sep 17 00:00:00 2001 From: Ramyak Mehra Date: Sun, 13 Feb 2022 16:32:13 +0530 Subject: [PATCH 16/16] refactor: registry refactores --- src/registry/action_catalog.rs | 2 +- src/registry/action_endpoint.rs | 17 ++++---- src/registry/endpoint_list.rs | 8 ++-- src/registry/event_endpoint.rs | 15 +++---- src/registry/mod.rs | 38 ++++++++--------- src/registry/node.rs | 2 +- src/registry/node_catalog.rs | 33 ++++++++++----- src/registry/registry.rs | 72 +++++++++++++++------------------ src/registry/service_catalog.rs | 65 +++++++++++++++-------------- src/registry/service_item.rs | 11 +++-- 10 files changed, 135 insertions(+), 128 deletions(-) diff --git a/src/registry/action_catalog.rs b/src/registry/action_catalog.rs index 3675d77..3916de4 100644 --- a/src/registry/action_catalog.rs +++ b/src/registry/action_catalog.rs @@ -13,7 +13,7 @@ impl ActionCatalog { actions: HashMap::new(), } } - pub fn add(&mut self, node: Arc, service: Arc, action: Action) { + pub fn add(&mut self, node: &Node, service: &ServiceItem, action: Action) { let list = self.actions.get_mut(&action.name); match list { Some(list) => list.add(node, service, action), diff --git a/src/registry/action_endpoint.rs b/src/registry/action_endpoint.rs index 948ba8c..94914bc 100644 --- a/src/registry/action_endpoint.rs +++ b/src/registry/action_endpoint.rs @@ -12,9 +12,9 @@ impl EndpointTrait for ActionEndpoint { fn update(&mut self, data: Self::Data) { self.action = data; } - fn new(node: Arc, service: Arc, data: Self::Data) -> Self { - let endpoint = Endpoint::new(node, service); - let name = format!("{}:{}", endpoint.id, data.name); + fn new(node_id: &str, service: &ServiceItem, data: Self::Data) -> Self { + let endpoint = Endpoint::new(node_id, service); + let name = format!("{}:{}", endpoint.node_id, data.name); Self { endpoint, name, @@ -22,13 +22,10 @@ impl EndpointTrait for ActionEndpoint { } } - fn node(&self) -> &Node { - &self.endpoint.node + fn node(&self) -> &str { + &self.endpoint.node_id } - fn service(&self) -> &ServiceItem { - &self.endpoint.service - } fn is_local(&self) -> bool { self.endpoint.local } @@ -36,9 +33,9 @@ impl EndpointTrait for ActionEndpoint { self.endpoint.state } fn id(&self) -> &str { - &self.endpoint.id + &self.endpoint.node_id } fn service_name(&self) -> &str { - &self.endpoint.service.name + &self.endpoint.service } } diff --git a/src/registry/endpoint_list.rs b/src/registry/endpoint_list.rs index f0d2715..1e9ce27 100644 --- a/src/registry/endpoint_list.rs +++ b/src/registry/endpoint_list.rs @@ -25,11 +25,11 @@ impl EndpointList { } } - pub fn add(&mut self, node: Arc, service: Arc, data: T::Data) { + pub fn add(&mut self, node: &Node, service:&ServiceItem, data: T::Data) { let entry = self .endpoints .iter_mut() - .find(|x| x.node() == &*node && x.service().name == service.name); + .find(|x| x.service_name() == service.unique_name()); match entry { Some(found) => { @@ -39,7 +39,7 @@ impl EndpointList { None => {} } - let ep = T::new(Arc::clone(&node), Arc::clone(&service), data); + let ep = T::new(&node.id, service, data); self.endpoints.push(ep.clone()); if ep.is_local() { @@ -101,7 +101,7 @@ impl EndpointList { } pub fn remove_by_service(&mut self, service: &ServiceItem) { self.endpoints.retain(|ep| { - let delete = ep.service() == service; + let delete = ep.service_name() == service.unique_name(); !delete }); self.update_local_endpoints(); diff --git a/src/registry/event_endpoint.rs b/src/registry/event_endpoint.rs index d8cd7d6..a96101a 100644 --- a/src/registry/event_endpoint.rs +++ b/src/registry/event_endpoint.rs @@ -11,8 +11,8 @@ impl EndpointTrait for EventEndpoint { fn update(&mut self, data: Self::Data) { self.event = data; } - fn new(node: Arc, service: Arc, data: Self::Data) -> Self { - let endpoint = Endpoint::new(node, service); + fn new(node_id: &str, service: &ServiceItem, data: Self::Data) -> Self { + let endpoint = Endpoint::new(node_id, service); Self { endpoint, @@ -20,13 +20,10 @@ impl EndpointTrait for EventEndpoint { } } - fn node(&self) -> &Node { - &self.endpoint.node + fn node(&self) -> &str { + &self.endpoint.node_id } - fn service(&self) -> &ServiceItem { - &self.endpoint.service - } fn is_local(&self) -> bool { self.endpoint.local } @@ -34,9 +31,9 @@ impl EndpointTrait for EventEndpoint { self.endpoint.state } fn id(&self) -> &str { - &self.endpoint.id + &self.endpoint.node_id } fn service_name(&self) -> &str { - &self.endpoint.service.name + &self.endpoint.service } } diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 6e7dd8c..40b7ec6 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -17,33 +17,30 @@ use action_catalog::ActionCatalog; pub use action_endpoint::ActionEndpoint; pub use endpoint_list::EndpointList; pub use event_endpoint::EventEndpoint; +use lazy_static::lazy_static; pub use node::{Client, Node}; use node_catalog::NodeCatalog; use regex::Regex; pub use registry::Registry; use service_catalog::ServiceCatalog; use service_item::ServiceItem; -use lazy_static::lazy_static; // pub use event_endpoint::EventEndpoint; - type ActionsMap = HashMap>; fn get_internal_service_regex_match(text: &str) -> bool { lazy_static! { - static ref RE: Regex = Regex::new(r"^\$").unwrap(); - + static ref RE: Regex = Regex::new(r"^\$").unwrap(); } RE.is_match(text) } - #[derive(PartialEq, Eq)] pub struct Logger {} trait FnType {} -#[derive(PartialEq, Eq, Clone , Debug)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct Action { pub name: String, visibility: Visibility, @@ -66,14 +63,14 @@ impl Action { // } } -#[derive(PartialEq, Eq, Clone , Debug)] +#[derive(PartialEq, Eq, Clone, Debug)] enum Visibility { Published, Public, Protected, Private, } -#[derive(PartialEq, Eq, Clone ,Debug)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct Event {} impl FnType for Event {} @@ -81,9 +78,8 @@ impl FnType for Event {} pub trait EndpointTrait { ///Data is eiter an Action struct or Event structs type Data; - fn new(node: Arc, service: Arc, data: Self::Data) -> Self; - fn node(&self) -> &Node; - fn service(&self) -> &ServiceItem; + fn new(node_id: &str, service: &ServiceItem, data: Self::Data) -> Self; + fn node(&self) -> &str; fn update(&mut self, data: Self::Data); fn is_local(&self) -> bool; fn is_available(&self) -> bool; @@ -93,22 +89,20 @@ pub trait EndpointTrait { #[derive(PartialEq, Eq, Clone)] struct Endpoint { - node: Arc, - service: Arc, + service: String, state: bool, - id: String, + node_id: String, local: bool, } impl Endpoint { - fn new(node: Arc, service: Arc) -> Self { - let id = node.id.to_string(); + fn new(node_id: &str, service: &ServiceItem) -> Self { let local = service.local; + let service = service.unique_name(); Self { - node, service, state: true, - id: id, + node_id: node_id.to_string(), local, } } @@ -131,3 +125,11 @@ pub struct ListOptions { with_events: bool, grouping: bool, } +use thiserror::Error; +#[derive(Error, Debug)] +enum RegistryError { + #[error("No local node found")] + NoLocalNodeFound, + #[error("No service found")] + NoServiceItemFound, +} diff --git a/src/registry/node.rs b/src/registry/node.rs index 8fdc6ad..5a4c090 100644 --- a/src/registry/node.rs +++ b/src/registry/node.rs @@ -27,7 +27,7 @@ pub struct Node { cpu cpuseq */ - pub services: Vec>, + pub services: Vec, pub seq: usize, offline_since: Option, } diff --git a/src/registry/node_catalog.rs b/src/registry/node_catalog.rs index be80799..9768ae4 100644 --- a/src/registry/node_catalog.rs +++ b/src/registry/node_catalog.rs @@ -2,22 +2,26 @@ use std::{collections::HashMap, net::IpAddr, sync::Arc}; use std::sync::RwLock; -use super::{node, Client, Logger, Node, Registry}; +use anyhow::bail; + +use crate::registry::RegistryError; +use super::{node, Client, Logger, Node, Registry}; pub struct NodeCatalog { nodes: HashMap, - pub local_node: Option>, + local_node_id: String, } impl NodeCatalog { pub fn new() -> Self { + //TODO: add the create local node logic here Self { nodes: HashMap::new(), - local_node: None, + local_node_id: "".to_string(), } } ///Create a local node - fn create_local_node(&mut self, version: String, node_id: String, instance_id: String) -> Arc { + fn create_local_node(&mut self, version: String, node_id: String, instance_id: String) { let client = Client { client_type: "rust".to_string(), lang_version: "1.56.1".to_string(), @@ -30,12 +34,9 @@ impl NodeCatalog { .set_hostname(get_hostname()) .set_seq(1) .set_client(client); - + //TODO:data constency between local node and node catalog self.nodes.insert(node.id.to_string(), node.clone()); - let node = Arc::new(node); - let node_c = Arc::clone(&node); - self.local_node = Some(node); - return node_c; + self.local_node_id = node.id; todo!() /* node.metadata = self.broker.metadata.clone() @@ -53,6 +54,19 @@ impl NodeCatalog { pub fn get_node(&self, id: &str) -> Option<&Node> { self.nodes.get(id) } + pub fn local_node(&self) -> anyhow::Result<&Node> { + match self.nodes.get(&self.local_node_id) { + Some(node) => Ok(node), + None => bail!(RegistryError::NoLocalNodeFound), + } + } + pub fn local_node_mut(&mut self) -> anyhow::Result<&mut Node> { + match self.nodes.get_mut(&self.local_node_id) { + Some(node) => Ok(node), + None => bail!(RegistryError::NoLocalNodeFound), + } + } + pub fn get_node_mut(&mut self, id: &str) -> Option<&mut Node> { self.nodes.get_mut(id) } @@ -120,4 +134,3 @@ fn get_ip_list() -> Vec { fn get_hostname() -> String { todo!() } - diff --git a/src/registry/registry.rs b/src/registry/registry.rs index 9c52a3d..19c11ac 100644 --- a/src/registry/registry.rs +++ b/src/registry/registry.rs @@ -1,5 +1,4 @@ use crate::{service::ServiceSpec, ServiceBroker, ServiceBrokerMessage}; -use derive_more::Display; use super::*; use anyhow::{bail, Error}; @@ -51,31 +50,33 @@ impl Registry { fn update_metrics(&self) { todo!("update metrics") } - pub fn register_local_service(&mut self, svc: ServiceSpec) { + pub fn register_local_service(&mut self, svc: ServiceSpec) -> anyhow::Result<()> { if !self .services .has(&svc.full_name, Some(&self.broker.node_id)) { - let service = self.services.add( - Arc::clone(&self.nodes.local_node.as_ref().unwrap()), - &svc, - true, - ); + let node = self.nodes.local_node()?; + + let service_full_name = self.services.add(node, &svc, true); if let Some(actions) = svc.actions { - let local_node = Arc::clone(&self.nodes.local_node.as_ref().unwrap()); - self.register_actions(local_node, Arc::clone(&service), actions); + self.register_actions(&service_full_name, actions); } if let Some(events) = svc.events { self.register_events(); } - //TODO:Add service to the local node. - //self.nodes.local_node.unwrap().services.push(Arc::clone(&service)); + + { + let local_node = self.nodes.local_node_mut()?; + + local_node.services.push(service_full_name); + } } + Ok(()) } pub fn register_services() { todo!("add remote serice support") } - fn check_action_visibility(action: &Action, node: &Arc) -> bool { + fn check_action_visibility(action: &Action, node: &Node) -> bool { match action.visibility { Visibility::Published => true, Visibility::Public => true, @@ -85,12 +86,14 @@ impl Registry { } fn register_actions( &mut self, - node: Arc, - service: Arc, + service_full_name: &str, actions: Vec, - ) { + ) -> anyhow::Result<()> { + let node = self.nodes.local_node()?; + let service = self.services.get_mut(service_full_name, Some(&node.id))?; + actions.iter().for_each(|action| { - if !Registry::check_action_visibility(action, &node) { + if !Registry::check_action_visibility(action, node) { return; } if node.local { @@ -99,19 +102,17 @@ impl Registry { //TODO: for remote services return; } - let node = Arc::clone(&node); - let service = Arc::clone(&service); + self.actions.add(node, service, action.to_owned()); //TODO: + // service.add_action(action) //add the action to the service. }); + Ok(()) } fn create_private_action_endpoint(&self, action: Action) -> anyhow::Result { - let local_node = match &self.nodes.local_node { - Some(node) => node, - None => bail!("No local node available"), - }; - let node = Arc::clone(local_node); + let node = self.nodes.local_node()?; + todo!("add service to action") // let action_ep = ActionEndpoint::new(node, service, action); // Ok(action_ep) @@ -168,20 +169,18 @@ impl Registry { todo!() } - fn get_local_node_info(&self, force: bool) -> Result { - if let None = self.nodes.local_node { - return Ok(self.regenerate_local_raw_info(None)); - } + fn get_local_node_info(&self, force: bool) -> anyhow::Result { + // if let None = self.nodes.local_node() { + // return Ok(self.regenerate_local_raw_info(None)); + // } if force { return Ok(self.regenerate_local_raw_info(None)); } - if let None = self.nodes.local_node { - return Err(RegistryError::NoLocalNodeFound); - } - let value = self.nodes.local_node.as_ref().unwrap().raw_info.to_owned(); + + let value = self.nodes.local_node()?.raw_info.to_owned(); match value { Some(value) => Ok(value), - None => Err(RegistryError::NoLocalNodeFound), + None => bail!(RegistryError::NoLocalNodeFound), } } fn get_node_info(&self, node_id: &str) -> Option { @@ -193,7 +192,7 @@ impl Registry { pub fn get_node_list(&self, only_available: bool, with_services: bool) -> Vec<&Node> { self.nodes.list(only_available, with_services) } - pub fn get_services_list(&self, opts: ListOptions) -> Vec<&Arc> { + pub fn get_services_list(&self, opts: ListOptions) -> Vec<&ServiceItem> { self.services.list(opts) } fn get_actions_list(&self, opts: ListOptions) -> Vec<&ActionEndpoint> { @@ -207,13 +206,6 @@ impl Registry { todo!() } } -use thiserror::Error; -#[derive(Error, Debug)] -enum RegistryError { - #[error("No local node found")] - NoLocalNodeFound, -} - #[cfg(test)] mod tests {} diff --git a/src/registry/service_catalog.rs b/src/registry/service_catalog.rs index 2a97001..b78b502 100644 --- a/src/registry/service_catalog.rs +++ b/src/registry/service_catalog.rs @@ -1,10 +1,11 @@ +use anyhow::bail; + use crate::service::ServiceSpec; use super::*; -use regex::Regex; #[derive(PartialEq, Eq)] pub struct ServiceCatalog { - services: Vec>, + services: Vec, } impl ServiceCatalog { @@ -14,13 +15,11 @@ impl ServiceCatalog { } } ///Add a new service - pub fn add(&mut self, node: Arc, service: &ServiceSpec, local: bool) -> Arc { + pub fn add(&mut self, node: &Node, service: &ServiceSpec, local: bool) -> String { let service_item = ServiceItem::new(node, service, local); - let service_item = Arc::new(service_item); - - let item = Arc::clone(&service_item); + let full_name = service_item.full_name.clone(); self.services.push(service_item); - item + full_name } ///Check the service exsists pub fn has(&self, full_name: &str, node_id: Option<&str>) -> bool { @@ -33,7 +32,7 @@ impl ServiceCatalog { None => false, } } - pub fn get(&self, full_name: &str, node_id: Option<&str>) -> Option<&Arc> { + pub fn get(&self, full_name: &str, node_id: Option<&str>) -> Option<&ServiceItem> { self.services .iter() .find(|svc| svc.equals(full_name, node_id)) @@ -42,42 +41,46 @@ impl ServiceCatalog { &mut self, full_name: &str, node_id: Option<&str>, - ) -> Option<&mut Arc> { - self.services + ) -> anyhow::Result<&mut ServiceItem> { + let result = self + .services .iter_mut() - .find(|svc| svc.equals(full_name, node_id)) + .find(|svc| svc.equals(full_name, node_id)); + match result { + Some(service_item) => Ok(service_item), + None => bail!(RegistryError::NoServiceItemFound), + } } - pub fn list( - &self, - opts : ListOptions - ) -> Vec<&Arc> { - - self.services.iter().filter(|svc| { - if opts.skip_internal && get_internal_service_regex_match(&svc.name) { - return false; - } - if opts.only_local && !svc.local { - return false; - } - if opts.only_available && !svc.node.available { - return false; - } + pub fn list(&self, opts: ListOptions) -> Vec<&ServiceItem> { + self.services + .iter() + .filter(|svc| { + if opts.skip_internal && get_internal_service_regex_match(&svc.name) { + return false; + } + if opts.only_local && !svc.local { + return false; + } + //TODO: find a way to get node available + // if opts.only_available && !svc.node.available { + // return false; + // } - return true; - }).collect() + return true; + }) + .collect() // TODO:("implement grouping and all that stuff") - } pub fn get_local_node_service(&self) { todo!() } //remove all endpoints by node_id. pub fn remove_all_by_node_id(&mut self, node_id: &str) { - let services: Vec<&Arc> = self + let services: Vec<&ServiceItem> = self .services .iter() .filter(|svc| { - if svc.node.id == node_id { + if svc.node == node_id { todo!("remove actions and events in registry"); return false; } diff --git a/src/registry/service_item.rs b/src/registry/service_item.rs index 9e2be8f..2b8ec14 100644 --- a/src/registry/service_item.rs +++ b/src/registry/service_item.rs @@ -5,7 +5,7 @@ use super::*; #[derive(PartialEq, Eq, Clone)] pub struct ServiceItem { pub name: String, - pub node: Arc, + pub node: String, pub local: bool, pub full_name: String, version: String, @@ -17,9 +17,9 @@ pub struct ServiceItem { */ } impl ServiceItem { - pub fn new(node: Arc, service: &ServiceSpec, local: bool) -> Self { + pub fn new(node: &Node, service: &ServiceSpec, local: bool) -> Self { Self { - node, + node: node.id.clone(), local, actions: HashMap::new(), full_name: service.full_name.to_string(), @@ -29,7 +29,7 @@ impl ServiceItem { } pub fn equals(&self, full_name: &str, node_id: Option<&str>) -> bool { match node_id { - Some(id) => self.node.id == id && self.full_name == full_name, + Some(id) => self.node == id && self.full_name == full_name, None => self.full_name == full_name, } } @@ -53,4 +53,7 @@ impl ServiceItem { pub fn add_event(&mut self, event: EndpointList) { todo!("Implement the events map") } + pub fn unique_name(&self) -> String { + format!("{}{}{}", self.full_name, self.version, self.node) + } }