Skip to content

Commit

Permalink
big refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
emmaboecker committed Feb 5, 2024
1 parent 26f4e98 commit f74c9c2
Show file tree
Hide file tree
Showing 51 changed files with 1,297 additions and 1,221 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion iris-client/src/endpoints/station_board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl IrisClient {

/// Get all planned information IRIS has for a specific station at the specified date + hour.
///
/// From experience IRIS does not have any more planned data than the current day + maybe a bit of the early hours of the next day.
/// From experience IRIS does not have more planned data than the current day + maybe a bit of the early hours of the next day.
///
/// **Consider using [`station_board`](IrisClient::station_board) instead.** \
///
Expand Down
2 changes: 1 addition & 1 deletion iris-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl IrisClient {
concurrent_requests: Option<usize>,
) -> Self {
Self {
client: client.unwrap_or_else(reqwest::Client::new),
client: client.unwrap_or_default(),
base_url: base_url.unwrap_or_else(|| String::from("https://iris.noncd.db.de")),
semaphore: Semaphore::new(concurrent_requests.unwrap_or(100)),
}
Expand Down
32 changes: 14 additions & 18 deletions railboard-api/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@ use chrono_tz::Europe::Berlin;
use iris_client::station_board::response::TimeTable;
use redis::JsonAsyncCommands;
use ris_client::{
journey_search::RisJourneySearchResponse, station_search::RisStationSearchResponse,
journey_search::RisJourneySearchResponse, station_search::RisStationSearchElement,
};
use serde::{de::DeserializeOwned, Serialize};
use thiserror::Error;

use crate::{
ris::{
journey_details::RisJourneyDetails, station_board::RisStationBoard,
station_information::StationInformation,
},
vendo::{
journey_details::JourneyDetails, location_search::LocationSearchCache,
station_board::StationBoard,
},
};
use ris_client::journey_details::RisJourneyDetails;
use ris_client::station_board::RisStationBoard;
use ris_client::station_information::RisStationInformation;
use vendo_client::journey_details::VendoJourneyDetails;
use vendo_client::station_board::VendoStationBoard;
use crate::vendo::location_search::LocationSearchCache;

#[async_trait::async_trait]
pub trait Cache: Sync + Send {
Expand All @@ -43,6 +38,7 @@ pub enum CacheInsertError {
RedisError(#[from] redis::RedisError),
}

#[derive(Clone)]
pub struct RedisCache {
pub redis_client: Arc<redis::Client>,
}
Expand Down Expand Up @@ -132,7 +128,7 @@ pub trait CachableObject {
}

#[async_trait::async_trait]
impl CachableObject for StationBoard {
impl CachableObject for VendoStationBoard {
async fn insert_to_cache<C: Cache>(
&self,
cache: &C,
Expand All @@ -158,7 +154,7 @@ impl CachableObject for LocationSearchCache {
}

#[async_trait::async_trait]
impl CachableObject for JourneyDetails {
impl CachableObject for VendoJourneyDetails {
async fn insert_to_cache<C: Cache>(
&self,
cache: &C,
Expand Down Expand Up @@ -253,7 +249,7 @@ impl CachableObject for RisStationBoard {
}

#[async_trait::async_trait]
impl CachableObject for StationInformation {
impl CachableObject for RisStationInformation {
async fn insert_to_cache<C: Cache>(
&self,
cache: &C,
Expand All @@ -266,14 +262,14 @@ impl CachableObject for StationInformation {
}

#[async_trait::async_trait]
impl CachableObject for RisStationSearchResponse {
impl CachableObject for Vec<RisStationSearchElement> {
async fn insert_to_cache<C: Cache>(
&self,
cache: &C,
information: Option<&str>,
) -> Result<(), CacheInsertError> {
let key = format!("ris.station_search_by_name.{}", information.unwrap_or(""));
let key = format!("ris.station-search-by-name.{}", information.unwrap_or(""));

cache.insert_to_cache(key, &self, 180).await
cache.insert_to_cache(key, &self, 60 * 60).await
}
}
24 changes: 3 additions & 21 deletions railboard-api/src/custom.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
use std::sync::Arc;

use axum::{routing::get, Router};
use iris_client::IrisClient;
use ris_client::RisClient;
use axum::{Router, routing::get};

use crate::cache::{self, RedisCache};
use crate::SharedState;

pub mod station_board;

#[derive(Clone)]
pub struct CustomEndpointState {
iris_client: Arc<IrisClient>,
ris_client: Arc<RisClient>,
cache: Arc<RedisCache>,
}

pub fn router(redis: Arc<redis::Client>, db_client_id: &str, db_api_key: &str) -> Router {
let ris_client = Arc::new(RisClient::new(None, None, None, db_client_id, db_api_key));

let shared_state = Arc::new(CustomEndpointState {
iris_client: Arc::new(IrisClient::default()),
ris_client,
cache: Arc::new(cache::RedisCache::new(redis)),
});

pub fn router() -> Router<Arc<SharedState>> {
Router::new()
.route("/station_board/:id", get(station_board::station_board))
.with_state(shared_state)
}
82 changes: 38 additions & 44 deletions railboard-api/src/custom/station_board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@ use axum::{
extract::{Path, Query, State},
Json,
};
use chrono::{DateTime, Datelike, FixedOffset, TimeZone, Utc};
use chrono::{Datelike, DateTime, FixedOffset, TimeZone, Utc};
use chrono_tz::Europe::Berlin;
use iris_client::station_board::{message::Message, IrisStationBoard, RouteStop};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::{
error::RailboardResult, iris::station_board::iris_station_board,
ris::station_board::ris_station_board,
};
use iris_client::station_board::{IrisStationBoard, message::Message, RouteStop};

use super::CustomEndpointState;
use crate::{error::RailboardResult, iris::station_board::iris_station_board, SharedState};

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
Expand All @@ -25,24 +21,24 @@ pub struct StationBoardQuery {
}

#[utoipa::path(
get,
path = "/v1/station_board/{eva}",
params(
("eva" = String, Path, description = "The Eva Number of the Station you are requesting"),
("timeStart" = Option<DateTime<FixedOffset>>, Query, description = "The Start Time of the Time Range you are requesting"),
("timeEnd" = Option<DateTime<FixedOffset>>, Query, description = "The End Time of the Time Range you are requesting")
),
tag = "Custom",
responses(
(status = 200, description = "The requested Station Board", body = StationBoard),
(status = 400, description = "The Error returned by the Ris or Iris, will be Variant 2 or Variant 5", body = RailboardApiError),
(status = 500, description = "The Error returned if the request or deserialization fails, will be domain Request", body = RailboardApiError)
)
get,
path = "/v1/station_board/{eva}",
params(
("eva" = String, Path, description = "The Eva Number of the Station you are requesting"),
("timeStart" = Option < DateTime < FixedOffset >>, Query, description = "The Start Time of the Time Range you are requesting"),
("timeEnd" = Option < DateTime < FixedOffset >>, Query, description = "The End Time of the Time Range you are requesting")
),
tag = "Custom",
responses(
(status = 200, description = "The requested Station Board", body = StationBoard),
(status = 400, description = "The Error returned by the Ris or Iris, will be Variant 2 or Variant 5", body = RailboardApiError),
(status = 500, description = "The Error returned if the request or deserialization fails, will be domain Request", body = RailboardApiError)
)
)]
pub async fn station_board(
Path(eva): Path<String>,
Query(query): Query<StationBoardQuery>,
State(state): State<Arc<CustomEndpointState>>,
State(state): State<Arc<SharedState>>,
) -> RailboardResult<Json<StationBoard>> {
let time_start = if let Some(time_start) = query.time_start {
Berlin.from_utc_datetime(&time_start.naive_utc())
Expand All @@ -57,19 +53,17 @@ pub async fn station_board(
};

let (ris_station_board, iris_station_board) = tokio::join!(
ris_station_board(
state.ris_client.station_board(
&eva,
Some(time_start),
Some(time_end),
state.ris_client.clone(),
state.cache.clone()
),
iris_station_board(
&eva,
time_end,
time_start,
state.iris_client.clone(),
state.cache.clone()
&state.cache
)
);

Expand All @@ -92,18 +86,18 @@ pub async fn station_board(
iris_item.train_number == item.train_number.to_string()
&& iris_item.train_type == item.category
&& (iris_item
.arrival
.clone()
.map(|arrival| arrival.planned_time.naive_utc().date().day())
== item
.arrival
.clone()
.map(|arrival| arrival.time_scheduled.naive_utc().date().day())
|| iris_item.departure.clone().map(|departure| {
departure.planned_time.naive_utc().date().day()
}) == item.departure.clone().map(|departure| {
departure.time_scheduled.naive_utc().date().day()
}))
.arrival
.clone()
.map(|arrival| arrival.planned_time.naive_utc().date().day())
== item
.arrival
.clone()
.map(|arrival| arrival.time_scheduled.naive_utc().date().day())
|| iris_item.departure.clone().map(|departure| {
departure.planned_time.naive_utc().date().day()
}) == item.departure.clone().map(|departure| {
departure.time_scheduled.naive_utc().date().day()
}))
});

let iris_item = iris_item.cloned();
Expand Down Expand Up @@ -176,13 +170,13 @@ pub async fn station_board(
})
.unwrap_or(false)
|| stop
.departure
.as_ref()
.map(|departure| {
departure.planned_time.naive_utc() >= time_start.naive_utc()
&& departure.planned_time.naive_utc() <= time_end.naive_utc()
})
.unwrap_or(false)
.departure
.as_ref()
.map(|departure| {
departure.planned_time.naive_utc() >= time_start.naive_utc()
&& departure.planned_time.naive_utc() <= time_end.naive_utc()
})
.unwrap_or(false)
}) {
if !items
.iter()
Expand Down
5 changes: 5 additions & 0 deletions railboard-api/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ impl From<RisOrRequestError> for RailboardApiError {
message: format!("Failed to get from Ris (through Zugportal): {err}"),
error: Some(UnderlyingApiError::ZugportalError(err)),
},
RisOrRequestError::NotFoundError => RailboardApiError {
domain: ErrorDomain::Input,
message: "There was nothing found with these parameters".to_string(),
error: None,
}
}
}
}
21 changes: 3 additions & 18 deletions railboard-api/src/iris.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
use std::sync::Arc;

use axum::{routing::get, Router};
use iris_client::IrisClient;
use axum::{Router, routing::get};

use crate::cache::{self, RedisCache};
use crate::SharedState;

pub mod station_board;

#[derive(Clone)]
pub struct IrisState {
iris_client: Arc<IrisClient>,
cache: Arc<RedisCache>,
}

pub fn router(redis: Arc<redis::Client>) -> Router {
let iris_client = Arc::new(IrisClient::default());

let shared_state = Arc::new(IrisState {
iris_client,
cache: Arc::new(cache::RedisCache::new(redis)),
});

pub fn router() -> Router<Arc<SharedState>> {
Router::new()
.route("/station_board/:id", get(station_board::station_board))
.with_state(shared_state)
}
Loading

0 comments on commit f74c9c2

Please sign in to comment.