- 搜索服务改用 namespace 隔离浏览器实例(参考 webtest-agent 方案), 解决定时任务与手动处理并发调用 agent-browser 互相踢掉导致搜索结果为0的问题 - agent-browser 调用加瞬时错误自动重试,使用 /tmp/xdg-rt 目录 - 步骤4 提示词放宽:品牌/系列相关页面也纳入提取,无精确型号时兜底选最相关内容 - 步骤4 大模型返回空时自动兜底,不再直接跳过导致会话卡死 - 会话收尾修复:失败/无数据时会话状态正确标记,并自动移除待处理产品 - 处理入口统一:定时任务/单产品/批量处理均改为 process_monitor 大模型流程(防重) - paramhub_client 增加登录态自动恢复:401 或连接失败时自动重新登录重试 - 全流程实测通过:deepseek-v4-flash-0731 → review_id 19ed2daaabfe
114 lines
3.8 KiB
Python
114 lines
3.8 KiB
Python
"""
|
|
定时任务调度器
|
|
"""
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
|
from apscheduler.triggers.interval import IntervalTrigger
|
|
from datetime import datetime
|
|
from models.database import db
|
|
from config import Config
|
|
import logging
|
|
|
|
# 配置日志
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger('scheduler')
|
|
|
|
class TaskScheduler:
|
|
def __init__(self):
|
|
self.scheduler = BackgroundScheduler()
|
|
self.running = False
|
|
|
|
def start(self):
|
|
"""启动调度器"""
|
|
if not self.running:
|
|
self.scheduler.start()
|
|
self.running = True
|
|
logger.info("定时任务调度器已启动")
|
|
|
|
def stop(self):
|
|
"""停止调度器"""
|
|
if self.running:
|
|
self.scheduler.shutdown()
|
|
self.running = False
|
|
logger.info("定时任务调度器已停止")
|
|
|
|
def add_interval_job(self, func, interval_seconds, job_id, **kwargs):
|
|
"""添加定时任务"""
|
|
self.scheduler.add_job(
|
|
func,
|
|
trigger=IntervalTrigger(seconds=interval_seconds),
|
|
id=job_id,
|
|
replace_existing=True,
|
|
**kwargs
|
|
)
|
|
logger.info(f"添加定时任务: {job_id}, 间隔: {interval_seconds}秒")
|
|
|
|
def remove_job(self, job_id):
|
|
"""移除定时任务"""
|
|
try:
|
|
self.scheduler.remove_job(job_id)
|
|
logger.info(f"移除定时任务: {job_id}")
|
|
except Exception as e:
|
|
logger.error(f"移除任务失败: {job_id}, 错误: {str(e)}")
|
|
|
|
def get_jobs(self):
|
|
"""获取所有任务"""
|
|
return self.scheduler.get_jobs()
|
|
|
|
# 创建全局调度器实例
|
|
task_scheduler = TaskScheduler()
|
|
|
|
def auto_process_task():
|
|
"""
|
|
自动处理产品的定时任务(大模型驱动)
|
|
通过 process_monitor 启动异步处理会话,避免与手动处理并发冲突
|
|
"""
|
|
from services.process_monitor import process_monitor
|
|
|
|
try:
|
|
# 检查是否启用自动处理
|
|
enabled = db.get_system_config('auto_process_enabled', 'true')
|
|
if enabled.lower() != 'true':
|
|
logger.info("自动处理已禁用,跳过本次执行")
|
|
return
|
|
|
|
# 获取批量处理数量
|
|
batch_size = int(db.get_system_config('batch_size', '5'))
|
|
|
|
# 获取待处理产品
|
|
products = db.get_pending_products(limit=batch_size)
|
|
|
|
if not products:
|
|
logger.info("没有待处理的产品")
|
|
return
|
|
|
|
logger.info(f"开始处理 {len(products)} 个产品")
|
|
|
|
for product in products:
|
|
try:
|
|
# 启动大模型处理会话(内部有防重,已有活跃会话会自动跳过)
|
|
session_id, started = process_monitor.start_process(
|
|
product_name=product['product_name'],
|
|
category=product.get('category'),
|
|
subcategory=product.get('subcategory')
|
|
)
|
|
if started:
|
|
logger.info(f"产品 {product['product_name']} 处理会话已启动: {session_id}")
|
|
else:
|
|
logger.info(f"产品 {product['product_name']} 已有处理会话: {session_id}")
|
|
except Exception as e:
|
|
logger.error(f"启动产品 {product['product_name']} 处理会话时出错: {str(e)}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"自动处理任务执行失败: {str(e)}")
|
|
|
|
def setup_auto_process_job():
|
|
"""设置自动处理定时任务"""
|
|
interval = int(db.get_system_config('process_interval', str(Config.PROCESS_INTERVAL)))
|
|
task_scheduler.add_interval_job(
|
|
auto_process_task,
|
|
interval_seconds=interval,
|
|
job_id='auto_process'
|
|
) |