fix(saas): P1 审计修复 — 连接池断路器 + Worker重试 + XSS防护 + 状态机SQL解析器

P1 修复内容:
- F7: health handler 连接池容量检查 (80%阈值返回503 degraded)
- F9: SSE spawned task 并发限制 (Semaphore 16 permits)
- F10: Key Pool 单次 JOIN 查询优化 (消除 N+1)
- F12: CORS panic → 配置错误
- F14: 连接池使用率计算修正 (ratio = used*100/total)
- F15: SQL 迁移解析器替换为状态机 (支持 $$, DO $body$, 存储过程)
- Worker 重试机制: 失败任务通过 mpsc channel 重新入队
- DOMPurify XSS 防护 (PipelineResultPreview)
- Admin V2: ErrorBoundary + SWR全局配置 + 请求优化
This commit is contained in:
iven
2026-03-30 14:21:39 +08:00
parent bc8c77e7fe
commit ba2c6a6105
38 changed files with 490 additions and 236 deletions

View File

@@ -155,6 +155,7 @@ impl WorkerDispatcher {
fn start_consumer(&self, mut receiver: mpsc::Receiver<TaskMessage>) {
let db = self.db.clone();
let handlers = self.handlers.clone();
let sender = self.sender.clone();
tokio::spawn(async move {
while let Some(msg) = receiver.recv().await {
@@ -169,6 +170,7 @@ impl WorkerDispatcher {
let worker_name = msg.worker_name.clone();
let max_retries = handler.max_retries();
let db = db.clone();
let sender = sender.clone();
tokio::spawn(async move {
match handler.perform(&db, &msg.args_json).await {
@@ -177,18 +179,27 @@ impl WorkerDispatcher {
}
Err(e) => {
if msg.attempt < max_retries {
tracing::warn!(
"Worker {} failed (attempt {}/{}): {}. Will retry.",
worker_name, msg.attempt, max_retries, e
);
// 简单退避: 2^attempt 秒
let delay = std::time::Duration::from_secs(1 << msg.attempt.min(4));
tracing::warn!(
"Worker {} failed (attempt {}/{}): {}. Re-queuing after {:?}.",
worker_name, msg.attempt, max_retries, e, delay
);
tokio::time::sleep(delay).await;
// 注意: 重试在当前设计中通过日志提醒
// 生产环境应将任务重新入队
// 重新入队(递增 attempt 计数)
let retry_msg = TaskMessage {
worker_name: msg.worker_name.clone(),
args_json: msg.args_json.clone(),
attempt: msg.attempt + 1,
};
if let Err(send_err) = sender.send(retry_msg).await {
tracing::error!(
"Worker {} retry enqueue failed (channel closed): {}",
worker_name, send_err
);
}
} else {
tracing::error!(
"Worker {} failed after {} attempts: {}",
"Worker {} failed after {} attempts: {}. Giving up.",
worker_name, max_retries, e
);
}