Skip to main content

tdm_server_rust/cache/
manga_name_cache.rs

1//! 漫画译名/原名列表缓存
2//!
3//! 缓存全量漫画的译名和原名 ID→名称映射列表。
4//! 用于前端下拉选择框和漫画名称搜索。
5//! TTL 默认 60 秒,可通过 `MANGA_NAME_CACHE_SECS` 环境变量调整。
6//!
7//! ## 缓存设计
8//!
9//! - **单 Key**: 译名与原名各一个条目,存储全量列表
10//! - **Value**: `Vec<MangaSimpleVo>`(包含 ID 和名称的简 VO 列表)
11//! - **失效**: 漫画增删改后调用 [`invalidate_manga_names`] 同时失效译名和原名缓存
12
13use crate::{app::AppState, entity::manga::MangaSimpleVo};
14
15/// 译名缓存键
16const TRAN_CACHE_KEY: &str = "manga_tran_names";
17/// 原名缓存键
18const ORI_CACHE_KEY: &str = "manga_ori_names";
19/// 结构化值缓存命名空间
20const VALUE_NS: &str = "manga_names";
21
22/// 译名/原名列表缓存标记类型
23pub struct MangaTranNameCache;
24
25/// 创建译名/原名列表缓存实例
26///
27/// TTL 由环境变量 `MANGA_NAME_CACHE_SECS` 控制,默认 60 秒。
28pub fn new_manga_tran_name_cache() -> MangaTranNameCache {
29    MangaTranNameCache
30}
31
32/// 使译名和原名列表缓存同时失效
33///
34/// 漫画新增、更新、删除后调用。
35pub async fn invalidate_manga_names(state: &AppState) {
36    state.redis.del_value(VALUE_NS, TRAN_CACHE_KEY).await;
37    state.redis.del_value(VALUE_NS, ORI_CACHE_KEY).await;
38}
39
40/// 获取缓存键名
41pub fn cache_key() -> &'static str {
42    TRAN_CACHE_KEY
43}
44
45/// 读取译名列表缓存
46pub async fn get_manga_tran_names_cached(state: &AppState) -> Option<Vec<MangaSimpleVo>> {
47    state.redis.get_value(VALUE_NS, TRAN_CACHE_KEY).await
48}
49
50/// 写入译名列表缓存
51pub async fn set_manga_tran_names_cached(state: &AppState, data: &[MangaSimpleVo]) {
52    state
53        .redis
54        .set_value_ttl(VALUE_NS, TRAN_CACHE_KEY, &data, cache_ttl_secs())
55        .await;
56}
57
58/// 读取原名列表缓存
59pub async fn get_manga_ori_names_cached(state: &AppState) -> Option<Vec<MangaSimpleVo>> {
60    state.redis.get_value(VALUE_NS, ORI_CACHE_KEY).await
61}
62
63/// 写入原名列表缓存
64pub async fn set_manga_ori_names_cached(state: &AppState, data: &[MangaSimpleVo]) {
65    state
66        .redis
67        .set_value_ttl(VALUE_NS, ORI_CACHE_KEY, &data, cache_ttl_secs())
68        .await;
69}
70
71/// 读取 TTL 秒数
72fn cache_ttl_secs() -> u64 {
73    std::env::var("MANGA_NAME_CACHE_SECS")
74        .ok()
75        .and_then(|v| v.parse().ok())
76        .unwrap_or(60)
77}