11use reqwest:: Method ;
22use slint:: { ComponentHandle , Model , VecModel } ;
3- use tracing:: debug;
3+ use thiserror:: Error ;
4+ use tracing:: { debug, warn} ;
45
56use super :: {
67 model:: { FeatureFlags , InstanceData , ServerState } ,
@@ -25,11 +26,10 @@ pub async fn start(state: ServerState) {
2526 let client = client. clone ( ) ;
2627 let state = state. clone ( ) ;
2728 tokio:: spawn ( async move {
28- if update_instance_latency ( state. clone ( ) , instance. clone ( ) , & client)
29- . await
30- . is_none ( )
31- {
32- pingfall ( state, instance) . await ;
29+ let result =
30+ update_instance_latency ( state. clone ( ) , instance. clone ( ) , & client) . await ;
31+ if let Err ( e) = result {
32+ pingfall ( state. clone ( ) , instance. clone ( ) , e) . await ;
3333 }
3434 } ) ;
3535 }
@@ -40,25 +40,32 @@ pub async fn start(state: ServerState) {
4040 }
4141}
4242
43+ #[ derive( Debug , Error ) ]
44+ pub enum LatencyError {
45+ #[ error( "Request error: {0}" ) ]
46+ Rewqest ( #[ from] reqwest:: Error ) ,
47+ #[ error( "Non-success status code" ) ]
48+ NonSuccessStatus ( u16 ) ,
49+ }
50+
4351pub async fn update_instance_latency (
4452 state : ServerState , instance : InstanceData , client : & reqwest:: Client ,
45- ) -> Option < i32 > {
53+ ) -> Result < i32 , LatencyError > {
4654 let req = client
4755 . request ( Method :: OPTIONS , instance. remote . replace ( "ws" , "http" ) )
4856 . header ( "User-Agent" , format ! ( "wsrx/{}" , env!( "CARGO_PKG_VERSION" ) ) )
49- . build ( )
50- . ok ( ) ?;
57+ . build ( ) ?;
5158
5259 let start_time = std:: time:: Instant :: now ( ) ;
5360
54- let resp = client. execute ( req) . await . ok ( ) ?;
61+ let resp = client. execute ( req) . await ?;
5562
5663 let elapsed = if resp. status ( ) . is_success ( ) {
5764 // always > 0
5865 start_time. elapsed ( ) . as_millis ( ) as i32 / 2
5966 } else {
6067 debug ! ( "Failed to ping instance: {}" , resp. status( ) ) ;
61- return None ;
68+ return Err ( LatencyError :: NonSuccessStatus ( resp . status ( ) . as_u16 ( ) ) ) ;
6269 } ;
6370
6471 for proxy_instance in state. instances . write ( ) . await . iter_mut ( ) {
@@ -98,10 +105,10 @@ pub async fn update_instance_latency(
98105 break ;
99106 }
100107
101- Some ( elapsed)
108+ Ok ( elapsed)
102109}
103110
104- async fn pingfall ( state : ServerState , instance : InstanceData ) {
111+ async fn pingfall ( state : ServerState , instance : InstanceData , err : LatencyError ) {
105112 let scopes = state. scopes . read ( ) . await ;
106113
107114 let scope = scopes
@@ -111,6 +118,33 @@ async fn pingfall(state: ServerState, instance: InstanceData) {
111118 if let Some ( scope) = scope
112119 && scope. features . contains ( FeatureFlags :: PingFall )
113120 {
114- on_instance_del ( & state, & instance. local ) . await ;
121+ let settings = scope. settings . get ( & FeatureFlags :: PingFall ) ;
122+ if let Some ( settings) = settings {
123+ let pingfall_settings: super :: model:: PingFallSettings =
124+ serde_json:: from_value ( settings. to_owned ( ) ) . unwrap_or_default ( ) ;
125+
126+ match err {
127+ LatencyError :: NonSuccessStatus ( code) => {
128+ if pingfall_settings. fail_status . contains ( & code)
129+ || pingfall_settings. fail_status . is_empty ( )
130+ {
131+ warn ! (
132+ "PingFall triggered for instance {} due to status code {}" ,
133+ instance. local, code
134+ ) ;
135+ on_instance_del ( & state, & instance. local ) . await ;
136+ }
137+ }
138+ LatencyError :: Rewqest ( _) => {
139+ if pingfall_settings. drop_unknown {
140+ warn ! (
141+ "PingFall triggered for instance {} due to request error" ,
142+ instance. local
143+ ) ;
144+ on_instance_del ( & state, & instance. local ) . await ;
145+ }
146+ }
147+ }
148+ }
115149 }
116150}
0 commit comments