feat(readarr): fetch the Readarr system status and expose it on the CLI
Add ReadarrEvent::GetStatus, mapped to GET /system/status, and get_readarr_status in the new readarr_network/system module. It stores the version and start time on ReadarrData so the system view and the tick refresh can read them. Surface it as `managarr readarr get system-status`, matching the Radarr, Sonarr, and Lidarr spelling of the same call. A `list status` spelling would have made the same command a different verb on the fourth servarr, which is a difference the user would have to remember for no benefit. Readarr instances answer /system/status with thirty keys; SystemStatus models the two that are used and serde ignores the rest, as it does for the other three servarrs. This is the first ReadarrCommand variant, so ReadarrCliHandler now reads its app and network fields.
This commit is contained in:
7 files changed
+248
-2
No files matched your search
@@ -5,12 +5,15 @@ use super::{NetworkEvent, NetworkResource};
|
||||
use crate::models::readarr_models::ReadarrSerdeable;
|
||||
use crate::network::{Network, RequestMethod};
|
||||
|
||||
mod system;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "readarr_network_tests.rs"]
|
||||
mod readarr_network_tests;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum ReadarrEvent {
|
||||
GetStatus,
|
||||
HealthCheck,
|
||||
}
|
||||
|
||||
@@ -18,6 +21,7 @@ impl NetworkResource for ReadarrEvent {
|
||||
fn resource(&self) -> &'static str {
|
||||
match &self {
|
||||
ReadarrEvent::HealthCheck => "/health",
|
||||
ReadarrEvent::GetStatus => "/system/status",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +38,7 @@ impl Network<'_, '_> {
|
||||
readarr_event: ReadarrEvent,
|
||||
) -> Result<ReadarrSerdeable> {
|
||||
match readarr_event {
|
||||
ReadarrEvent::GetStatus => self.get_readarr_status().await.map(ReadarrSerdeable::from),
|
||||
ReadarrEvent::HealthCheck => self
|
||||
.get_readarr_healthcheck()
|
||||
.await
|
||||
|
||||
@@ -7,6 +7,7 @@ mod tests {
|
||||
|
||||
#[rstest]
|
||||
#[case(ReadarrEvent::HealthCheck, "/health")]
|
||||
#[case(ReadarrEvent::GetStatus, "/system/status")]
|
||||
fn test_resource(#[case] event: ReadarrEvent, #[case] expected_uri: &str) {
|
||||
assert_str_eq!(event.resource(), expected_uri);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
use crate::models::servarr_models::SystemStatus;
|
||||
use crate::network::readarr_network::ReadarrEvent;
|
||||
use crate::network::{Network, RequestMethod};
|
||||
use anyhow::Result;
|
||||
use log::info;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "readarr_system_network_tests.rs"]
|
||||
mod readarr_system_network_tests;
|
||||
|
||||
impl Network<'_, '_> {
|
||||
pub(in crate::network::readarr_network) async fn get_readarr_status(
|
||||
&mut self,
|
||||
) -> Result<SystemStatus> {
|
||||
info!("Fetching Readarr system status");
|
||||
let event = ReadarrEvent::GetStatus;
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
||||
.await;
|
||||
|
||||
self
|
||||
.handle_request::<(), SystemStatus>(request_props, |system_status, mut app| {
|
||||
app.data.readarr_data.version = system_status.version;
|
||||
app.data.readarr_data.start_time = system_status.start_time;
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::readarr_models::ReadarrSerdeable;
|
||||
use crate::models::servarr_models::SystemStatus;
|
||||
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
|
||||
use crate::network::readarr_network::ReadarrEvent;
|
||||
use chrono::DateTime;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use serde_json::json;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_get_readarr_status_event() {
|
||||
let (mock, app, _server) = MockServarrApi::get()
|
||||
.returns(json!({
|
||||
"version": "0.4.20.129",
|
||||
"startTime": "2026-08-17T03:55:02Z"
|
||||
}))
|
||||
.build_for(ReadarrEvent::GetStatus)
|
||||
.await;
|
||||
app.lock().await.server_tabs.set_index(3);
|
||||
let mut network = test_network(&app);
|
||||
let date_time = DateTime::from(DateTime::parse_from_rfc3339("2026-08-17T03:55:02Z").unwrap());
|
||||
|
||||
let result = network.handle_readarr_event(ReadarrEvent::GetStatus).await;
|
||||
|
||||
mock.assert_async().await;
|
||||
|
||||
let ReadarrSerdeable::SystemStatus(status) = result.unwrap() else {
|
||||
panic!("Expected SystemStatus")
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
status,
|
||||
SystemStatus {
|
||||
version: "0.4.20.129".to_owned(),
|
||||
start_time: date_time
|
||||
}
|
||||
);
|
||||
assert_str_eq!(app.lock().await.data.readarr_data.version, "0.4.20.129");
|
||||
assert_eq!(app.lock().await.data.readarr_data.start_time, date_time);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_get_readarr_status_event_failure() {
|
||||
let (mock, app, _server) = MockServarrApi::get()
|
||||
.returns(json!({}))
|
||||
.status(500)
|
||||
.build_for(ReadarrEvent::GetStatus)
|
||||
.await;
|
||||
app.lock().await.server_tabs.set_index(3);
|
||||
let mut network = test_network(&app);
|
||||
|
||||
let result = network.handle_readarr_event(ReadarrEvent::GetStatus).await;
|
||||
|
||||
mock.assert_async().await;
|
||||
assert_err!(result);
|
||||
assert_is_empty!(app.lock().await.data.readarr_data.version);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user