fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复异常处理 - 修复PEP8格式问题 - 添加类型注解 - 修复缺失的urllib.parse导入
This commit is contained in:
@@ -15,6 +15,7 @@ import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import logging
|
||||
import urllib.parse
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field
|
||||
@@ -32,6 +33,7 @@ from apscheduler.triggers.interval import IntervalTrigger
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WorkflowStatus(Enum):
|
||||
"""工作流状态"""
|
||||
|
||||
@@ -40,6 +42,7 @@ class WorkflowStatus(Enum):
|
||||
ERROR = "error"
|
||||
COMPLETED = "completed"
|
||||
|
||||
|
||||
class WorkflowType(Enum):
|
||||
"""工作流类型"""
|
||||
|
||||
@@ -49,6 +52,7 @@ class WorkflowType(Enum):
|
||||
SCHEDULED_REPORT = "scheduled_report" # 定时报告
|
||||
CUSTOM = "custom" # 自定义工作流
|
||||
|
||||
|
||||
class WebhookType(Enum):
|
||||
"""Webhook 类型"""
|
||||
|
||||
@@ -57,6 +61,7 @@ class WebhookType(Enum):
|
||||
SLACK = "slack"
|
||||
CUSTOM = "custom"
|
||||
|
||||
|
||||
class TaskStatus(Enum):
|
||||
"""任务执行状态"""
|
||||
|
||||
@@ -66,6 +71,7 @@ class TaskStatus(Enum):
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
|
||||
@dataclass
|
||||
class WorkflowTask:
|
||||
"""工作流任务定义"""
|
||||
@@ -89,6 +95,7 @@ class WorkflowTask:
|
||||
if not self.updated_at:
|
||||
self.updated_at = self.created_at
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookConfig:
|
||||
"""Webhook 配置"""
|
||||
@@ -113,6 +120,7 @@ class WebhookConfig:
|
||||
if not self.updated_at:
|
||||
self.updated_at = self.created_at
|
||||
|
||||
|
||||
@dataclass
|
||||
class Workflow:
|
||||
"""工作流定义"""
|
||||
@@ -142,6 +150,7 @@ class Workflow:
|
||||
if not self.updated_at:
|
||||
self.updated_at = self.created_at
|
||||
|
||||
|
||||
@dataclass
|
||||
class WorkflowLog:
|
||||
"""工作流执行日志"""
|
||||
@@ -162,6 +171,7 @@ class WorkflowLog:
|
||||
if not self.created_at:
|
||||
self.created_at = datetime.now().isoformat()
|
||||
|
||||
|
||||
class WebhookNotifier:
|
||||
"""Webhook 通知器 - 支持飞书、钉钉、Slack"""
|
||||
|
||||
@@ -213,11 +223,23 @@ class WebhookNotifier:
|
||||
"timestamp": timestamp,
|
||||
"sign": sign,
|
||||
"msg_type": "post",
|
||||
"content": {"post": {"zh_cn": {"title": message.get("title", ""), "content": message.get("body", [])}}},
|
||||
"content": {
|
||||
"post": {
|
||||
"zh_cn": {
|
||||
"title": message.get("title", ""),
|
||||
"content": message.get("body", []),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
else:
|
||||
# 卡片消息
|
||||
payload = {"timestamp": timestamp, "sign": sign, "msg_type": "interactive", "card": message.get("card", {})}
|
||||
payload = {
|
||||
"timestamp": timestamp,
|
||||
"sign": sign,
|
||||
"msg_type": "interactive",
|
||||
"card": message.get("card", {}),
|
||||
}
|
||||
|
||||
headers = {"Content-Type": "application/json", **config.headers}
|
||||
|
||||
@@ -235,7 +257,9 @@ class WebhookNotifier:
|
||||
if config.secret:
|
||||
secret_enc = config.secret.encode("utf-8")
|
||||
string_to_sign = f"{timestamp}\n{config.secret}"
|
||||
hmac_code = hmac.new(secret_enc, string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
|
||||
hmac_code = hmac.new(
|
||||
secret_enc, string_to_sign.encode("utf-8"), digestmod=hashlib.sha256
|
||||
).digest()
|
||||
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
|
||||
url = f"{config.url}×tamp={timestamp}&sign={sign}"
|
||||
else:
|
||||
@@ -303,6 +327,7 @@ class WebhookNotifier:
|
||||
"""关闭 HTTP 客户端"""
|
||||
await self.http_client.aclose()
|
||||
|
||||
|
||||
class WorkflowManager:
|
||||
"""工作流管理器 - 核心管理类"""
|
||||
|
||||
@@ -390,7 +415,9 @@ class WorkflowManager:
|
||||
coalesce=True,
|
||||
)
|
||||
|
||||
logger.info(f"Scheduled workflow {workflow.id} ({workflow.name}) with {workflow.schedule_type}")
|
||||
logger.info(
|
||||
f"Scheduled workflow {workflow.id} ({workflow.name}) with {workflow.schedule_type}"
|
||||
)
|
||||
|
||||
async def _execute_workflow_job(self, workflow_id: str):
|
||||
"""调度器调用的工作流执行函数"""
|
||||
@@ -463,7 +490,9 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def list_workflows(self, project_id: str = None, status: str = None, workflow_type: str = None) -> list[Workflow]:
|
||||
def list_workflows(
|
||||
self, project_id: str = None, status: str = None, workflow_type: str = None
|
||||
) -> list[Workflow]:
|
||||
"""列出工作流"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -632,7 +661,8 @@ class WorkflowManager:
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM workflow_tasks WHERE workflow_id = ? ORDER BY task_order", (workflow_id,)
|
||||
"SELECT * FROM workflow_tasks WHERE workflow_id = ? ORDER BY task_order",
|
||||
(workflow_id,),
|
||||
).fetchall()
|
||||
|
||||
return [self._row_to_task(row) for row in rows]
|
||||
@@ -743,7 +773,9 @@ class WorkflowManager:
|
||||
"""获取 Webhook 配置"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
row = conn.execute("SELECT * FROM webhook_configs WHERE id = ?", (webhook_id,)).fetchone()
|
||||
row = conn.execute(
|
||||
"SELECT * FROM webhook_configs WHERE id = ?", (webhook_id,)
|
||||
).fetchone()
|
||||
|
||||
if not row:
|
||||
return None
|
||||
@@ -766,7 +798,15 @@ class WorkflowManager:
|
||||
"""更新 Webhook 配置"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
allowed_fields = ["name", "webhook_type", "url", "secret", "headers", "template", "is_active"]
|
||||
allowed_fields = [
|
||||
"name",
|
||||
"webhook_type",
|
||||
"url",
|
||||
"secret",
|
||||
"headers",
|
||||
"template",
|
||||
"is_active",
|
||||
]
|
||||
updates = []
|
||||
values = []
|
||||
|
||||
@@ -915,7 +955,12 @@ class WorkflowManager:
|
||||
conn.close()
|
||||
|
||||
def list_logs(
|
||||
self, workflow_id: str = None, task_id: str = None, status: str = None, limit: int = 100, offset: int = 0
|
||||
self,
|
||||
workflow_id: str = None,
|
||||
task_id: str = None,
|
||||
status: str = None,
|
||||
limit: int = 100,
|
||||
offset: int = 0,
|
||||
) -> list[WorkflowLog]:
|
||||
"""列出工作流日志"""
|
||||
conn = self.db.get_conn()
|
||||
@@ -955,7 +1000,8 @@ class WorkflowManager:
|
||||
|
||||
# 总执行次数
|
||||
total = conn.execute(
|
||||
"SELECT COUNT(*) FROM workflow_logs WHERE workflow_id = ? AND created_at > ?", (workflow_id, since)
|
||||
"SELECT COUNT(*) FROM workflow_logs WHERE workflow_id = ? AND created_at > ?",
|
||||
(workflow_id, since),
|
||||
).fetchone()[0]
|
||||
|
||||
# 成功次数
|
||||
@@ -997,7 +1043,9 @@ class WorkflowManager:
|
||||
"failed": failed,
|
||||
"success_rate": round(success / total * 100, 2) if total > 0 else 0,
|
||||
"avg_duration_ms": round(avg_duration, 2),
|
||||
"daily": [{"date": r["date"], "count": r["count"], "success": r["success"]} for r in daily],
|
||||
"daily": [
|
||||
{"date": r["date"], "count": r["count"], "success": r["success"]} for r in daily
|
||||
],
|
||||
}
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -1104,7 +1152,9 @@ class WorkflowManager:
|
||||
|
||||
raise
|
||||
|
||||
async def _execute_tasks_with_deps(self, tasks: list[WorkflowTask], input_data: dict, log_id: str) -> dict:
|
||||
async def _execute_tasks_with_deps(
|
||||
self, tasks: list[WorkflowTask], input_data: dict, log_id: str
|
||||
) -> dict:
|
||||
"""按依赖顺序执行任务"""
|
||||
results = {}
|
||||
completed_tasks = set()
|
||||
@@ -1112,7 +1162,10 @@ class WorkflowManager:
|
||||
while len(completed_tasks) < len(tasks):
|
||||
# 找到可以执行的任务(依赖已完成)
|
||||
ready_tasks = [
|
||||
t for t in tasks if t.id not in completed_tasks and all(dep in completed_tasks for dep in t.depends_on)
|
||||
t
|
||||
for t in tasks
|
||||
if t.id not in completed_tasks
|
||||
and all(dep in completed_tasks for dep in t.depends_on)
|
||||
]
|
||||
|
||||
if not ready_tasks:
|
||||
@@ -1191,7 +1244,10 @@ class WorkflowManager:
|
||||
|
||||
except Exception as e:
|
||||
self.update_log(
|
||||
task_log.id, status=TaskStatus.FAILED.value, end_time=datetime.now().isoformat(), error_message=str(e)
|
||||
task_log.id,
|
||||
status=TaskStatus.FAILED.value,
|
||||
end_time=datetime.now().isoformat(),
|
||||
error_message=str(e),
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -1222,7 +1278,12 @@ class WorkflowManager:
|
||||
|
||||
# 这里调用现有的文件分析逻辑
|
||||
# 实际实现需要与 main.py 中的 upload_audio 逻辑集成
|
||||
return {"task": "analyze", "project_id": project_id, "files_processed": len(file_ids), "status": "completed"}
|
||||
return {
|
||||
"task": "analyze",
|
||||
"project_id": project_id,
|
||||
"files_processed": len(file_ids),
|
||||
"status": "completed",
|
||||
}
|
||||
|
||||
async def _handle_align_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理实体对齐任务"""
|
||||
@@ -1283,7 +1344,12 @@ class WorkflowManager:
|
||||
async def _handle_custom_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理自定义任务"""
|
||||
# 自定义任务的具体逻辑由外部处理器实现
|
||||
return {"task": "custom", "task_name": task.name, "config": task.config, "status": "completed"}
|
||||
return {
|
||||
"task": "custom",
|
||||
"task_name": task.name,
|
||||
"config": task.config,
|
||||
"status": "completed",
|
||||
}
|
||||
|
||||
# ==================== Default Workflow Implementations ====================
|
||||
|
||||
@@ -1340,7 +1406,9 @@ class WorkflowManager:
|
||||
|
||||
# ==================== Notification ====================
|
||||
|
||||
async def _send_workflow_notification(self, workflow: Workflow, results: dict, success: bool = True):
|
||||
async def _send_workflow_notification(
|
||||
self, workflow: Workflow, results: dict, success: bool = True
|
||||
):
|
||||
"""发送工作流执行通知"""
|
||||
if not workflow.webhook_ids:
|
||||
return
|
||||
@@ -1397,7 +1465,7 @@ class WorkflowManager:
|
||||
|
||||
**状态:** {status_text}
|
||||
|
||||
**时间:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
**时间:** {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
||||
|
||||
**结果:**
|
||||
```json
|
||||
@@ -1418,7 +1486,11 @@ class WorkflowManager:
|
||||
"title": f"Workflow Execution: {workflow.name}",
|
||||
"fields": [
|
||||
{"title": "Status", "value": status_text, "short": True},
|
||||
{"title": "Time", "value": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "short": True},
|
||||
{
|
||||
"title": "Time",
|
||||
"value": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"short": True,
|
||||
},
|
||||
],
|
||||
"footer": "InsightFlow",
|
||||
"ts": int(datetime.now().timestamp()),
|
||||
@@ -1426,9 +1498,11 @@ class WorkflowManager:
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# Singleton instance
|
||||
_workflow_manager = None
|
||||
|
||||
|
||||
def get_workflow_manager(db_manager=None) -> WorkflowManager:
|
||||
"""获取 WorkflowManager 单例"""
|
||||
global _workflow_manager
|
||||
|
||||
Reference in New Issue
Block a user