add tracing + custom error type
This commit is contained in:
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -726,6 +726,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1291,9 +1292,21 @@ checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.34"
|
version = "0.1.34"
|
||||||
|
@@ -11,3 +11,4 @@ serde_json = "1"
|
|||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
quick-xml = "0.38"
|
quick-xml = "0.38"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
tracing = "0.1"
|
||||||
|
37
src/lib.rs
37
src/lib.rs
@@ -6,6 +6,7 @@ use serde_json::Value;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{net::TcpListener, sync::RwLock};
|
use tokio::{net::TcpListener, sync::RwLock};
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
pub async fn start(
|
pub async fn start(
|
||||||
title: String,
|
title: String,
|
||||||
@@ -26,10 +27,15 @@ pub async fn start(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
enum FetchError {}
|
enum FetchError {
|
||||||
|
#[error("error fetching url")]
|
||||||
|
Fetching(reqwest::Error),
|
||||||
|
#[error("error parsing json")]
|
||||||
|
JsonParsing(reqwest::Error),
|
||||||
|
}
|
||||||
|
|
||||||
trait Feed {
|
trait Feed {
|
||||||
async fn fetch(&mut self) -> Result<(), Box<dyn std::error::Error>>;
|
async fn fetch(&mut self) -> Result<(), FetchError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -69,7 +75,7 @@ impl rss::ToRss for TestFeed {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl Feed for TestFeed {
|
impl Feed for TestFeed {
|
||||||
async fn fetch(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
async fn fetch(&mut self) -> Result<(), FetchError> {
|
||||||
self.amount_fetch_calls += 1;
|
self.amount_fetch_calls += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -84,7 +90,7 @@ struct LiveFeed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Feed for LiveFeed {
|
impl Feed for LiveFeed {
|
||||||
async fn fetch(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
async fn fetch(&mut self) -> Result<(), FetchError> {
|
||||||
let broadcasts = self.get_all_broadcasts().await?;
|
let broadcasts = self.get_all_broadcasts().await?;
|
||||||
|
|
||||||
for broadcast in broadcasts {
|
for broadcast in broadcasts {
|
||||||
@@ -132,12 +138,17 @@ impl LiveFeed {
|
|||||||
self.episodes.iter().any(|e| e.url == url)
|
self.episodes.iter().any(|e| e.url == url)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_all_broadcasts(&self) -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
async fn get_all_broadcasts(&self) -> Result<Vec<String>, FetchError> {
|
||||||
// List of broadcasts: https://audioapi.orf.at/oe1/api/json/current/broadcasts
|
// List of broadcasts: https://audioapi.orf.at/oe1/api/json/current/broadcasts
|
||||||
//
|
//
|
||||||
// ^ contains link, e.g. https://audioapi.orf.at/oe1/api/json/4.0/broadcast/797577/20250611
|
// ^ contains link, e.g. https://audioapi.orf.at/oe1/api/json/4.0/broadcast/797577/20250611
|
||||||
let url = "https://audioapi.orf.at/oe1/api/json/current/broadcasts";
|
let url = "https://audioapi.orf.at/oe1/api/json/current/broadcasts";
|
||||||
let data: Value = reqwest::get(url).await?.json().await?;
|
let data: Value = reqwest::get(url)
|
||||||
|
.await
|
||||||
|
.map_err(FetchError::Fetching)?
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.map_err(FetchError::JsonParsing)?;
|
||||||
|
|
||||||
let mut ret: Vec<String> = Vec::new();
|
let mut ret: Vec<String> = Vec::new();
|
||||||
|
|
||||||
@@ -145,13 +156,19 @@ impl LiveFeed {
|
|||||||
for day in days {
|
for day in days {
|
||||||
if let Some(broadcasts) = day["broadcasts"].as_array() {
|
if let Some(broadcasts) = day["broadcasts"].as_array() {
|
||||||
for broadcast in broadcasts {
|
for broadcast in broadcasts {
|
||||||
|
let Some(title) = broadcast["title"].as_str() else {
|
||||||
|
warn!("Broadcast has no 'title' attribute, skipping broadcast");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Some(href) = broadcast["href"].as_str() else {
|
||||||
|
warn!("Broadcast has no 'href' attribute, skipping broadcast");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if self.filter_titles.is_empty()
|
if self.filter_titles.is_empty()
|
||||||
|| self
|
|| self.filter_titles.contains(&title.into())
|
||||||
.filter_titles
|
|
||||||
.contains(&broadcast["title"].as_str().unwrap().into())
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
ret.push(broadcast["href"].as_str().unwrap().into());
|
ret.push(href.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,9 @@ use reqwest::header;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::{net::TcpListener, sync::RwLock};
|
use tokio::{net::TcpListener, sync::RwLock};
|
||||||
|
|
||||||
async fn stream_handler<T: Feed + ToRss>(State(state): State<Arc<RwLock<T>>>) -> impl IntoResponse {
|
async fn stream_handler<T: Feed + ToRss + Send>(
|
||||||
|
State(state): State<Arc<RwLock<T>>>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
state.write().await.fetch().await.unwrap();
|
state.write().await.fetch().await.unwrap();
|
||||||
|
|
||||||
let content = state.read().await.to_rss();
|
let content = state.read().await.to_rss();
|
||||||
|
Reference in New Issue
Block a user