use crate::activity_summary::ActivitySummaryResponse;
use crate::error::FitbitError;
use crate::fitbit_client::FitbitClientTrait;
use crate::sleep::SleepResponseV1_2;
use chrono::NaiveDate;
use std::collections::HashMap;
pub struct FitbitResponseCache<C: FitbitClientTrait> {
fitbit_client: C,
sleep_responses: HashMap<NaiveDate, SleepResponseV1_2>,
activity_summary_responses: HashMap<NaiveDate, ActivitySummaryResponse>,
}
impl<C: FitbitClientTrait> FitbitResponseCache<C> {
pub fn new(fitbit_client: C) -> Self {
Self {
fitbit_client,
sleep_responses: HashMap::new(),
activity_summary_responses: HashMap::new(),
}
}
pub fn get_sleep_response(
&mut self,
date: NaiveDate,
) -> Result<&SleepResponseV1_2, FitbitError> {
if !self.sleep_responses.contains_key(&date) {
let response = self.fitbit_client.fetch_sleep_data(date)?;
self.sleep_responses.insert(date, response);
}
Ok(self.sleep_responses.get(&date).unwrap())
}
pub fn get_activity_summary_response(
&mut self,
date: NaiveDate,
) -> Result<&ActivitySummaryResponse, FitbitError> {
if !self.activity_summary_responses.contains_key(&date) {
let response = self.fitbit_client.fetch_activity_summary(date)?;
self.activity_summary_responses.insert(date, response);
}
Ok(self.activity_summary_responses.get(&date).unwrap())
}
pub fn clear_cache(&mut self) {
self.sleep_responses.clear();
self.activity_summary_responses.clear();
}
pub fn remove_from_cache(&mut self, date: NaiveDate) {
self.sleep_responses.remove(&date);
self.activity_summary_responses.remove(&date);
}
pub fn client(&self) -> &C {
&self.fitbit_client
}
}
#[cfg(test)]
mod response_cache_tests {
use super::*;
use crate::fitbit_client::MockFitbitClientTrait;
use chrono::NaiveDate;
use mockall::predicate::*;
#[test]
fn test_cache_behavior() -> Result<(), FitbitError> {
let mut mock_client = MockFitbitClientTrait::new();
let date = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
mock_client
.expect_fetch_sleep_data()
.with(eq(date))
.times(1)
.returning(|_| Ok(create_mock_sleep_response()));
let mut cache = FitbitResponseCache::new(mock_client);
let _response1 = cache.get_sleep_response(date)?;
let _response2 = cache.get_sleep_response(date)?;
Ok(())
}
#[test]
fn test_clear_cache() -> Result<(), FitbitError> {
let mut mock_client = MockFitbitClientTrait::new();
let date = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
mock_client
.expect_fetch_sleep_data()
.with(eq(date))
.times(2)
.returning(|_| Ok(create_mock_sleep_response()));
let mut cache = FitbitResponseCache::new(mock_client);
let _response1 = cache.get_sleep_response(date)?;
cache.clear_cache();
let _response2 = cache.get_sleep_response(date)?;
Ok(())
}
#[test]
fn test_remove_from_cache() -> Result<(), FitbitError> {
let mut mock_client = MockFitbitClientTrait::new();
let date = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
mock_client
.expect_fetch_sleep_data()
.with(eq(date))
.times(2)
.returning(|_| Ok(create_mock_sleep_response()));
let mut cache = FitbitResponseCache::new(mock_client);
let _response1 = cache.get_sleep_response(date)?;
cache.remove_from_cache(date);
let _response2 = cache.get_sleep_response(date)?;
Ok(())
}
fn create_mock_sleep_response() -> SleepResponseV1_2 {
SleepResponseV1_2::default()
}
}