Skip to content

Commit

Permalink
chore: optimize cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Okabe-Rintarou-0 committed Sep 28, 2024
1 parent bbf6ad2 commit 37e5112
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 10 deletions.
17 changes: 9 additions & 8 deletions src-tauri/src/app/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
utils::{self, TempFile},
};

use super::App;
use super::{constants::COURSES_CACHE_KEY, App};

const MY_CANVAS_FILES_FOLDER_NAME: &str = "我的Canvas文件";

Expand Down Expand Up @@ -138,8 +138,9 @@ impl App {
Ok(())
}

async fn invalidate_cache(&self) {
*self.cached_courses.write().await = None;
fn invalidate_cache(&self) -> Result<()> {
self.cache.clear()?;
Ok(())
}

pub async fn switch_account(&self, account: &Account) -> Result<()> {
Expand All @@ -156,7 +157,7 @@ impl App {
account_info.current_account = account.clone();
App::save_account_info(&account_info)?;
*self.current_account.write().await = account.clone();
self.invalidate_cache().await;
self.invalidate_cache()?;
Ok(())
}

Expand Down Expand Up @@ -195,7 +196,7 @@ impl App {
current_account: RwLock::new(account_info.current_account),
config: RwLock::new(config),
handle: Default::default(),
cached_courses: Default::default(),
cache: Default::default(),
}
}

Expand Down Expand Up @@ -281,14 +282,14 @@ impl App {
}

pub async fn list_courses(&self) -> Result<Vec<Course>> {
if let Some(cached_courses) = self.cached_courses.read().await.clone() {
if let Some(cached_courses) = self.cache.get(COURSES_CACHE_KEY)? {
return Ok(cached_courses);
}
let courses = self
.client
.list_courses(&self.config.read().await.token)
.await?;
*self.cached_courses.write().await = Some(courses.clone());
self.cache.set(COURSES_CACHE_KEY, courses.clone())?;
Ok(courses)
}

Expand Down Expand Up @@ -798,7 +799,7 @@ impl App {
fs::write(&config_path, serde_json::to_vec(&config).unwrap())?;
let base_url = Self::get_base_url(&config.account_type);
if self.client.set_base_url(base_url).await {
self.invalidate_cache().await;
self.invalidate_cache()?;
}
*self.config.write().await = config;
Ok(())
Expand Down
110 changes: 110 additions & 0 deletions src-tauri/src/app/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use std::{collections::HashMap, sync::Mutex};

use serde::{de::DeserializeOwned, Serialize};

use crate::{
error::{AppError, Result},
utils::parse_json,
};

#[derive(Debug, Default)]
pub struct Cache {
inner: Mutex<HashMap<String, String>>,
}

impl Cache {
pub fn get<V>(&self, key: &str) -> Result<Option<V>>
where
V: DeserializeOwned + Serialize,
{
let cache = self.inner.lock().map_err(|_| AppError::MutexError)?;
let value = cache.get(key);
match value {
Some(v) => {
let value = parse_json(v.as_bytes())?;
Ok(Some(value))
}
None => Ok(None),
}
}

pub fn set<K, V>(&self, key: K, value: V) -> Result<()>
where
K: Into<String>,
V: DeserializeOwned + Serialize,
{
let mut cache = self.inner.lock().map_err(|_| AppError::MutexError)?;
let value = serde_json::to_string(&value)?;
cache.insert(key.into(), value);
Ok(())
}

pub fn clear(&self) -> Result<()> {
let mut cache = self.inner.lock().map_err(|_| AppError::MutexError)?;
cache.clear();
Ok(())
}

#[allow(dead_code)]
pub fn remove<V>(&self, key: &str) -> Result<Option<V>>
where
V: DeserializeOwned + Serialize,
{
let mut cache = self.inner.lock().map_err(|_| AppError::MutexError)?;

let value = cache.get(key);
match value {
Some(v) => {
let value = parse_json(v.as_bytes())?;
cache.remove(key);
Ok(Some(value))
}
None => Ok(None),
}
}
}

mod tests {
use super::*;
use serde::Deserialize;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
struct Person {
age: usize,
gender: String,
name: String,
}

#[derive(Serialize, Deserialize)]
struct Pet {
name: String,
owner: String,
}

#[test]
fn test_cache() -> Result<()> {
const PERSON_CACHE_KEY: &str = "person_cache_key";
let test_person = Person {
age: 25,
gender: "male".to_owned(),
name: "Alice".to_owned(),
};

let cache = Cache::default();

// person is not set yet
let mut person: Option<Person> = cache.get(PERSON_CACHE_KEY)?;
assert!(person.is_none());
// set person
cache.set(PERSON_CACHE_KEY, test_person.clone()).unwrap();
// person is now set
person = cache.get(PERSON_CACHE_KEY)?;
assert!(person.is_some());
assert_eq!(test_person, person.unwrap());

// try to get person as a pet, will fail
let result: Result<Option<Pet>> = cache.get(PERSON_CACHE_KEY);
assert!(result.is_err());
Ok(())
}
}
1 change: 1 addition & 0 deletions src-tauri/src/app/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const COURSES_CACHE_KEY: &str = "courses_cache_key";
7 changes: 5 additions & 2 deletions src-tauri/src/app/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use cache::Cache;
use std::sync::Arc;
use tokio::{sync::RwLock, task::JoinHandle};

use crate::{
client::Client,
model::{Account, AppConfig, Course},
model::{Account, AppConfig},
};
pub mod basic;
pub mod cache;
mod constants;
pub mod jbox;
pub mod video;

Expand All @@ -14,7 +17,7 @@ pub struct App {
current_account: RwLock<Account>,
config: RwLock<AppConfig>,
handle: RwLock<Option<JoinHandle<()>>>,
cached_courses: RwLock<Option<Vec<Course>>>,
cache: Cache,
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub enum AppError {
NotAllowedToDeleteDefaultAccount,
#[error("Not allowed to create default account")]
NotAllowedToCreateDefaultAccount,
#[error("Mutex error")]
MutexError,
}

impl serde::Serialize for AppError {
Expand Down

0 comments on commit 37e5112

Please sign in to comment.