1313// CONDITIONS OF ANY KIND, either express or implied. See the License for the
1414// specific language governing permissions and limitations under the License.
1515
16- use std:: sync:: Arc ;
16+ use std:: { sync:: Arc , time :: Duration } ;
1717
1818use crate :: core:: {
1919 flow:: CircuitBreakerFlow ,
2020 model:: {
21- circuitbreaker:: { CallAbortedError , CheckResult , Resource , ResourceStat } ,
21+ circuitbreaker:: { CallAbortedError , CheckResult , MethodResource , Resource , ResourceStat , RetStatus , ServiceResource } ,
2222 error:: PolarisError ,
2323 } ,
2424} ;
2525
2626use super :: req:: { RequestContext , ResponseContext } ;
2727
28+ /// CircuitBreakerAPI .
2829#[ async_trait:: async_trait]
2930pub trait CircuitBreakerAPI
3031where
4142 ) -> Result < Arc < InvokeHandler > , PolarisError > ;
4243}
4344
45+ /// InvokeHandler .
4446pub struct InvokeHandler {
47+ // req_ctx: 请求上下文
4548 req_ctx : RequestContext ,
49+ // flow: 熔断器流程
4650 flow : Arc < CircuitBreakerFlow > ,
4751}
4852
@@ -53,14 +57,87 @@ impl InvokeHandler {
5357
5458 /// acquire_permission 检查当前请求是否可放通
5559 async fn acquire_permission ( & self ) -> Result < ( ) , CallAbortedError > {
56- Ok ( ( ) )
60+ let svc_res = ServiceResource :: new_waith_caller (
61+ self . req_ctx . caller_service . clone ( ) ,
62+ self . req_ctx . callee_service . clone ( ) ) ;
63+
64+ match self . flow . check_resource ( Resource :: ServiceResource ( svc_res) ) . await {
65+ Ok ( ret) => {
66+ if ret. pass {
67+ Ok ( ( ) )
68+ } else {
69+ Err ( CallAbortedError :: new ( ret. rule_name , ret. fallback_info ) )
70+ }
71+ } ,
72+ Err ( e) => {
73+ // 内部异常,不触发垄断,但是需要记录
74+ crate :: error!( "[circuitbreaker][invoke] check resource failed: {:?}" , e) ;
75+ Ok ( ( ) )
76+ } ,
77+ }
5778 }
5879
5980 async fn on_success ( & self , rsp : ResponseContext ) -> Result < ( ) , PolarisError > {
60- Ok ( ( ) )
81+ let cost = rsp. duration . clone ( ) ;
82+ let mut code = -1 as i32 ;
83+ let mut status = RetStatus :: RetSuccess ;
84+
85+ if let Some ( r) = & self . req_ctx . result_to_code {
86+ code = r. on_success ( rsp. result . unwrap ( ) ) ;
87+ }
88+ if let Some ( e) = rsp. error {
89+ let ret = e. downcast :: < CallAbortedError > ( ) ;
90+ if ret. is_ok ( ) {
91+ status = RetStatus :: RetReject ;
92+ }
93+ }
94+ self . common_report ( cost, code, status) . await
6195 }
6296
6397 async fn on_error ( & self , rsp : ResponseContext ) -> Result < ( ) , PolarisError > {
64- Ok ( ( ) )
98+ let cost = rsp. duration . clone ( ) ;
99+ let mut code = 0 as i32 ;
100+ let mut status = RetStatus :: RetUnknown ;
101+
102+ if let Some ( r) = & self . req_ctx . result_to_code {
103+ code = r. on_success ( rsp. result . unwrap ( ) ) ;
104+ }
105+ self . common_report ( cost, code, status) . await
106+ }
107+
108+ async fn common_report ( & self , cost : Duration , code : i32 , status : RetStatus ) -> Result < ( ) , PolarisError > {
109+ let stat = ResourceStat {
110+ resource : Resource :: ServiceResource ( ServiceResource :: new_waith_caller (
111+ self . req_ctx . caller_service . clone ( ) ,
112+ self . req_ctx . callee_service . clone ( ) ) ) ,
113+ ret_code : code. to_string ( ) ,
114+ delay : cost,
115+ status : status. clone ( ) ,
116+ } ;
117+
118+ let ret = self . flow . report_stat ( stat) . await ;
119+ if ret. is_err ( ) {
120+ crate :: error!( "[circuitbreaker][invoke] report stat failed" ) ;
121+ return ret;
122+ }
123+
124+ if self . req_ctx . path . is_empty ( ) {
125+ return Ok ( ( ) ) ;
126+ }
127+
128+ // 补充一个接口级别的数据上报
129+ let stat = ResourceStat {
130+ resource : Resource :: MethodResource ( MethodResource :: new_waith_caller (
131+ self . req_ctx . caller_service . clone ( ) ,
132+ self . req_ctx . callee_service . clone ( ) ,
133+ self . req_ctx . protocol . clone ( ) ,
134+ self . req_ctx . method . clone ( ) ,
135+ self . req_ctx . path . clone ( ) ,
136+ ) ) ,
137+ ret_code : code. to_string ( ) ,
138+ delay : cost,
139+ status,
140+ } ;
141+ self . flow . report_stat ( stat) . await
65142 }
66143}
0 commit comments