Skip to main content

tdm_server_rust/cache/
episode_statistics_cache.rs

1//! 话数统计接口短 TTL JSON 缓存
2//!
3//! ## 使用说明
4//!
5//! | Key | 接口 |
6//! |-----|------|
7//! | `statistics_list` | `GET /api/episodes/statistics` |
8//! | `member_stats:{start}:{end}` | `GET /api/episodes/memberStatistics` |
9//!
10//! 接稿/交稿后调用 [`invalidate_episode_statistics`]。
11
12use crate::{
13    app::AppState,
14    cache::two_tier,
15    common::result::ResultBody,
16    entity::episode::{MemberStatistics, Statistics},
17    utils::fast_json,
18};
19use std::sync::Arc;
20
21/// 话数统计 JSON 缓存标记类型
22pub struct EpisodeStatisticsCache;
23
24/// 统计列表缓存键
25fn statistics_list_key() -> &'static str {
26    "statistics_list"
27}
28
29/// 读取 TTL 秒数
30fn cache_ttl_secs() -> u64 {
31    std::env::var("EPISODE_STATISTICS_CACHE_SECS")
32        .ok()
33        .and_then(|v| v.parse().ok())
34        .unwrap_or(60)
35}
36
37/// 创建话数统计缓存
38pub fn new_episode_statistics_cache() -> EpisodeStatisticsCache {
39    EpisodeStatisticsCache
40}
41
42/// 组员统计缓存键
43pub fn member_statistics_cache_key(_state: &AppState, start: &str, end: &str) -> String {
44    format!("member_stats:{start}:{end}")
45}
46
47/// 读取统计列表 JSON(Redis-only)
48pub async fn get_statistics_list_json_cached(state: &AppState) -> Option<Arc<Vec<u8>>> {
49    two_tier::get_json(&state.redis, statistics_list_key()).await
50}
51
52/// 写入统计列表 JSON(Redis-only)
53pub async fn set_statistics_list_json_cached(state: &AppState, data: Vec<Statistics>) {
54    let body = ResultBody::success_data(&data);
55    let json = match fast_json::to_vec(&body) {
56        Ok(bytes) => Arc::new(bytes),
57        Err(_) => return,
58    };
59    two_tier::set_json(
60        &state.redis,
61        statistics_list_key(),
62        json.as_ref(),
63        cache_ttl_secs(),
64    )
65    .await;
66}
67
68/// 读取组员统计 JSON(Redis-only)
69pub async fn get_member_statistics_json_cached(
70    state: &AppState,
71    key: &str,
72) -> Option<Arc<Vec<u8>>> {
73    two_tier::get_json(&state.redis, key).await
74}
75
76/// 写入组员统计 JSON(Redis-only)
77pub async fn set_member_statistics_json_cached(
78    state: &AppState,
79    key: String,
80    data: Vec<MemberStatistics>,
81) {
82    let body = ResultBody::success_data(&data);
83    let json = match fast_json::to_vec(&body) {
84        Ok(bytes) => Arc::new(bytes),
85        Err(_) => return,
86    };
87    two_tier::set_json(&state.redis, &key, json.as_ref(), cache_ttl_secs()).await;
88}
89
90/// 使全部话数统计缓存失效
91pub async fn invalidate_episode_statistics(state: &AppState) {
92    state.redis.del_json(statistics_list_key()).await;
93    state.redis.del_json_pattern("member_stats:*").await;
94}