mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 17:57:47 +03:00
feat(schedule)!: move schedule parser, downloader, and updater to external library
This can be used to support more schedule formats in the future.
This commit is contained in:
@@ -1,69 +1,88 @@
|
||||
mod env;
|
||||
mod fcm_client;
|
||||
mod schedule;
|
||||
|
||||
pub use crate::state::env::AppEnv;
|
||||
use crate::state::fcm_client::FCMClientData;
|
||||
use crate::xls_downloader::basic_impl::BasicXlsDownloader;
|
||||
use actix_web::web;
|
||||
use diesel::{Connection, PgConnection};
|
||||
use firebase_messaging_rs::FCMClient;
|
||||
use std::ops::DerefMut;
|
||||
use tokio::sync::{MappedMutexGuard, Mutex, MutexGuard};
|
||||
|
||||
pub use self::schedule::{Schedule, ScheduleSnapshot};
|
||||
pub use crate::state::env::AppEnv;
|
||||
use providers::base::{ScheduleProvider, ScheduleSnapshot};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
/// Common data provided to endpoints.
|
||||
pub struct AppState {
|
||||
cancel_token: CancellationToken,
|
||||
database: Mutex<PgConnection>,
|
||||
downloader: Mutex<BasicXlsDownloader>,
|
||||
schedule: Mutex<Schedule>,
|
||||
providers: HashMap<String, Arc<dyn ScheduleProvider>>,
|
||||
env: AppEnv,
|
||||
fcm_client: Option<Mutex<FCMClient>>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub async fn new() -> Result<Self, self::schedule::Error> {
|
||||
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
|
||||
let mut _self = Self {
|
||||
downloader: Mutex::new(BasicXlsDownloader::new()),
|
||||
let env = AppEnv::default();
|
||||
let providers: HashMap<String, Arc<dyn ScheduleProvider>> = HashMap::from([(
|
||||
"eng_polytechnic".to_string(),
|
||||
providers::EngelsPolytechnicProvider::new({
|
||||
#[cfg(test)]
|
||||
{
|
||||
providers::EngelsPolytechnicUpdateSource::Prepared(ScheduleSnapshot {
|
||||
url: "".to_string(),
|
||||
fetched_at: chrono::DateTime::default(),
|
||||
updated_at: chrono::DateTime::default(),
|
||||
data: providers::test_utils::engels_polytechnic::test_result().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
schedule: Mutex::new(Schedule::default()),
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
if let Some(url) = &env.schedule.url {
|
||||
providers::EngelsPolytechnicUpdateSource::Url(url.clone())
|
||||
} else {
|
||||
providers::EngelsPolytechnicUpdateSource::GrabFromSite {
|
||||
yandex_api_key: env.yandex_cloud.api_key.clone(),
|
||||
yandex_func_id: env.yandex_cloud.func_id.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.await?,
|
||||
)]);
|
||||
|
||||
let this = Self {
|
||||
cancel_token: CancellationToken::new(),
|
||||
database: Mutex::new(
|
||||
PgConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url)),
|
||||
),
|
||||
env: AppEnv::default(),
|
||||
env,
|
||||
providers,
|
||||
fcm_client: FCMClientData::new().await,
|
||||
};
|
||||
|
||||
if _self.env.schedule.auto_update {
|
||||
_self
|
||||
.get_schedule()
|
||||
.await
|
||||
.init(_self.get_downloader().await.deref_mut(), &_self.env)
|
||||
.await?;
|
||||
if this.env.schedule.auto_update {
|
||||
for (_, provider) in &this.providers {
|
||||
let provider = provider.clone();
|
||||
let cancel_token = this.cancel_token.clone();
|
||||
|
||||
tokio::spawn(async move { provider.start_auto_update_task(cancel_token).await });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(_self)
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
pub async fn get_downloader(&'_ self) -> MutexGuard<'_, BasicXlsDownloader> {
|
||||
self.downloader.lock().await
|
||||
}
|
||||
pub async fn get_schedule_snapshot(&'_ self, provider: &str) -> Option<Arc<ScheduleSnapshot>> {
|
||||
if let Some(provider) = self.providers.get(provider) {
|
||||
return Some(provider.get_schedule().await);
|
||||
}
|
||||
|
||||
pub async fn get_schedule(&'_ self) -> MutexGuard<'_, Schedule> {
|
||||
self.schedule.lock().await
|
||||
}
|
||||
|
||||
pub async fn get_schedule_snapshot(&'_ self) -> MappedMutexGuard<'_, ScheduleSnapshot> {
|
||||
let snapshot =
|
||||
MutexGuard::<'_, Schedule>::map(self.schedule.lock().await, |schedule| unsafe {
|
||||
schedule.snapshot.assume_init_mut()
|
||||
});
|
||||
|
||||
snapshot
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn get_database(&'_ self) -> MutexGuard<'_, PgConnection> {
|
||||
@@ -83,6 +102,6 @@ impl AppState {
|
||||
}
|
||||
|
||||
/// Create a new object web::Data<AppState>.
|
||||
pub async fn new_app_state() -> Result<web::Data<AppState>, self::schedule::Error> {
|
||||
pub async fn new_app_state() -> Result<web::Data<AppState>, Box<dyn std::error::Error>> {
|
||||
Ok(web::Data::new(AppState::new().await?))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user