Fixed long-running requests to be cancelled when users try to change tabs or contexts.

This commit is contained in:
2023-08-08 10:50:07 -06:00
parent e253ca8359
commit a8f6a5398b
10 changed files with 299 additions and 193 deletions
+66 -51
View File
@@ -2,13 +2,15 @@ use std::fmt::Debug;
use std::sync::Arc;
use anyhow::anyhow;
use log::{debug, error};
use log::{debug, error, warn};
use regex::Regex;
use reqwest::{Client, RequestBuilder};
use serde::de::DeserializeOwned;
use serde::Serialize;
use strum_macros::Display;
use tokio::select;
use tokio::sync::{Mutex, MutexGuard};
use tokio_util::sync::CancellationToken;
use crate::app::App;
use crate::network::radarr_network::RadarrEvent;
@@ -27,18 +29,20 @@ pub enum NetworkEvent {
pub struct Network<'a, 'b> {
client: Client,
cancellation_token: CancellationToken,
pub app: &'a Arc<Mutex<App<'b>>>,
}
impl<'a, 'b> Network<'a, 'b> {
pub fn new(app: &'a Arc<Mutex<App<'b>>>) -> Self {
pub fn new(app: &'a Arc<Mutex<App<'b>>>, cancellation_token: CancellationToken) -> Self {
Network {
client: Client::new(),
app,
cancellation_token,
}
}
pub async fn handle_network_event(&self, network_event: NetworkEvent) {
pub async fn handle_network_event(&mut self, network_event: NetworkEvent) {
match network_event {
NetworkEvent::Radarr(radarr_event) => self.handle_radarr_event(radarr_event).await,
}
@@ -48,7 +52,7 @@ impl<'a, 'b> Network<'a, 'b> {
}
pub async fn handle_request<B, R>(
&self,
&mut self,
request_props: RequestProps<B>,
mut app_update_fn: impl FnMut(R, MutexGuard<'_, App<'_>>),
) where
@@ -56,54 +60,65 @@ impl<'a, 'b> Network<'a, 'b> {
R: DeserializeOwned,
{
let method = request_props.method;
match self.call_api(request_props).await.send().await {
Ok(response) => {
if response.status().is_success() {
match method {
RequestMethod::Get | RequestMethod::Post => {
match utils::parse_response::<R>(response).await {
Ok(value) => {
let app = self.app.lock().await;
app_update_fn(value, app);
}
Err(e) => {
error!("Failed to parse response! {:?}", e);
self
.app
.lock()
.await
.handle_error(anyhow!("Failed to parse response! {:?}", e));
}
}
}
RequestMethod::Delete | RequestMethod::Put => (),
}
} else {
let status = response.status();
let whitespace_regex = Regex::new(r"\s+").unwrap();
let response_body = response.text().await.unwrap_or_default();
let error_body = whitespace_regex
.replace_all(&response_body.replace('\n', " "), " ")
.to_string();
error!(
"Request failed. Received {} response code with body: {}",
status, response_body
);
self.app.lock().await.handle_error(anyhow!(
"Request failed. Received {} response code with body: {}",
status,
error_body
));
}
let request_uri = request_props.uri.clone();
select! {
_ = self.cancellation_token.cancelled() => {
warn!("Received Cancel request. Cancelling request to: {}", request_uri);
let mut app = self.app.lock().await;
self.cancellation_token = app.reset_cancellation_token();
app.is_loading = false;
}
Err(e) => {
error!("Failed to send request. {:?}", e);
self
.app
.lock()
.await
.handle_error(anyhow!("Failed to send request. {} ", e));
resp = tokio::spawn(self.call_api(request_props).await.send()) => {
match resp.unwrap() {
Ok(response) => {
if response.status().is_success() {
match method {
RequestMethod::Get | RequestMethod::Post => {
match utils::parse_response::<R>(response).await {
Ok(value) => {
let app = self.app.lock().await;
app_update_fn(value, app);
}
Err(e) => {
error!("Failed to parse response! {:?}", e);
self
.app
.lock()
.await
.handle_error(anyhow!("Failed to parse response! {:?}", e));
}
}
}
RequestMethod::Delete | RequestMethod::Put => (),
}
} else {
let status = response.status();
let whitespace_regex = Regex::new(r"\s+").unwrap();
let response_body = response.text().await.unwrap_or_default();
let error_body = whitespace_regex
.replace_all(&response_body.replace('\n', " "), " ")
.to_string();
error!(
"Request failed. Received {} response code with body: {}",
status, response_body
);
self.app.lock().await.handle_error(anyhow!(
"Request failed. Received {} response code with body: {}",
status,
error_body
));
}
}
Err(e) => {
error!("Failed to send request. {:?}", e);
self
.app
.lock()
.await
.handle_error(anyhow!("Failed to send request. {} ", e));
}
}
}
}
}