refactor(saas): 架构重构 + 性能优化 — 借鉴 loco-rs 模式
Phase 0: 知识库
- docs/knowledge-base/loco-rs-patterns.md — loco-rs 10 个可借鉴模式研究
Phase 1: 数据层重构
- crates/zclaw-saas/src/models/ — 15 个 FromRow 类型化模型
- Login 3 次查询合并为 1 次 AccountLoginRow 查询
- 所有 service 文件从元组解构迁移到 FromRow 结构体
Phase 2: Worker + Scheduler 系统
- crates/zclaw-saas/src/workers/ — Worker trait + 5 个具体实现
- crates/zclaw-saas/src/scheduler.rs — TOML 声明式调度器
- crates/zclaw-saas/src/tasks/ — CLI 任务系统
Phase 3: 性能修复
- Relay N+1 查询 → 精准 SQL (relay/handlers.rs)
- Config RwLock → AtomicU32 无锁 rate limit (state.rs, middleware.rs)
- SSE std::sync::Mutex → tokio::sync::Mutex (relay/service.rs)
- /auth/refresh 阻塞清理 → Scheduler 定期执行
Phase 4: 多环境配置
- config/saas-{development,production,test}.toml
- ZCLAW_ENV 环境选择 + ZCLAW_SAAS_CONFIG 精确覆盖
- scheduler 配置集成到 TOML
This commit is contained in:
46
crates/zclaw-saas/src/workers/log_operation.rs
Normal file
46
crates/zclaw-saas/src/workers/log_operation.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
//! 异步操作日志 Worker
|
||||
|
||||
use async_trait::async_trait;
|
||||
use sqlx::PgPool;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::error::SaasResult;
|
||||
use super::Worker;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LogOperationArgs {
|
||||
pub account_id: String,
|
||||
pub action: String,
|
||||
pub target_type: String,
|
||||
pub target_id: String,
|
||||
pub details: Option<String>,
|
||||
pub ip_address: Option<String>,
|
||||
}
|
||||
|
||||
pub struct LogOperationWorker;
|
||||
|
||||
#[async_trait]
|
||||
impl Worker for LogOperationWorker {
|
||||
type Args = LogOperationArgs;
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"log_operation"
|
||||
}
|
||||
|
||||
async fn perform(&self, db: &PgPool, args: Self::Args) -> SaasResult<()> {
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
sqlx::query(
|
||||
"INSERT INTO operation_logs (account_id, action, target_type, target_id, details, ip_address, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)"
|
||||
)
|
||||
.bind(&args.account_id)
|
||||
.bind(&args.action)
|
||||
.bind(&args.target_type)
|
||||
.bind(&args.target_id)
|
||||
.bind(&args.details)
|
||||
.bind(&args.ip_address)
|
||||
.bind(&now)
|
||||
.execute(db)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user