Skip to main content

yggdrasil/api/settings/
webp.rs

1// 与 posts 模块一致:Leptos `#[server]` 宏触发 deprecated/unit/too_many_arguments
2// 提示,按项目惯例放行(限流/运行器等配置项天然参数多)。
3#![allow(clippy::unused_unit, deprecated, clippy::too_many_arguments)]
4
5use crate::api::error::ApiError;
6use leptos::prelude::*;
7
8#[cfg(feature = "server")]
9use crate::api::auth::get_current_admin_user;
10#[cfg(feature = "server")]
11use crate::api::error::AppError;
12#[cfg(feature = "server")]
13use crate::db::pool::get_conn;
14use crate::models::settings::WebpSettings;
15
16// ============================================================================
17// WebP 编码配置(需重启生效)
18// ============================================================================
19
20/// 启动时用 `WEBP_QUALITY` / `WEBP_METHOD` 环境变量播种 WebP 编码配置。
21///
22/// 语义与 [`seed_security_settings_from_env`][crate::api::settings::seed_security_settings_from_env] 一致:仅当对应 settings 键
23/// **不存在**时插入(首次部署),之后以面板写入的 DB 值为准。单个变量非法只
24/// 告警跳过。这些值在进程启动时烘焙进 LazyLock,改 DB 值后需重启生效。
25#[cfg(feature = "server")]
26pub(crate) async fn seed_webp_settings_from_env(
27    client: &tokio_postgres::Client,
28) -> Result<(), AppError> {
29    use crate::models::settings as m;
30
31    let mut seeds: Vec<(&'static str, String)> = Vec::new();
32
33    if let Ok(v) = std::env::var("WEBP_QUALITY") {
34        match v.trim().parse::<f32>() {
35            Ok(q) => seeds.push((
36                "webp_quality",
37                m::WebpSettings::clamp_quality(q).to_string(),
38            )),
39            Err(_) => tracing::warn!("WEBP_QUALITY={v:?} 非法(期望浮点数),跳过"),
40        }
41    }
42    if let Ok(v) = std::env::var("WEBP_METHOD") {
43        match v.trim().parse::<u32>() {
44            Ok(n) => seeds.push(("webp_method", m::WebpSettings::clamp_method(n).to_string())),
45            Err(_) => tracing::warn!("WEBP_METHOD={v:?} 非法(期望非负整数),跳过"),
46        }
47    }
48
49    super::insert_env_seeds(client, seeds).await
50}
51
52/// 从 settings 表读取 WebP 配置(缺键回退默认值)。
53///
54/// 启动时由 startup.rs 调用,将结果写入 `config::WEBP_CFG`,供 infra/webp.rs 的 LazyLock
55/// 在首次编码时读取。
56#[cfg(feature = "server")]
57pub(crate) async fn load_webp_settings(
58    client: &tokio_postgres::Client,
59) -> Result<WebpSettings, AppError> {
60    use crate::models::settings as m;
61
62    let values = super::load_setting_values(client, &["webp_quality", "webp_method"]).await?;
63    let quality = values
64        .get("webp_quality")
65        .and_then(|v| v.parse().ok())
66        .map(m::WebpSettings::clamp_quality)
67        .unwrap_or(m::DEFAULT_WEBP_QUALITY);
68    let method = values
69        .get("webp_method")
70        .and_then(|v| v.parse().ok())
71        .map(m::WebpSettings::clamp_method)
72        .unwrap_or(m::DEFAULT_WEBP_METHOD);
73
74    Ok(WebpSettings { quality, method })
75}
76
77/// 读取 WebP 配置(面板用)。
78#[server(GetWebpSettings, endpoint = "get_webp_settings", input = leptos::server_fn::codec::Json)]
79pub async fn get_webp_settings() -> Result<WebpSettings, ApiError> {
80    let _user = get_current_admin_user().await?;
81
82    #[cfg(feature = "server")]
83    {
84        let client = get_conn().await.map_err(AppError::db_conn)?;
85        let s = load_webp_settings(&client)
86            .await
87            .map_err(<ApiError>::from)?;
88        Ok(s)
89    }
90
91    #[cfg(not(feature = "server"))]
92    {
93        Ok(WebpSettings::default())
94    }
95}
96
97/// 更新 WebP 配置。
98///
99/// 字段会被 clamp 后写入 DB。由于配置烘焙进 LazyLock 静态量,修改后需**重启进程**
100/// 生效——不做运行时缓存失效。
101#[server(UpdateWebpSettings, endpoint = "update_webp_settings", input = leptos::server_fn::codec::Json)]
102pub async fn update_webp_settings(quality: f32, method: u32) -> Result<WebpSettings, ApiError> {
103    let _user = get_current_admin_user().await?;
104
105    let quality = WebpSettings::clamp_quality(quality);
106    let method = WebpSettings::clamp_method(method);
107
108    #[cfg(feature = "server")]
109    {
110        let client = get_conn().await.map_err(AppError::db_conn)?;
111
112        super::upsert_settings(
113            &**client,
114            &[
115                ("webp_quality", quality.to_string()),
116                ("webp_method", method.to_string()),
117            ],
118        )
119        .await?;
120
121        tracing::info!(
122            "WebP settings updated (需重启生效): quality={}, method={}",
123            quality,
124            method
125        );
126    }
127
128    Ok(WebpSettings { quality, method })
129}