tdm_server_rust/cache/
task_tracking_cache.rs1use crate::{
19 app::AppState,
20 common::{page_bean::PageBean, result::ResultBody},
21 entity::episode::{MemberTaskCount, PendingMangaTask, TaskTrackingResponse},
22 utils::fast_json,
23};
24use std::sync::Arc;
25
26const EPISODE_TASKS_KEY: &str = "episode_tasks";
28const MEMBER_TASK_COUNTS_KEY: &str = "member_task_counts";
30const VALUE_NS: &str = "task_tracking";
32
33#[derive(Clone)]
35pub struct EpisodeTasksCacheEntry {
36 pub data: TaskTrackingResponse,
38 pub json: Arc<Vec<u8>>,
40}
41
42#[derive(Clone)]
44pub struct MemberTaskCountsCacheEntry {
45 pub data: Vec<MemberTaskCount>,
47 pub json: Arc<Vec<u8>>,
49}
50
51pub struct EpisodeTasksCache;
53pub struct MemberTaskCountsCache;
55pub struct PendingMangaTasksCache;
57
58fn cache_ttl_secs() -> u64 {
60 std::env::var("TASK_TRACKING_CACHE_SECS")
61 .ok()
62 .and_then(|v| v.parse().ok())
63 .unwrap_or(60)
64}
65
66pub fn new_episode_tasks_cache() -> EpisodeTasksCache {
68 EpisodeTasksCache
69}
70
71pub fn new_member_task_counts_cache() -> MemberTaskCountsCache {
73 MemberTaskCountsCache
74}
75
76pub fn new_pending_manga_tasks_cache() -> PendingMangaTasksCache {
78 PendingMangaTasksCache
79}
80
81pub fn pending_manga_cache_key(page: i32, page_size: i32, manga_tran_name: Option<&str>) -> String {
83 format!(
84 "pending:{page}:{page_size}:{}",
85 manga_tran_name.unwrap_or("")
86 )
87}
88
89pub async fn get_episode_tasks_json_cached(state: &AppState) -> Option<Arc<Vec<u8>>> {
91 state.redis.get_json_bytes(EPISODE_TASKS_KEY).await
92}
93
94pub async fn get_episode_tasks_cached(state: &AppState) -> Option<TaskTrackingResponse> {
96 state.redis.get_value(VALUE_NS, EPISODE_TASKS_KEY).await
97}
98
99pub async fn set_episode_tasks_cached(state: &AppState, data: TaskTrackingResponse) {
101 let body = ResultBody::success_data(&data);
102 let json = match fast_json::to_vec(&body) {
103 Ok(bytes) => Arc::new(bytes),
104 Err(_) => return,
105 };
106 state
107 .redis
108 .set_json_bytes_ttl(EPISODE_TASKS_KEY, json.as_ref(), cache_ttl_secs())
109 .await;
110 state
111 .redis
112 .set_value_ttl(VALUE_NS, EPISODE_TASKS_KEY, &data, cache_ttl_secs())
113 .await;
114}
115
116pub async fn get_member_task_counts_json_cached(state: &AppState) -> Option<Arc<Vec<u8>>> {
118 state.redis.get_json_bytes(MEMBER_TASK_COUNTS_KEY).await
119}
120
121pub async fn get_member_task_counts_cached(state: &AppState) -> Option<Vec<MemberTaskCount>> {
123 state
124 .redis
125 .get_value(VALUE_NS, MEMBER_TASK_COUNTS_KEY)
126 .await
127}
128
129pub async fn set_member_task_counts_cached(state: &AppState, data: Vec<MemberTaskCount>) {
131 let body = ResultBody::success_data(&data);
132 let json = match fast_json::to_vec(&body) {
133 Ok(bytes) => Arc::new(bytes),
134 Err(_) => return,
135 };
136 state
137 .redis
138 .set_json_bytes_ttl(MEMBER_TASK_COUNTS_KEY, json.as_ref(), cache_ttl_secs())
139 .await;
140 state
141 .redis
142 .set_value_ttl(VALUE_NS, MEMBER_TASK_COUNTS_KEY, &data, cache_ttl_secs())
143 .await;
144}
145
146pub async fn invalidate_task_tracking(state: &AppState) {
150 state.redis.del_json(EPISODE_TASKS_KEY).await;
151 state.redis.del_json(MEMBER_TASK_COUNTS_KEY).await;
152 state.redis.del_value(VALUE_NS, EPISODE_TASKS_KEY).await;
153 state
154 .redis
155 .del_value(VALUE_NS, MEMBER_TASK_COUNTS_KEY)
156 .await;
157 state.redis.del_value_pattern(VALUE_NS, "pending:*").await;
158}
159
160pub async fn get_pending_manga_tasks_cached(
162 state: &AppState,
163 key: &str,
164) -> Option<PageBean<PendingMangaTask>> {
165 state.redis.get_value(VALUE_NS, key).await
166}
167
168pub async fn set_pending_manga_tasks_cached(
170 state: &AppState,
171 key: String,
172 data: PageBean<PendingMangaTask>,
173) {
174 state
175 .redis
176 .set_value_ttl(VALUE_NS, &key, &data, cache_ttl_secs())
177 .await;
178}