use crate::asynch::datasource::{Error, ReadOnlyDataSource, ReadWriteDataSource};
use crate::lectures::entities::StaticDegree;
use crate::lectures::entities::Lecture;
#[derive(Default)]
pub struct LectureRepository<'a> {
sources: Vec<Box<dyn ReadWriteDataSource + 'a>>,
read_only_sources: Vec<Box<dyn ReadOnlyDataSource + 'a>>,
}
impl<'a> LectureRepository<'a> {
pub fn new() -> Self {
LectureRepository {
sources: Vec::new(),
read_only_sources: Vec::new(),
}
}
pub fn add_source(&mut self, source: impl ReadWriteDataSource + 'a) {
self.sources.push(Box::new(source));
}
pub fn source(mut self, source: impl ReadWriteDataSource + 'a) -> Self {
self.add_source(source);
self
}
pub fn add_readonly_source(&mut self, source: impl ReadOnlyDataSource + 'a) {
self.read_only_sources.push(Box::new(source));
}
pub fn readonly_source(mut self, source: impl ReadOnlyDataSource + 'a) -> Self {
self.add_readonly_source(source);
self
}
pub async fn load_and_update(&self, degree: &'static StaticDegree) -> Result<Vec<Lecture>, Error> {
match self.try_loading(degree).await {
Some(lectures) => {
for rw in &self.sources {
if let Err(e) = rw.save_lectures(degree, &lectures).await {
eprintln!("Error saving lecture to some datasource with error: {}", e);
}
}
Ok(lectures)
}
None => Err(format!(
"No source returned lectures for degree {}",
degree.name
)),
}
}
async fn try_loading(&self, degree: &'static StaticDegree) -> Option<Vec<Lecture>> {
for source in &self.sources {
match source.load_lectures(degree).await {
Ok(result) => return Some(result),
Err(_) => continue,
}
}
for source in &self.read_only_sources {
match source.load_lectures(degree).await {
Ok(result) => return Some(result),
Err(_) => continue,
}
}
None
}
}