fix: auto-fix code issues (cron)

- 修复重复导入/字段
- 修复异常处理
- 修复PEP8格式问题
- 添加类型注解
This commit is contained in:
OpenClaw Bot
2026-02-27 18:09:24 +08:00
parent 646b64daf7
commit 17bda3dbce
38 changed files with 1993 additions and 1972 deletions

View File

@@ -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"