diff options
| -rw-r--r-- | src/lib/client.rs | 130 |
1 files changed, 102 insertions, 28 deletions
diff --git a/src/lib/client.rs b/src/lib/client.rs index 3b613b6..445bf77 100644 --- a/src/lib/client.rs +++ b/src/lib/client.rs | |||
| @@ -15,11 +15,11 @@ use std::{ | |||
| 15 | fmt::{Display, Write}, | 15 | fmt::{Display, Write}, |
| 16 | fs::create_dir_all, | 16 | fs::create_dir_all, |
| 17 | path::Path, | 17 | path::Path, |
| 18 | sync::Arc, | 18 | sync::{Arc, RwLock}, |
| 19 | time::Duration, | 19 | time::Duration, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | use anyhow::{Context, Result, bail}; | 22 | use anyhow::{Context, Result, anyhow, bail}; |
| 23 | use async_trait::async_trait; | 23 | use async_trait::async_trait; |
| 24 | use console::Style; | 24 | use console::Style; |
| 25 | use futures::{ | 25 | use futures::{ |
| @@ -60,6 +60,29 @@ pub struct Client { | |||
| 60 | more_fallback_relays: Vec<String>, | 60 | more_fallback_relays: Vec<String>, |
| 61 | blaster_relays: Vec<String>, | 61 | blaster_relays: Vec<String>, |
| 62 | fallback_signer_relays: Vec<String>, | 62 | fallback_signer_relays: Vec<String>, |
| 63 | relays_not_to_retry: Arc<RwLock<HashMap<RelayUrl, String>>>, | ||
| 64 | } | ||
| 65 | |||
| 66 | impl Client { | ||
| 67 | /// Marks a relay as skipped for the current session with a given reason. | ||
| 68 | /// This method encapsulates the write lock for the relays_not_to_retry map. | ||
| 69 | fn skip_relay_for_session(&self, relay_url: RelayUrl, reason: String) { | ||
| 70 | self.relays_not_to_retry | ||
| 71 | .write() | ||
| 72 | .unwrap() | ||
| 73 | .insert(relay_url, reason); | ||
| 74 | } | ||
| 75 | |||
| 76 | /// Checks if a relay should be skipped for the current session and returns | ||
| 77 | /// the reason if it is. This method encapsulates the read lock for the | ||
| 78 | /// relays_not_to_retry map. | ||
| 79 | fn is_relay_skipped_for_session(&self, relay_url: &RelayUrl) -> Option<String> { | ||
| 80 | self.relays_not_to_retry | ||
| 81 | .read() | ||
| 82 | .unwrap() | ||
| 83 | .get(relay_url) | ||
| 84 | .cloned() | ||
| 85 | } | ||
| 63 | } | 86 | } |
| 64 | 87 | ||
| 65 | #[cfg_attr(test, automock)] | 88 | #[cfg_attr(test, automock)] |
| @@ -127,6 +150,7 @@ impl Connect for Client { | |||
| 127 | more_fallback_relays: opts.more_fallback_relays, | 150 | more_fallback_relays: opts.more_fallback_relays, |
| 128 | blaster_relays: opts.blaster_relays, | 151 | blaster_relays: opts.blaster_relays, |
| 129 | fallback_signer_relays: opts.fallback_signer_relays, | 152 | fallback_signer_relays: opts.fallback_signer_relays, |
| 153 | relays_not_to_retry: Arc::new(RwLock::new(HashMap::new())), | ||
| 130 | } | 154 | } |
| 131 | } | 155 | } |
| 132 | 156 | ||
| @@ -135,6 +159,9 @@ impl Connect for Client { | |||
| 135 | } | 159 | } |
| 136 | 160 | ||
| 137 | async fn connect(&self, relay_url: &RelayUrl) -> Result<()> { | 161 | async fn connect(&self, relay_url: &RelayUrl) -> Result<()> { |
| 162 | if let Some(reason) = self.is_relay_skipped_for_session(relay_url) { | ||
| 163 | bail!("{reason}"); | ||
| 164 | } | ||
| 138 | self.client | 165 | self.client |
| 139 | .add_relay(relay_url) | 166 | .add_relay(relay_url) |
| 140 | .await | 167 | .await |
| @@ -150,6 +177,7 @@ impl Connect for Client { | |||
| 150 | } | 177 | } |
| 151 | 178 | ||
| 152 | if !relay.is_connected() { | 179 | if !relay.is_connected() { |
| 180 | self.skip_relay_for_session(relay_url.clone(), "connection timeout".to_string()); | ||
| 153 | bail!("connection timeout"); | 181 | bail!("connection timeout"); |
| 154 | } | 182 | } |
| 155 | Ok(()) | 183 | Ok(()) |
| @@ -244,21 +272,37 @@ impl Connect for Client { | |||
| 244 | } else { | 272 | } else { |
| 245 | None | 273 | None |
| 246 | }; | 274 | }; |
| 275 | fn update_progress_bar_with_error( | ||
| 276 | relay_url: &RelayUrl, | ||
| 277 | pb: Option<ProgressBar>, | ||
| 278 | error: &anyhow::Error, | ||
| 279 | ) { | ||
| 280 | if let Some(pb) = pb { | ||
| 281 | pb.set_style(pb_after_style(false)); | ||
| 282 | pb.set_prefix(format!("{: <11}{}", "error", relay_url)); | ||
| 283 | pb.finish_with_message( | ||
| 284 | console::style( | ||
| 285 | error.to_string().replace("relay pool error:", "error:"), | ||
| 286 | ) | ||
| 287 | .for_stderr() | ||
| 288 | .red() | ||
| 289 | .to_string(), | ||
| 290 | ); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | if let Some(reason) = self.is_relay_skipped_for_session(relay.url()) { | ||
| 294 | update_progress_bar_with_error(relay.url(), pb, &anyhow!("{reason}")); | ||
| 295 | bail!("{reason}"); | ||
| 296 | } | ||
| 247 | #[allow(clippy::large_futures)] | 297 | #[allow(clippy::large_futures)] |
| 248 | match get_events_of(relay, filters, &pb).await { | 298 | match get_events_of(relay, filters, &pb).await { |
| 249 | Err(error) => { | 299 | Err(error) => { |
| 250 | if let Some(pb) = pb { | 300 | // Check error for timeout/connection issues and add to skip list |
| 251 | pb.set_style(pb_after_style(false)); | 301 | if error.to_string().contains("connection timeout") { |
| 252 | pb.set_prefix(format!("{: <11}{}", "error", relay.url())); | 302 | // Simple check, refine as needed |
| 253 | pb.finish_with_message( | 303 | self.skip_relay_for_session(relay.url().clone(), error.to_string()); |
| 254 | console::style( | ||
| 255 | error.to_string().replace("relay pool error:", "error:"), | ||
| 256 | ) | ||
| 257 | .for_stderr() | ||
| 258 | .red() | ||
| 259 | .to_string(), | ||
| 260 | ); | ||
| 261 | } | 304 | } |
| 305 | update_progress_bar_with_error(relay.url(), pb, &error); | ||
| 262 | Err(error) | 306 | Err(error) |
| 263 | } | 307 | } |
| 264 | Ok(res) => { | 308 | Ok(res) => { |
| @@ -391,25 +435,55 @@ impl Connect for Client { | |||
| 391 | } else { | 435 | } else { |
| 392 | None | 436 | None |
| 393 | }; | 437 | }; |
| 394 | 438 | // do here | |
| 439 | |||
| 440 | fn update_progress_bar_with_error( | ||
| 441 | relay_column_width: usize, | ||
| 442 | relay_url: &RelayUrl, | ||
| 443 | pb: Option<ProgressBar>, | ||
| 444 | error: &anyhow::Error, | ||
| 445 | ) { | ||
| 446 | if let Some(pb) = pb { | ||
| 447 | pb.set_style(pb_after_style(false)); | ||
| 448 | pb.set_prefix( | ||
| 449 | Style::new() | ||
| 450 | .color256(247) | ||
| 451 | .apply_to(format!("{: <relay_column_width$}", &relay_url)) | ||
| 452 | .to_string(), | ||
| 453 | ); | ||
| 454 | pb.finish_with_message( | ||
| 455 | console::style( | ||
| 456 | error.to_string().replace("relay pool error:", "error:"), | ||
| 457 | ) | ||
| 458 | .for_stderr() | ||
| 459 | .red() | ||
| 460 | .to_string(), | ||
| 461 | ); | ||
| 462 | } | ||
| 463 | } | ||
| 464 | if let Some(reason) = self.is_relay_skipped_for_session(&relay_url) { | ||
| 465 | update_progress_bar_with_error( | ||
| 466 | relay_column_width, | ||
| 467 | &relay_url, | ||
| 468 | pb, | ||
| 469 | &anyhow!("{reason}"), | ||
| 470 | ); | ||
| 471 | bail!("{reason}"); | ||
| 472 | } | ||
| 395 | #[allow(clippy::large_futures)] | 473 | #[allow(clippy::large_futures)] |
| 396 | match self.fetch_all_from_relay(git_repo_path, request, &pb).await { | 474 | match self.fetch_all_from_relay(git_repo_path, request, &pb).await { |
| 397 | Err(error) => { | 475 | Err(error) => { |
| 398 | if let Some(pb) = pb { | 476 | // Check error for timeout/connection issues and add to skip list |
| 399 | pb.set_style(pb_after_style(false)); | 477 | if error.to_string().contains("connection timeout") { |
| 400 | pb.set_prefix( | 478 | // Simple check, refine as needed |
| 401 | dim.apply_to(format!("{: <relay_column_width$}", &relay_url)) | 479 | self.skip_relay_for_session(relay_url.clone(), error.to_string()); |
| 402 | .to_string(), | ||
| 403 | ); | ||
| 404 | pb.finish_with_message( | ||
| 405 | console::style( | ||
| 406 | error.to_string().replace("relay pool error:", "error:"), | ||
| 407 | ) | ||
| 408 | .for_stderr() | ||
| 409 | .red() | ||
| 410 | .to_string(), | ||
| 411 | ); | ||
| 412 | } | 480 | } |
| 481 | update_progress_bar_with_error( | ||
| 482 | relay_column_width, | ||
| 483 | &relay_url, | ||
| 484 | pb, | ||
| 485 | &error, | ||
| 486 | ); | ||
| 413 | Err(error) | 487 | Err(error) |
| 414 | } | 488 | } |
| 415 | Ok(res) => Ok(res), | 489 | Ok(res) => Ok(res), |