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:
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user