From a72b2991fd4f8273333122dbce84cf9d653088f2 Mon Sep 17 00:00:00 2001 From: Jonathan McCumber Date: Sun, 28 Jun 2026 13:00:16 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20address=20reviewer=20feedback=20?= =?UTF-8?q?=E2=80=94=20regex=20OnceLock=20and=20restore=20tick=20rate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Compile whitespace regex once via OnceLock instead of on every non-success response; makes format_error_body infallible (String return, no Result) eliminating the only practical failure mode - Revert default tick rate from 100ms back to 50ms to preserve the existing 20-second Servarr poll cadence (tick_until_poll=400 × 50ms); the recv() change is the real CPU fix — the tick rate change was unnecessary and silently halved the data refresh rate - Keep MANAGARR_TICK_RATE_MS as opt-in override; note that tuning it proportionally stretches the poll interval alongside the tick rate --- src/event/input_event.rs | 13 +++++-------- src/network/mod.rs | 12 +++++++----- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/event/input_event.rs b/src/event/input_event.rs index a02d96c..39e87e0 100644 --- a/src/event/input_event.rs +++ b/src/event/input_event.rs @@ -19,7 +19,7 @@ pub struct Events { rx: Receiver>, } -const DEFAULT_TICK_RATE_MS: u64 = 100; +const DEFAULT_TICK_RATE_MS: u64 = 50; fn configured_tick_rate_ms_from(raw: Option<&str>) -> u64 { raw @@ -78,18 +78,15 @@ mod tests { use super::*; #[test] - fn defaults_to_a_slower_idle_tick_rate() { - assert_eq!(DEFAULT_TICK_RATE_MS, 100); - assert_eq!(configured_tick_rate_ms_from(None), 100); + fn defaults_to_original_tick_rate() { + assert_eq!(DEFAULT_TICK_RATE_MS, 50); + assert_eq!(configured_tick_rate_ms_from(None), 50); } #[test] fn parses_positive_tick_rates_and_rejects_invalid_values() { assert_eq!(configured_tick_rate_ms_from(Some("250")), 250); - assert_eq!( - configured_tick_rate_ms_from(Some("0")), - DEFAULT_TICK_RATE_MS - ); + assert_eq!(configured_tick_rate_ms_from(Some("0")), DEFAULT_TICK_RATE_MS); assert_eq!( configured_tick_rate_ms_from(Some("abc")), DEFAULT_TICK_RATE_MS diff --git a/src/network/mod.rs b/src/network/mod.rs index a319881..c275a2c 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -1,11 +1,13 @@ use std::fmt::Debug; -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use anyhow::{Result, anyhow}; use async_trait::async_trait; use lidarr_network::LidarrEvent; use log::{debug, error, warn}; use regex::Regex; + +static WHITESPACE_RE: OnceLock = OnceLock::new(); use reqwest::{Client, RequestBuilder}; use serde::Serialize; use serde::de::DeserializeOwned; @@ -144,7 +146,7 @@ impl<'a, 'b> Network<'a, 'b> { } else { let status = response.status(); let response_body = response.text().await.unwrap_or_default(); - let error_body = format_error_body(&response_body)?; + let error_body = format_error_body(&response_body); error!("Request failed. Received {status} response code with body: {response_body}"); self.app.lock().await.handle_error(anyhow!("Request failed. Received {status} response code with body: {error_body}")); @@ -277,8 +279,8 @@ impl<'a, 'b> Network<'a, 'b> { } } -fn format_error_body(response_body: &str) -> Result { - let whitespace_regex = Regex::new(r"\s+")?; +fn format_error_body(response_body: &str) -> String { + let re = WHITESPACE_RE.get_or_init(|| Regex::new(r"\s+").unwrap()); let body = serde_json::from_str::(response_body) .ok() .and_then(|value| { @@ -291,7 +293,7 @@ fn format_error_body(response_body: &str) -> Result { }) .unwrap_or_else(|| response_body.replace('\n', " ")); - Ok(whitespace_regex.replace_all(&body, " ").to_string()) + re.replace_all(&body, " ").to_string() } #[derive(Clone, Copy, Debug, Display, PartialEq, Eq)]