fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复异常处理 - 修复PEP8格式问题 - 添加类型注解
This commit is contained in:
@@ -9,20 +9,21 @@ InsightFlow Workflow Manager - Phase 7
|
||||
- 工作流配置管理
|
||||
"""
|
||||
|
||||
import json
|
||||
import uuid
|
||||
import asyncio
|
||||
import httpx
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Dict, Optional, Callable, Any
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_EXECUTED
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
@@ -70,9 +71,9 @@ class WorkflowTask:
|
||||
workflow_id: str
|
||||
name: str
|
||||
task_type: str # analyze, align, discover_relations, notify, custom
|
||||
config: Dict = field(default_factory=dict)
|
||||
config: dict = field(default_factory=dict)
|
||||
order: int = 0
|
||||
depends_on: List[str] = field(default_factory=list)
|
||||
depends_on: list[str] = field(default_factory=list)
|
||||
timeout_seconds: int = 300
|
||||
retry_count: int = 3
|
||||
retry_delay: int = 5
|
||||
@@ -94,12 +95,12 @@ class WebhookConfig:
|
||||
webhook_type: str # feishu, dingtalk, slack, custom
|
||||
url: str
|
||||
secret: str = "" # 用于签名验证
|
||||
headers: Dict = field(default_factory=dict)
|
||||
headers: dict = field(default_factory=dict)
|
||||
template: str = "" # 消息模板
|
||||
is_active: bool = True
|
||||
created_at: str = ""
|
||||
updated_at: str = ""
|
||||
last_used_at: Optional[str] = None
|
||||
last_used_at: str | None = None
|
||||
success_count: int = 0
|
||||
fail_count: int = 0
|
||||
|
||||
@@ -119,15 +120,15 @@ class Workflow:
|
||||
workflow_type: str
|
||||
project_id: str
|
||||
status: str = "active"
|
||||
schedule: Optional[str] = None # cron expression or interval
|
||||
schedule: str | None = None # cron expression or interval
|
||||
schedule_type: str = "manual" # manual, cron, interval
|
||||
config: Dict = field(default_factory=dict)
|
||||
webhook_ids: List[str] = field(default_factory=list)
|
||||
config: dict = field(default_factory=dict)
|
||||
webhook_ids: list[str] = field(default_factory=list)
|
||||
is_active: bool = True
|
||||
created_at: str = ""
|
||||
updated_at: str = ""
|
||||
last_run_at: Optional[str] = None
|
||||
next_run_at: Optional[str] = None
|
||||
last_run_at: str | None = None
|
||||
next_run_at: str | None = None
|
||||
run_count: int = 0
|
||||
success_count: int = 0
|
||||
fail_count: int = 0
|
||||
@@ -144,13 +145,13 @@ class WorkflowLog:
|
||||
"""工作流执行日志"""
|
||||
id: str
|
||||
workflow_id: str
|
||||
task_id: Optional[str] = None
|
||||
task_id: str | None = None
|
||||
status: str = "pending" # pending, running, success, failed, cancelled
|
||||
start_time: Optional[str] = None
|
||||
end_time: Optional[str] = None
|
||||
start_time: str | None = None
|
||||
end_time: str | None = None
|
||||
duration_ms: int = 0
|
||||
input_data: Dict = field(default_factory=dict)
|
||||
output_data: Dict = field(default_factory=dict)
|
||||
input_data: dict = field(default_factory=dict)
|
||||
output_data: dict = field(default_factory=dict)
|
||||
error_message: str = ""
|
||||
created_at: str = ""
|
||||
|
||||
@@ -165,7 +166,7 @@ class WebhookNotifier:
|
||||
def __init__(self):
|
||||
self.http_client = httpx.AsyncClient(timeout=30.0)
|
||||
|
||||
async def send(self, config: WebhookConfig, message: Dict) -> bool:
|
||||
async def send(self, config: WebhookConfig, message: dict) -> bool:
|
||||
"""发送 Webhook 通知"""
|
||||
try:
|
||||
webhook_type = WebhookType(config.webhook_type)
|
||||
@@ -179,14 +180,14 @@ class WebhookNotifier:
|
||||
else:
|
||||
return await self._send_custom(config, message)
|
||||
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Webhook send failed: {e}")
|
||||
return False
|
||||
|
||||
async def _send_feishu(self, config: WebhookConfig, message: Dict) -> bool:
|
||||
async def _send_feishu(self, config: WebhookConfig, message: dict) -> bool:
|
||||
"""发送飞书通知"""
|
||||
import hashlib
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
timestamp = str(int(datetime.now().timestamp()))
|
||||
@@ -252,10 +253,10 @@ class WebhookNotifier:
|
||||
|
||||
return result.get("code") == 0
|
||||
|
||||
async def _send_dingtalk(self, config: WebhookConfig, message: Dict) -> bool:
|
||||
async def _send_dingtalk(self, config: WebhookConfig, message: dict) -> bool:
|
||||
"""发送钉钉通知"""
|
||||
import hashlib
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import urllib.parse
|
||||
|
||||
@@ -314,7 +315,7 @@ class WebhookNotifier:
|
||||
|
||||
return result.get("errcode") == 0
|
||||
|
||||
async def _send_slack(self, config: WebhookConfig, message: Dict) -> bool:
|
||||
async def _send_slack(self, config: WebhookConfig, message: dict) -> bool:
|
||||
"""发送 Slack 通知"""
|
||||
# Slack 直接支持标准 webhook 格式
|
||||
payload = {
|
||||
@@ -341,7 +342,7 @@ class WebhookNotifier:
|
||||
|
||||
return response.text == "ok"
|
||||
|
||||
async def _send_custom(self, config: WebhookConfig, message: Dict) -> bool:
|
||||
async def _send_custom(self, config: WebhookConfig, message: dict) -> bool:
|
||||
"""发送自定义 Webhook 通知"""
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
@@ -374,8 +375,8 @@ class WorkflowManager:
|
||||
self.db = db_manager
|
||||
self.scheduler = AsyncIOScheduler()
|
||||
self.notifier = WebhookNotifier()
|
||||
self._task_handlers: Dict[str, Callable] = {}
|
||||
self._running_tasks: Dict[str, asyncio.Task] = {}
|
||||
self._task_handlers: dict[str, Callable] = {}
|
||||
self._running_tasks: dict[str, asyncio.Task] = {}
|
||||
self._setup_default_handlers()
|
||||
|
||||
# 添加调度器事件监听
|
||||
@@ -421,7 +422,7 @@ class WorkflowManager:
|
||||
for workflow in workflows:
|
||||
if workflow.schedule and workflow.is_active:
|
||||
self._schedule_workflow(workflow)
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Failed to load workflows: {e}")
|
||||
|
||||
def _schedule_workflow(self, workflow: Workflow):
|
||||
@@ -458,7 +459,7 @@ class WorkflowManager:
|
||||
"""调度器调用的工作流执行函数"""
|
||||
try:
|
||||
await self.execute_workflow(workflow_id)
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Scheduled workflow execution failed: {e}")
|
||||
|
||||
def _on_job_executed(self, event):
|
||||
@@ -497,7 +498,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_workflow(self, workflow_id: str) -> Optional[Workflow]:
|
||||
def get_workflow(self, workflow_id: str) -> Workflow | None:
|
||||
"""获取工作流"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -514,7 +515,7 @@ class WorkflowManager:
|
||||
conn.close()
|
||||
|
||||
def list_workflows(self, project_id: str = None, status: str = None,
|
||||
workflow_type: str = None) -> List[Workflow]:
|
||||
workflow_type: str = None) -> list[Workflow]:
|
||||
"""列出工作流"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -542,7 +543,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def update_workflow(self, workflow_id: str, **kwargs) -> Optional[Workflow]:
|
||||
def update_workflow(self, workflow_id: str, **kwargs) -> Workflow | None:
|
||||
"""更新工作流"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -648,7 +649,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_task(self, task_id: str) -> Optional[WorkflowTask]:
|
||||
def get_task(self, task_id: str) -> WorkflowTask | None:
|
||||
"""获取任务"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -664,7 +665,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def list_tasks(self, workflow_id: str) -> List[WorkflowTask]:
|
||||
def list_tasks(self, workflow_id: str) -> list[WorkflowTask]:
|
||||
"""列出工作流的所有任务"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -677,7 +678,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def update_task(self, task_id: str, **kwargs) -> Optional[WorkflowTask]:
|
||||
def update_task(self, task_id: str, **kwargs) -> WorkflowTask | None:
|
||||
"""更新任务"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -758,7 +759,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_webhook(self, webhook_id: str) -> Optional[WebhookConfig]:
|
||||
def get_webhook(self, webhook_id: str) -> WebhookConfig | None:
|
||||
"""获取 Webhook 配置"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -774,7 +775,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def list_webhooks(self) -> List[WebhookConfig]:
|
||||
def list_webhooks(self) -> list[WebhookConfig]:
|
||||
"""列出所有 Webhook 配置"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -786,7 +787,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def update_webhook(self, webhook_id: str, **kwargs) -> Optional[WebhookConfig]:
|
||||
def update_webhook(self, webhook_id: str, **kwargs) -> WebhookConfig | None:
|
||||
"""更新 Webhook 配置"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -889,7 +890,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def update_log(self, log_id: str, **kwargs) -> Optional[WorkflowLog]:
|
||||
def update_log(self, log_id: str, **kwargs) -> WorkflowLog | None:
|
||||
"""更新工作流日志"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -918,7 +919,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_log(self, log_id: str) -> Optional[WorkflowLog]:
|
||||
def get_log(self, log_id: str) -> WorkflowLog | None:
|
||||
"""获取日志"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -935,7 +936,7 @@ 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) -> List[WorkflowLog]:
|
||||
status: str = None, limit: int = 100, offset: int = 0) -> list[WorkflowLog]:
|
||||
"""列出工作流日志"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -966,7 +967,7 @@ class WorkflowManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_workflow_stats(self, workflow_id: str, days: int = 30) -> Dict:
|
||||
def get_workflow_stats(self, workflow_id: str, days: int = 30) -> dict:
|
||||
"""获取工作流统计"""
|
||||
conn = self.db.get_conn()
|
||||
try:
|
||||
@@ -1037,7 +1038,7 @@ class WorkflowManager:
|
||||
|
||||
# ==================== Workflow Execution ====================
|
||||
|
||||
async def execute_workflow(self, workflow_id: str, input_data: Dict = None) -> Dict:
|
||||
async def execute_workflow(self, workflow_id: str, input_data: dict = None) -> dict:
|
||||
"""执行工作流"""
|
||||
workflow = self.get_workflow(workflow_id)
|
||||
if not workflow:
|
||||
@@ -1100,7 +1101,7 @@ class WorkflowManager:
|
||||
"duration_ms": duration
|
||||
}
|
||||
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Workflow {workflow_id} execution failed: {e}")
|
||||
|
||||
# 更新日志为失败
|
||||
@@ -1122,8 +1123,8 @@ 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()
|
||||
@@ -1158,7 +1159,7 @@ class WorkflowManager:
|
||||
try:
|
||||
result = await self._execute_single_task(task, task_input, log_id)
|
||||
break
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Task {task.id} retry {attempt + 1} failed: {e}")
|
||||
if attempt == task.retry_count - 1:
|
||||
raise
|
||||
@@ -1171,7 +1172,7 @@ class WorkflowManager:
|
||||
return results
|
||||
|
||||
async def _execute_single_task(self, task: WorkflowTask,
|
||||
input_data: Dict, log_id: str) -> Any:
|
||||
input_data: dict, log_id: str) -> Any:
|
||||
"""执行单个任务"""
|
||||
handler = self._task_handlers.get(task.task_type)
|
||||
if not handler:
|
||||
@@ -1205,7 +1206,7 @@ class WorkflowManager:
|
||||
|
||||
return result
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
except TimeoutError:
|
||||
self.update_log(
|
||||
task_log.id,
|
||||
status=TaskStatus.FAILED.value,
|
||||
@@ -1224,7 +1225,7 @@ class WorkflowManager:
|
||||
raise
|
||||
|
||||
async def _execute_default_workflow(self, workflow: Workflow,
|
||||
input_data: Dict) -> Dict:
|
||||
input_data: dict) -> dict:
|
||||
"""执行默认工作流(根据类型)"""
|
||||
workflow_type = WorkflowType(workflow.workflow_type)
|
||||
|
||||
@@ -1241,7 +1242,7 @@ class WorkflowManager:
|
||||
|
||||
# ==================== Default Task Handlers ====================
|
||||
|
||||
async def _handle_analyze_task(self, task: WorkflowTask, input_data: Dict) -> Dict:
|
||||
async def _handle_analyze_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理分析任务"""
|
||||
project_id = input_data.get("project_id")
|
||||
file_ids = input_data.get("file_ids", [])
|
||||
@@ -1258,7 +1259,7 @@ class WorkflowManager:
|
||||
"status": "completed"
|
||||
}
|
||||
|
||||
async def _handle_align_task(self, task: WorkflowTask, input_data: Dict) -> Dict:
|
||||
async def _handle_align_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理实体对齐任务"""
|
||||
project_id = input_data.get("project_id")
|
||||
threshold = task.config.get("threshold", 0.85)
|
||||
@@ -1276,7 +1277,7 @@ class WorkflowManager:
|
||||
}
|
||||
|
||||
async def _handle_discover_relations_task(self, task: WorkflowTask,
|
||||
input_data: Dict) -> Dict:
|
||||
input_data: dict) -> dict:
|
||||
"""处理关系发现任务"""
|
||||
project_id = input_data.get("project_id")
|
||||
|
||||
@@ -1291,7 +1292,7 @@ class WorkflowManager:
|
||||
"status": "completed"
|
||||
}
|
||||
|
||||
async def _handle_notify_task(self, task: WorkflowTask, input_data: Dict) -> Dict:
|
||||
async def _handle_notify_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理通知任务"""
|
||||
webhook_id = task.config.get("webhook_id")
|
||||
message = task.config.get("message", {})
|
||||
@@ -1319,7 +1320,7 @@ class WorkflowManager:
|
||||
"success": success
|
||||
}
|
||||
|
||||
async def _handle_custom_task(self, task: WorkflowTask, input_data: Dict) -> Dict:
|
||||
async def _handle_custom_task(self, task: WorkflowTask, input_data: dict) -> dict:
|
||||
"""处理自定义任务"""
|
||||
# 自定义任务的具体逻辑由外部处理器实现
|
||||
return {
|
||||
@@ -1331,7 +1332,7 @@ class WorkflowManager:
|
||||
|
||||
# ==================== Default Workflow Implementations ====================
|
||||
|
||||
async def _auto_analyze_files(self, workflow: Workflow, input_data: Dict) -> Dict:
|
||||
async def _auto_analyze_files(self, workflow: Workflow, input_data: dict) -> dict:
|
||||
"""自动分析新上传的文件"""
|
||||
project_id = workflow.project_id
|
||||
|
||||
@@ -1346,7 +1347,7 @@ class WorkflowManager:
|
||||
"status": "completed"
|
||||
}
|
||||
|
||||
async def _auto_align_entities(self, workflow: Workflow, input_data: Dict) -> Dict:
|
||||
async def _auto_align_entities(self, workflow: Workflow, input_data: dict) -> dict:
|
||||
"""自动实体对齐"""
|
||||
project_id = workflow.project_id
|
||||
threshold = workflow.config.get("threshold", 0.85)
|
||||
@@ -1359,7 +1360,7 @@ class WorkflowManager:
|
||||
"status": "completed"
|
||||
}
|
||||
|
||||
async def _auto_discover_relations(self, workflow: Workflow, input_data: Dict) -> Dict:
|
||||
async def _auto_discover_relations(self, workflow: Workflow, input_data: dict) -> dict:
|
||||
"""自动关系发现"""
|
||||
project_id = workflow.project_id
|
||||
|
||||
@@ -1370,7 +1371,7 @@ class WorkflowManager:
|
||||
"status": "completed"
|
||||
}
|
||||
|
||||
async def _generate_scheduled_report(self, workflow: Workflow, input_data: Dict) -> Dict:
|
||||
async def _generate_scheduled_report(self, workflow: Workflow, input_data: dict) -> dict:
|
||||
"""生成定时报告"""
|
||||
project_id = workflow.project_id
|
||||
report_type = workflow.config.get("report_type", "summary")
|
||||
@@ -1385,7 +1386,7 @@ class WorkflowManager:
|
||||
# ==================== Notification ====================
|
||||
|
||||
async def _send_workflow_notification(self, workflow: Workflow,
|
||||
results: Dict, success: bool = True):
|
||||
results: dict, success: bool = True):
|
||||
"""发送工作流执行通知"""
|
||||
if not workflow.webhook_ids:
|
||||
return
|
||||
@@ -1414,11 +1415,11 @@ class WorkflowManager:
|
||||
try:
|
||||
result = await self.notifier.send(webhook, message)
|
||||
self.update_webhook_stats(webhook_id, result)
|
||||
except (httpx.HTTPError, asyncio.TimeoutError) as e:
|
||||
except (TimeoutError, httpx.HTTPError) as e:
|
||||
logger.error(f"Failed to send notification to {webhook_id}: {e}")
|
||||
|
||||
def _build_feishu_message(self, workflow: Workflow, results: Dict,
|
||||
success: bool) -> Dict:
|
||||
def _build_feishu_message(self, workflow: Workflow, results: dict,
|
||||
success: bool) -> dict:
|
||||
"""构建飞书消息"""
|
||||
status_text = "✅ 成功" if success else "❌ 失败"
|
||||
|
||||
@@ -1431,8 +1432,8 @@ class WorkflowManager:
|
||||
]
|
||||
}
|
||||
|
||||
def _build_dingtalk_message(self, workflow: Workflow, results: Dict,
|
||||
success: bool) -> Dict:
|
||||
def _build_dingtalk_message(self, workflow: Workflow, results: dict,
|
||||
success: bool) -> dict:
|
||||
"""构建钉钉消息"""
|
||||
status_text = "✅ 成功" if success else "❌ 失败"
|
||||
|
||||
@@ -1453,8 +1454,8 @@ class WorkflowManager:
|
||||
"""
|
||||
}
|
||||
|
||||
def _build_slack_message(self, workflow: Workflow, results: Dict,
|
||||
success: bool) -> Dict:
|
||||
def _build_slack_message(self, workflow: Workflow, results: dict,
|
||||
success: bool) -> dict:
|
||||
"""构建 Slack 消息"""
|
||||
color = "#36a64f" if success else "#ff0000"
|
||||
status_text = "Success" if success else "Failed"
|
||||
|
||||
Reference in New Issue
Block a user