| """ |
| 定时任务管理API蓝图 |
| 提供定时任务的启动、停止、状态查询等接口 |
| """ |
| from flask import Blueprint, jsonify, request, current_app |
| from functools import wraps |
| |
| scheduler_bp = Blueprint('scheduler', __name__, url_prefix='/api/scheduler') |
| |
| def admin_required(f): |
| """装饰器:需要管理员权限""" |
| @wraps(f) |
| def decorated(*args, **kwargs): |
| # 这里可以添加管理员权限验证逻辑 |
| # 暂时允许所有请求通过 |
| return f(*args, **kwargs) |
| return decorated |
| |
| @scheduler_bp.route('/status', methods=['GET']) |
| def get_scheduler_status(): |
| """获取定时任务状态""" |
| try: |
| scheduler_manager = current_app.scheduler_manager |
| status = scheduler_manager.get_task_status() |
| |
| return jsonify({ |
| 'success': True, |
| 'data': status, |
| 'message': '获取定时任务状态成功' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'获取定时任务状态失败: {str(e)}' |
| }), 500 |
| |
| @scheduler_bp.route('/start', methods=['POST']) |
| @admin_required |
| def start_scheduler(): |
| """启动定时任务""" |
| try: |
| data = request.get_json() or {} |
| interval_minutes = data.get('interval_minutes', 1) |
| |
| # 验证间隔时间 |
| if not isinstance(interval_minutes, (int, float)) or interval_minutes <= 0: |
| return jsonify({ |
| 'success': False, |
| 'message': '无效的间隔时间,必须是大于0的数字' |
| }), 400 |
| |
| scheduler_manager = current_app.scheduler_manager |
| scheduler_manager.start_graph_rebuild_task(interval_minutes) |
| |
| return jsonify({ |
| 'success': True, |
| 'message': f'定时任务已启动,间隔: {interval_minutes}分钟' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'启动定时任务失败: {str(e)}' |
| }), 500 |
| |
| @scheduler_bp.route('/stop', methods=['POST']) |
| @admin_required |
| def stop_scheduler(): |
| """停止定时任务""" |
| try: |
| scheduler_manager = current_app.scheduler_manager |
| scheduler_manager.stop_graph_rebuild_task() |
| |
| return jsonify({ |
| 'success': True, |
| 'message': '定时任务已停止' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'停止定时任务失败: {str(e)}' |
| }), 500 |
| |
| @scheduler_bp.route('/update-interval', methods=['POST']) |
| @admin_required |
| def update_interval(): |
| """更新任务间隔""" |
| try: |
| data = request.get_json() |
| if not data or 'interval_minutes' not in data: |
| return jsonify({ |
| 'success': False, |
| 'message': '缺少interval_minutes参数' |
| }), 400 |
| |
| interval_minutes = data['interval_minutes'] |
| |
| # 验证间隔时间 |
| if not isinstance(interval_minutes, (int, float)) or interval_minutes <= 0: |
| return jsonify({ |
| 'success': False, |
| 'message': '无效的间隔时间,必须是大于0的数字' |
| }), 400 |
| |
| scheduler_manager = current_app.scheduler_manager |
| scheduler_manager.update_task_interval(interval_minutes) |
| |
| return jsonify({ |
| 'success': True, |
| 'message': f'任务间隔已更新为 {interval_minutes}分钟' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'更新任务间隔失败: {str(e)}' |
| }), 500 |
| |
| @scheduler_bp.route('/rebuild-now', methods=['POST']) |
| @admin_required |
| def rebuild_graph_now(): |
| """立即执行一次图重建""" |
| try: |
| scheduler_manager = current_app.scheduler_manager |
| |
| # 在新线程中执行,避免阻塞请求 |
| import threading |
| thread = threading.Thread(target=scheduler_manager.rebuild_graph_job) |
| thread.start() |
| |
| return jsonify({ |
| 'success': True, |
| 'message': '图重建任务已开始执行' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'执行图重建失败: {str(e)}' |
| }), 500 |
| |
| @scheduler_bp.route('/logs', methods=['GET']) |
| def get_rebuild_logs(): |
| """获取重建日志统计""" |
| try: |
| scheduler_manager = current_app.scheduler_manager |
| status = scheduler_manager.get_task_status() |
| |
| log_info = { |
| 'rebuild_count': status['rebuild_count'], |
| 'error_count': status['error_count'], |
| 'last_rebuild_time': status['last_rebuild_time'], |
| 'success_rate': ( |
| ((status['rebuild_count'] - status['error_count']) / status['rebuild_count'] * 100) |
| if status['rebuild_count'] > 0 else 0 |
| ) |
| } |
| |
| return jsonify({ |
| 'success': True, |
| 'data': log_info, |
| 'message': '获取重建日志成功' |
| }) |
| except Exception as e: |
| return jsonify({ |
| 'success': False, |
| 'message': f'获取重建日志失败: {str(e)}' |
| }), 500 |