From 0e8fd818c06b2b47a2c90b65609332e5d8100275 Mon Sep 17 00:00:00 2001 From: icycrystal4 Date: Fri, 15 Dec 2023 14:14:15 +0800 Subject: [PATCH] =?UTF-8?q?endpoint:=20=E7=94=9F=E6=88=90=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=97=B6=EF=BC=8C=E6=8C=89=E9=9C=80=E8=A6=81=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0R=E7=9A=84=E6=B3=9B=E5=9E=8B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- endpoint/src/topo.rs | 296 ++++++------------------------------------ procs/src/endpoint.rs | 78 ++++++++--- 2 files changed, 99 insertions(+), 275 deletions(-) diff --git a/endpoint/src/topo.rs b/endpoint/src/topo.rs index 1c70888e8..ab2023d69 100644 --- a/endpoint/src/topo.rs +++ b/endpoint/src/topo.rs @@ -10,264 +10,46 @@ pub type TopologyProtocol = Topologies; // 2. trait => where表示,为Topologies实现trait,满足where的条件. // 第一个参数必须是self,否则无法dispatcher // 3. 如果trait是pub的,则同时会创建这个trait。非pub的trait,只会为Topologies实现 -// procs::topology_dispatcher! { -// #[derive(Clone)] -// pub enum Topologies { -// MsgQue(crate::msgque::topo::MsgQue), -// RedisService(crate::redisservice::topo::RedisService), -// CacheService(crate::cacheservice::topo::CacheService), -// PhantomService(crate::phantomservice::topo::PhantomService), -// KvService(crate::kv::topo::KvService), -// UuidService(crate::uuid::topo::UuidService), -// } +procs::topology_dispatcher! { + #[derive(Clone)] + pub enum Topologies { + MsgQue(crate::msgque::topo::MsgQue), + RedisService(crate::redisservice::topo::RedisService), + CacheService(crate::cacheservice::topo::CacheService), + PhantomService(crate::phantomservice::topo::PhantomService), + KvService(crate::kv::topo::KvService), + UuidService(crate::uuid::topo::UuidService), + } + + pub trait Endpoint: Sized + Send + Sync { + type Item; + fn send(&self, req: Self::Item); + fn shard_idx(&self, _hash: i64) -> usize {todo!("shard_idx not implemented");} + fn available(&self) -> bool {todo!("available not implemented");} + fn addr(&self) -> &str {"addr not implemented"} + fn build_o(_addr: &str, _p: P, _r: Resource, _service: &str, _to: Timeout, _o: ResOption) -> Self {todo!("build not implemented")} + fn build(addr: &str, p: P, r: Resource, service: &str, to: Timeout) -> Self {Self::build_o(addr, p, r, service, to, Default::default())} + } => where P:Protocol, E:Endpoint + Inited, R: Request + + pub trait Topology : Endpoint + Hash{ + fn exp_sec(&self) -> u32 {86400} + } => where P:Protocol, E:Endpoint, R:Request, Topologies: Endpoint + + trait Inited { + fn inited(&self) -> bool; + } => where E:Inited + + trait TopologyWrite { + fn update(&mut self, name: &str, cfg: &str); + fn disgroup<'a>(&self, _path: &'a str, cfg: &'a str) -> Vec<(&'a str, &'a str)>; + fn need_load(&self) -> bool; + fn load(&mut self) -> bool; + } => where P:Protocol, E:Endpoint + + trait Hash { + fn hash(&self, key: &S) -> i64; + } => where P:Protocol, E:Endpoint, -// pub trait Endpoint: Sized + Send + Sync { -// type Item; -// fn send(&self, req: Self::Item); -// fn shard_idx(&self, _hash: i64) -> usize {todo!("shard_idx not implemented");} -// fn available(&self) -> bool {todo!("available not implemented");} -// fn addr(&self) -> &str {"addr not implemented"} -// fn build_o(_addr: &str, _p: P, _r: Resource, _service: &str, _to: Timeout, _o: ResOption) -> Self {todo!("build not implemented")} -// fn build(addr: &str, p: P, r: Resource, service: &str, to: Timeout) -> Self {Self::build_o(addr, p, r, service, to, Default::default())} -// } => where P:Protocol, E:Endpoint + Inited, R: Request - -// pub trait Topology : Endpoint + Hash{ -// fn exp_sec(&self) -> u32 {86400} -// } => where P:Protocol, E:Endpoint, R:Request, Topologies: Endpoint - -// trait Inited { -// fn inited(&self) -> bool; -// } => where E:Inited - -// trait TopologyWrite { -// fn update(&mut self, name: &str, cfg: &str); -// fn disgroup<'a>(&self, _path: &'a str, cfg: &'a str) -> Vec<(&'a str, &'a str)>; -// fn need_load(&self) -> bool; -// fn load(&mut self) -> bool; -// } => where P:Protocol, E:Endpoint - -// trait Hash { -// fn hash(&self, key: &S) -> i64; -// } => where P:Protocol, E:Endpoint, R:Request - -// } - -// Recursive expansion of topology_dispatcher! macro -// ================================================== - -#[derive(Clone)] -pub enum Topologies { - MsgQue(crate::msgque::topo::MsgQue), - RedisService(crate::redisservice::topo::RedisService), - CacheService(crate::cacheservice::topo::CacheService), - PhantomService(crate::phantomservice::topo::PhantomService), - KvService(crate::kv::topo::KvService), - UuidService(crate::uuid::topo::UuidService), -} -impl Topologies { - pub fn try_from(p: P, endpoint: &str) -> std::io::Result { - match endpoint { - "msg" | "mq" => Ok(Self::MsgQue(p.into())), - "redis" | "rs" => Ok(Self::RedisService(p.into())), - "cache" | "cs" => Ok(Self::CacheService(p.into())), - "phantom" | "ps" | "pt" => Ok(Self::PhantomService(p.into())), - "kv" | "ks" => Ok(Self::KvService(p.into())), - "uuid" | "us" => Ok(Self::UuidService(p.into())), - _ => todo!(), - } - } -} -pub trait Endpoint: Sized + Send + Sync { - type Item; - fn send(&self, req: Self::Item); - - fn shard_idx(&self, _hash: i64) -> usize { - { - todo!(); - }; - } - fn available(&self) -> bool { - { - todo!(); - }; - } - fn addr(&self) -> &str { - "addr not implemented" - } - fn build_o( - _addr: &str, - _p: P, - _r: Resource, - _service: &str, - _to: Timeout, - _o: ResOption, - ) -> Self { - { - todo!(); - } - } - fn build(addr: &str, p: P, r: Resource, service: &str, to: Timeout) -> Self { - Self::build_o(addr, p, r, service, to, Default::default()) - } -} -impl Endpoint for Topologies -where - P: Protocol, - E: Endpoint + Inited, - R: Request, -{ - type Item = R; - #[inline] - fn send(&self, req: Self::Item) { - match self { - Topologies::MsgQue(p) => Endpoint::send(p, req), - Topologies::RedisService(p) => Endpoint::send(p, req), - Topologies::CacheService(p) => Endpoint::send(p, req), - Topologies::PhantomService(p) => Endpoint::send(p, req), - Topologies::KvService(p) => Endpoint::send(p, req), - Topologies::UuidService(p) => Endpoint::send(p, req), - } - } - #[inline] - fn shard_idx(&self, _hash: i64) -> usize { - match self { - Topologies::MsgQue(p) => Endpoint::shard_idx(p, _hash), - Topologies::RedisService(p) => Endpoint::shard_idx(p, _hash), - Topologies::CacheService(p) => Endpoint::shard_idx(p, _hash), - Topologies::PhantomService(p) => Endpoint::shard_idx(p, _hash), - Topologies::KvService(p) => Endpoint::shard_idx(p, _hash), - Topologies::UuidService(p) => Endpoint::shard_idx(p, _hash), - } - } - #[inline] - fn available(&self) -> bool { - match self { - Topologies::MsgQue(p) => Endpoint::available(p), - Topologies::RedisService(p) => Endpoint::available(p), - Topologies::CacheService(p) => Endpoint::available(p), - Topologies::PhantomService(p) => Endpoint::available(p), - Topologies::KvService(p) => Endpoint::available(p), - Topologies::UuidService(p) => Endpoint::available(p), - } - } - #[inline] - fn addr(&self) -> &str { - match self { - Topologies::MsgQue(p) => Endpoint::addr(p), - Topologies::RedisService(p) => Endpoint::addr(p), - Topologies::CacheService(p) => Endpoint::addr(p), - Topologies::PhantomService(p) => Endpoint::addr(p), - Topologies::KvService(p) => Endpoint::addr(p), - Topologies::UuidService(p) => Endpoint::addr(p), - } - } -} -pub trait Topology: Endpoint + Hash { - fn exp_sec(&self) -> u32 { - 86400 - } -} -impl Topology for Topologies -where - P: Protocol, - E: Endpoint, - R: Request, - Topologies: Endpoint, -{ - #[inline] - fn exp_sec(&self) -> u32 { - match self { - Topologies::MsgQue(p) => Topology::exp_sec(p), - Topologies::RedisService(p) => Topology::exp_sec(p), - Topologies::CacheService(p) => Topology::exp_sec(p), - Topologies::PhantomService(p) => Topology::exp_sec(p), - Topologies::KvService(p) => Topology::exp_sec(p), - Topologies::UuidService(p) => Topology::exp_sec(p), - } - } -} -impl Inited for Topologies -where - E: Inited, -{ - #[inline] - fn inited(&self) -> bool { - match self { - Topologies::MsgQue(p) => Inited::inited(p), - Topologies::RedisService(p) => Inited::inited(p), - Topologies::CacheService(p) => Inited::inited(p), - Topologies::PhantomService(p) => Inited::inited(p), - Topologies::KvService(p) => Inited::inited(p), - Topologies::UuidService(p) => Inited::inited(p), - } - } -} -impl TopologyWrite for Topologies -where - P: Protocol, - E: Endpoint, -{ - #[inline] - fn update(&mut self, name: &str, cfg: &str) { - match self { - Topologies::MsgQue(p) => TopologyWrite::update(p, name, cfg), - Topologies::RedisService(p) => TopologyWrite::update(p, name, cfg), - Topologies::CacheService(p) => TopologyWrite::update(p, name, cfg), - Topologies::PhantomService(p) => TopologyWrite::update(p, name, cfg), - Topologies::KvService(p) => TopologyWrite::update(p, name, cfg), - Topologies::UuidService(p) => TopologyWrite::update(p, name, cfg), - } - } - #[inline] - fn disgroup<'a>(&self, _path: &'a str, cfg: &'a str) -> Vec<(&'a str, &'a str)> { - match self { - Topologies::MsgQue(p) => TopologyWrite::disgroup(p, _path, cfg), - Topologies::RedisService(p) => TopologyWrite::disgroup(p, _path, cfg), - Topologies::CacheService(p) => TopologyWrite::disgroup(p, _path, cfg), - Topologies::PhantomService(p) => TopologyWrite::disgroup(p, _path, cfg), - Topologies::KvService(p) => TopologyWrite::disgroup(p, _path, cfg), - Topologies::UuidService(p) => TopologyWrite::disgroup(p, _path, cfg), - } - } - #[inline] - fn need_load(&self) -> bool { - match self { - Topologies::MsgQue(p) => TopologyWrite::need_load(p), - Topologies::RedisService(p) => TopologyWrite::need_load(p), - Topologies::CacheService(p) => TopologyWrite::need_load(p), - Topologies::PhantomService(p) => TopologyWrite::need_load(p), - Topologies::KvService(p) => TopologyWrite::need_load(p), - Topologies::UuidService(p) => TopologyWrite::need_load(p), - } - } - #[inline] - fn load(&mut self) -> bool { - match self { - Topologies::MsgQue(p) => TopologyWrite::load(p), - Topologies::RedisService(p) => TopologyWrite::load(p), - Topologies::CacheService(p) => TopologyWrite::load(p), - Topologies::PhantomService(p) => TopologyWrite::load(p), - Topologies::KvService(p) => TopologyWrite::load(p), - Topologies::UuidService(p) => TopologyWrite::load(p), - } - } -} -impl Hash for Topologies -where - P: Protocol, - E: Endpoint, -{ - #[inline] - fn hash(&self, key: &S) -> i64 { - match self { - Topologies::MsgQue(p) => Hash::hash(p, key), - Topologies::RedisService(p) => Hash::hash(p, key), - Topologies::CacheService(p) => Hash::hash(p, key), - Topologies::PhantomService(p) => Hash::hash(p, key), - Topologies::KvService(p) => Hash::hash(p, key), - Topologies::UuidService(p) => Hash::hash(p, key), - } - } } // 从环境变量获取是否开启后端资源访问的性能模式 diff --git a/procs/src/endpoint.rs b/procs/src/endpoint.rs index ab3642290..6e501a750 100644 --- a/procs/src/endpoint.rs +++ b/procs/src/endpoint.rs @@ -17,23 +17,7 @@ pub fn topology_dispatcher(input: TokenStream) -> TokenStream { let where_clause = trait_def.where_clause; let trait_def = trait_def.trait_def; let trait_ident = &trait_def.ident; - let methods = trait_def.items.iter().map(|item| { - if let TraitItem::Method(method) = item { - // 判断第一个参数是否是self - let is_self = method.sig.inputs.iter().next().map(|arg| { - if let FnArg::Receiver(_) = arg { - true - } else { - // 判断当前方法是否有body - assert!(method.default.is_some(), "Trait method without self Receiver must have body"); - false - } - }).unwrap_or(false); - is_self.then_some(method) - } else { - None - } - }).filter_map(|x| x); + let methods = get_trait_methods(&trait_def); let type_def = trait_def.items.iter().find_map(|item| { if let TraitItem::Type(_item) = item { Some(quote!{ @@ -75,10 +59,16 @@ pub fn topology_dispatcher(input: TokenStream) -> TokenStream { _ => None, }; + let mut generics = enum_generics.clone(); + // 判断where_clause里面是否有R,如果有,则generics需要增加R + if has_r(&where_clause) { + generics.params.push(syn::parse_quote!{R}); + } + quote! { #trait_define - impl #enum_generics #trait_ident for #enum_name #enum_generics #where_clause { + impl #generics #trait_ident for #enum_name #enum_generics #where_clause { #type_def #(#method_impls)* @@ -156,3 +146,55 @@ impl Parse for TopologyInput { Ok(TopologyInput { enum_def, traits }) } } + +// 获取trait中的方法 +// 1. 第一个参数必须是self +fn get_trait_methods(trait_def: &ItemTrait) -> impl Iterator { + trait_def + .items + .iter() + .map(|item| { + if let TraitItem::Method(method) = item { + // 判断第一个参数是否是self + let is_self = method + .sig + .inputs + .iter() + .next() + .map(|arg| { + if let FnArg::Receiver(_) = arg { + true + } else { + // 判断当前方法是否有body + assert!( + method.default.is_some(), + "Trait method without self Receiver must have body" + ); + false + } + }) + .unwrap_or(false); + is_self.then_some(method) + } else { + None + } + }) + .filter_map(|x| x) +} + +// 判断where_clause里面是否有R,如果有,则generics需要增加R +fn has_r(where_clause: &WhereClause) -> bool { + where_clause + .predicates + .iter() + .any(|predicate| match predicate { + syn::WherePredicate::Type(syn::PredicateType { bounded_ty, .. }) => { + if let syn::Type::Path(syn::TypePath { path, .. }) = &*bounded_ty { + path.segments.iter().any(|segment| segment.ident == "R") + } else { + false + } + } + _ => false, + }) +}