feat: restore source parity and harden agent runtime
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
延时节点处理器
|
||||
处理流程延时等待
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, TYPE_CHECKING
|
||||
|
||||
from online_dev.workflow.engine.handlers.base_handler import BaseNodeHandler
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from online_dev.workflow.engine.base import ExecutionContext
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DelayNodeHandler(BaseNodeHandler):
|
||||
"""
|
||||
延时节点处理器
|
||||
|
||||
支持延时单位:
|
||||
- minute: 分钟
|
||||
- hour: 小时
|
||||
- day: 天
|
||||
- workday: 工作日(跳过周六日)
|
||||
"""
|
||||
|
||||
async def execute(self, context: 'ExecutionContext', node: Dict) -> None:
|
||||
"""
|
||||
执行延时节点:计算到期时间,注册定时任务
|
||||
"""
|
||||
node_id = self.get_node_id(node)
|
||||
node_name = self.get_node_name(node)
|
||||
node_config = self.get_node_config(node)
|
||||
|
||||
duration = node_config.get('duration', 1)
|
||||
unit = node_config.get('unit', 'hour')
|
||||
|
||||
unit_names = {
|
||||
'minute': '分钟',
|
||||
'hour': '小时',
|
||||
'day': '天',
|
||||
'workday': '工作日',
|
||||
}
|
||||
unit_name = unit_names.get(unit, unit)
|
||||
|
||||
logger.info(f"延时节点 - 等待 {duration} {unit_name}")
|
||||
|
||||
# 更新实例当前节点
|
||||
await self.update_instance_node(context, node)
|
||||
|
||||
# 计算到期时间
|
||||
delay_until = self._calculate_delay_until(duration, unit)
|
||||
|
||||
# 更新实例延时状态
|
||||
context.instance.delay_node_id = node_id
|
||||
context.instance.delay_until = delay_until
|
||||
context.db.add(context.instance)
|
||||
await context.db.flush()
|
||||
|
||||
# 记录延时开始日志
|
||||
await self.create_log(
|
||||
context, node, 'delay_start',
|
||||
comment=f'开始延时等待 {duration} {unit_name},预计 {delay_until.strftime("%Y-%m-%d %H:%M:%S")} 恢复',
|
||||
extra_data={
|
||||
'duration': duration,
|
||||
'unit': unit,
|
||||
'delay_until': delay_until.isoformat(),
|
||||
},
|
||||
operator_id='',
|
||||
)
|
||||
|
||||
# 注册定时任务
|
||||
from online_dev.workflow.engine.delay_callback import _register_delay_job
|
||||
|
||||
instance_id = str(context.instance.id)
|
||||
success = await _register_delay_job(instance_id, node_id, delay_until)
|
||||
|
||||
if not success:
|
||||
# 调度器不可用时,直接跳过延时继续推进(降级处理)
|
||||
logger.warning(f"调度器不可用,延时节点直接跳过: instance={instance_id}, node={node_id}")
|
||||
|
||||
# 清除延时状态
|
||||
context.instance.delay_node_id = ""
|
||||
context.instance.delay_until = None
|
||||
context.db.add(context.instance)
|
||||
await context.db.flush()
|
||||
|
||||
await self.create_log(
|
||||
context, node, 'delay_skip',
|
||||
comment='调度器不可用,延时跳过',
|
||||
operator_id='',
|
||||
)
|
||||
await self.advance_to_next(context, node)
|
||||
|
||||
@staticmethod
|
||||
def _calculate_delay_until(duration: int, unit: str) -> datetime:
|
||||
"""
|
||||
计算延时到期时间
|
||||
|
||||
Args:
|
||||
duration: 延时时长
|
||||
unit: 延时单位 (minute/hour/day/workday)
|
||||
|
||||
Returns:
|
||||
到期时间
|
||||
"""
|
||||
now = datetime.now()
|
||||
|
||||
if unit == 'minute':
|
||||
return now + timedelta(minutes=duration)
|
||||
elif unit == 'hour':
|
||||
return now + timedelta(hours=duration)
|
||||
elif unit == 'day':
|
||||
return now + timedelta(days=duration)
|
||||
elif unit == 'workday':
|
||||
return DelayNodeHandler._add_workdays(now, duration)
|
||||
else:
|
||||
# 默认按小时处理
|
||||
return now + timedelta(hours=duration)
|
||||
|
||||
@staticmethod
|
||||
def _add_workdays(start: datetime, days: int) -> datetime:
|
||||
"""
|
||||
添加工作日(跳过周六日)
|
||||
|
||||
Args:
|
||||
start: 起始时间
|
||||
days: 工作日天数
|
||||
|
||||
Returns:
|
||||
目标时间(保持原始时分秒)
|
||||
"""
|
||||
current = start
|
||||
added = 0
|
||||
while added < days:
|
||||
current += timedelta(days=1)
|
||||
# weekday(): 0=周一, 5=周六, 6=周日
|
||||
if current.weekday() < 5:
|
||||
added += 1
|
||||
return current
|
||||
Reference in New Issue
Block a user