Skip to main content

yggdrasil/api/settings/
asset_purge.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::AssetPurgeSettings;
15
16// ============================================================================
17// 孤儿素材自动清理配置(即时生效)
18// ============================================================================
19
20/// 启动时用 `ASSET_ORPHAN_PURGE_*` 环境变量播种孤儿素材清理配置。
21///
22/// 语义与 [`seed_image_cache_settings_from_env`][crate::api::settings::seed_image_cache_settings_from_env] 一致:仅当对应 settings 键
23/// **不存在**时插入(首次部署),之后以面板写入的 DB 值为准,重启不被 env 覆盖。
24/// 单个变量非法只告警跳过,不影响启动。
25#[cfg(feature = "server")]
26pub(crate) async fn seed_asset_purge_settings_from_env(
27    client: &tokio_postgres::Client,
28) -> Result<(), AppError> {
29    let mut seeds: Vec<(&'static str, String)> = Vec::new();
30
31    if let Ok(v) = std::env::var("ASSET_ORPHAN_PURGE_ENABLED") {
32        match v.trim().parse::<bool>() {
33            Ok(b) => seeds.push(("asset_orphan_purge_enabled", b.to_string())),
34            Err(_) => {
35                tracing::warn!("ASSET_ORPHAN_PURGE_ENABLED={v:?} 非法(期望 true/false),跳过")
36            }
37        }
38    }
39    if let Ok(v) = std::env::var("ASSET_ORPHAN_RETENTION_DAYS") {
40        match v.trim().parse::<i32>() {
41            Ok(n) => seeds.push((
42                "asset_orphan_retention_days",
43                crate::models::settings::AssetPurgeSettings::clamp_retention(n).to_string(),
44            )),
45            Err(_) => {
46                tracing::warn!("ASSET_ORPHAN_RETENTION_DAYS={v:?} 非法(期望正整数),跳过")
47            }
48        }
49    }
50
51    super::insert_env_seeds(client, seeds).await
52}
53
54/// 读取孤儿素材清理配置(面板用)。
55///
56/// settings 表缺失键时回退到默认值,保证向后兼容。
57#[server(GetAssetPurgeSettings, endpoint = "get_asset_purge_settings", input = leptos::server_fn::codec::Json)]
58pub async fn get_asset_purge_settings() -> Result<AssetPurgeSettings, ApiError> {
59    let _user = get_current_admin_user().await?;
60
61    #[cfg(feature = "server")]
62    {
63        let client = get_conn().await.map_err(AppError::db_conn)?;
64
65        let values = super::load_setting_values(
66            &client,
67            &["asset_orphan_purge_enabled", "asset_orphan_retention_days"],
68        )
69        .await?;
70        let enabled = values
71            .get("asset_orphan_purge_enabled")
72            .and_then(|v| v.parse().ok())
73            .unwrap_or(crate::models::settings::DEFAULT_ASSET_ORPHAN_PURGE_ENABLED);
74        let days = values
75            .get("asset_orphan_retention_days")
76            .and_then(|v| v.parse().ok())
77            .unwrap_or(crate::models::settings::DEFAULT_ASSET_ORPHAN_RETENTION_DAYS);
78
79        Ok(AssetPurgeSettings {
80            auto_purge_enabled: enabled,
81            retention_days: AssetPurgeSettings::clamp_retention(days),
82        })
83    }
84
85    #[cfg(not(feature = "server"))]
86    {
87        Ok(AssetPurgeSettings::default())
88    }
89}
90
91/// 更新孤儿素材清理配置。
92///
93/// retention_days 会被 clamp 到合法范围后写入。清理任务每天 tick 时读取
94/// 最新值,无需重启。
95#[server(UpdateAssetPurgeSettings, endpoint = "update_asset_purge_settings", input = leptos::server_fn::codec::Json)]
96pub async fn update_asset_purge_settings(
97    auto_purge_enabled: bool,
98    retention_days: i32,
99) -> Result<AssetPurgeSettings, ApiError> {
100    let _user = get_current_admin_user().await?;
101
102    let retention_days = AssetPurgeSettings::clamp_retention(retention_days);
103
104    #[cfg(feature = "server")]
105    {
106        let client = get_conn().await.map_err(AppError::db_conn)?;
107
108        super::upsert_settings(
109            &**client,
110            &[
111                ("asset_orphan_purge_enabled", auto_purge_enabled.to_string()),
112                ("asset_orphan_retention_days", retention_days.to_string()),
113            ],
114        )
115        .await?;
116
117        tracing::info!(
118            "Asset purge settings updated: auto_purge={}, retention_days={}",
119            auto_purge_enabled,
120            retention_days
121        );
122    }
123
124    Ok(AssetPurgeSettings {
125        auto_purge_enabled,
126        retention_days,
127    })
128}