Skip to main content

yggdrasil/api/settings/
ssr_cache.rs

1// 与 posts 模块一致:Leptos `#[server]` 宏触发 deprecated/unit 提示,按项目惯例放行。
2#![allow(clippy::unused_unit, deprecated)]
3
4use crate::api::error::ApiError;
5use leptos::prelude::*;
6
7#[cfg(feature = "server")]
8use crate::api::auth::get_current_admin_user;
9#[cfg(feature = "server")]
10use crate::api::error::AppError;
11#[cfg(feature = "server")]
12use crate::db::pool::get_conn;
13use crate::models::settings::SsrCacheSettings;
14
15// ============================================================================
16// SSR 页面缓存配置(需重启生效)
17// ============================================================================
18
19/// 启动时用 `SSR_CACHE_MAX_PAGE_BYTES`、`SSR_CACHE_EDGE_TTL_SECS` 环境变量播种 SSR 页面缓存配置。
20#[cfg(feature = "server")]
21pub(crate) async fn seed_ssr_cache_settings_from_env(
22    client: &tokio_postgres::Client,
23) -> Result<(), AppError> {
24    let mut seeds: Vec<(&'static str, String)> = Vec::new();
25
26    if let Ok(v) = std::env::var("SSR_CACHE_MAX_PAGE_BYTES") {
27        match v.trim().parse::<u64>() {
28            Ok(n) => seeds.push((
29                "ssr_cache_max_page_bytes",
30                SsrCacheSettings::clamp_max_page_bytes(n).to_string(),
31            )),
32            Err(_) => tracing::warn!("SSR_CACHE_MAX_PAGE_BYTES={v:?} 非法(期望正整数),跳过"),
33        }
34    }
35    if let Ok(v) = std::env::var("SSR_CACHE_EDGE_TTL_SECS") {
36        match v.trim().parse::<u64>() {
37            Ok(n) => seeds.push((
38                "ssr_cache_edge_ttl_secs",
39                SsrCacheSettings::clamp_edge_ttl_secs(n).to_string(),
40            )),
41            Err(_) => tracing::warn!("SSR_CACHE_EDGE_TTL_SECS={v:?} 非法(期望非负整数),跳过"),
42        }
43    }
44
45    super::insert_env_seeds(client, seeds).await
46}
47
48/// 从 settings 表读取 SSR 页面缓存配置(缺键回退默认值)。
49#[cfg(feature = "server")]
50pub(crate) async fn load_ssr_cache_settings(
51    client: &tokio_postgres::Client,
52) -> Result<SsrCacheSettings, AppError> {
53    let values = super::load_setting_values(
54        client,
55        &["ssr_cache_max_page_bytes", "ssr_cache_edge_ttl_secs"],
56    )
57    .await?;
58    let max_page_bytes = values
59        .get("ssr_cache_max_page_bytes")
60        .and_then(|v| v.parse().ok())
61        .map(SsrCacheSettings::clamp_max_page_bytes)
62        .unwrap_or(crate::models::settings::DEFAULT_SSR_CACHE_MAX_PAGE_BYTES);
63    let edge_ttl_secs = values
64        .get("ssr_cache_edge_ttl_secs")
65        .and_then(|v| v.parse().ok())
66        .map(SsrCacheSettings::clamp_edge_ttl_secs)
67        .unwrap_or(0);
68
69    Ok(SsrCacheSettings {
70        max_page_bytes,
71        edge_ttl_secs,
72    })
73}
74
75/// 读取 SSR 页面缓存配置(面板用)。
76#[server(GetSsrCacheSettings, endpoint = "get_ssr_cache_settings", input = leptos::server_fn::codec::Json)]
77pub async fn get_ssr_cache_settings() -> Result<SsrCacheSettings, ApiError> {
78    let _user = get_current_admin_user().await?;
79
80    #[cfg(feature = "server")]
81    {
82        let client = get_conn().await.map_err(AppError::db_conn)?;
83        let s = load_ssr_cache_settings(&client)
84            .await
85            .map_err(<ApiError>::from)?;
86        Ok(s)
87    }
88
89    #[cfg(not(feature = "server"))]
90    {
91        Ok(SsrCacheSettings::default())
92    }
93}
94
95/// 更新 SSR 页面缓存配置。
96///
97/// 字段会被 clamp 后写入 DB。HTML 缓存首次使用时读取,修改后需**重启进程**生效。
98#[server(UpdateSsrCacheSettings, endpoint = "update_ssr_cache_settings", input = leptos::server_fn::codec::Json)]
99pub async fn update_ssr_cache_settings(
100    max_page_bytes: u64,
101    edge_ttl_secs: u64,
102) -> Result<SsrCacheSettings, ApiError> {
103    let _user = get_current_admin_user().await?;
104
105    #[cfg(feature = "server")]
106    {
107        let max_page_bytes = SsrCacheSettings::clamp_max_page_bytes(max_page_bytes);
108        let edge_ttl_secs = SsrCacheSettings::clamp_edge_ttl_secs(edge_ttl_secs);
109        let client = get_conn().await.map_err(AppError::db_conn)?;
110        super::upsert_setting(
111            &**client,
112            "ssr_cache_max_page_bytes",
113            &max_page_bytes.to_string(),
114        )
115        .await?;
116        super::upsert_setting(
117            &**client,
118            "ssr_cache_edge_ttl_secs",
119            &edge_ttl_secs.to_string(),
120        )
121        .await?;
122
123        tracing::info!(
124            "SSR cache settings updated (需重启生效): max_page_bytes={max_page_bytes}, edge_ttl_secs={edge_ttl_secs}"
125        );
126        Ok(SsrCacheSettings {
127            max_page_bytes,
128            edge_ttl_secs,
129        })
130    }
131
132    #[cfg(not(feature = "server"))]
133    {
134        Ok(SsrCacheSettings {
135            max_page_bytes,
136            edge_ttl_secs,
137        })
138    }
139}