2026-07-17 23:08:59 +08:00
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
"""
|
|
|
|
|
|
资产推荐定时任务
|
|
|
|
|
|
|
|
|
|
|
|
功能:
|
|
|
|
|
|
1. 每日运维提醒推送(L2)
|
|
|
|
|
|
2. 画像缓存预热
|
|
|
|
|
|
3. 新员工欢迎推送(L3)
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
|
|
import logging
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
|
|
|
|
from apscheduler.triggers.cron import CronTrigger
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
# 定时任务调度器实例
|
2026-07-18 01:13:33 +08:00
|
|
|
|
# v4.0 P1-7 修复:AsyncIOSScheduler → AsyncIOScheduler(原拼写错误,import 即 NameError)
|
|
|
|
|
|
# 注意:本模块当前无人 import(main.py 使用自己的 _scheduler),批次 4 候选删除
|
|
|
|
|
|
scheduler = AsyncIOScheduler()
|
2026-07-17 23:08:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setup_scheduled_tasks():
|
|
|
|
|
|
"""配置定时任务"""
|
|
|
|
|
|
|
|
|
|
|
|
# 每日 9:00 运维提醒
|
|
|
|
|
|
scheduler.add_job(
|
|
|
|
|
|
daily_maintenance_push,
|
|
|
|
|
|
trigger=CronTrigger(hour=9, minute=0),
|
|
|
|
|
|
id='daily_maintenance_push',
|
|
|
|
|
|
name='每日运维提醒推送',
|
|
|
|
|
|
replace_existing=True
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 每小时画像缓存刷新
|
|
|
|
|
|
scheduler.add_job(
|
|
|
|
|
|
hourly_profile_sync,
|
|
|
|
|
|
trigger=CronTrigger(minute=0),
|
|
|
|
|
|
id='hourly_profile_sync',
|
|
|
|
|
|
name='每小时员工画像同步',
|
|
|
|
|
|
replace_existing=True
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 每天 8:55 检查新员工
|
|
|
|
|
|
scheduler.add_job(
|
|
|
|
|
|
check_new_employees,
|
|
|
|
|
|
trigger=CronTrigger(hour=8, minute=55),
|
|
|
|
|
|
id='check_new_employees',
|
|
|
|
|
|
name='新员工欢迎检查',
|
|
|
|
|
|
replace_existing=True
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"[Scheduler] 已配置 {len(scheduler.get_jobs())} 个定时任务")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def daily_maintenance_push():
|
|
|
|
|
|
"""每日运维提醒推送"""
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("[Scheduler] 开始执行每日运维提醒推送")
|
|
|
|
|
|
|
|
|
|
|
|
from app.services.asset_recommend_service import get_asset_recommend_service
|
|
|
|
|
|
from app.services.employee_profile_service import get_employee_profile_service
|
|
|
|
|
|
|
|
|
|
|
|
asset_service = get_asset_recommend_service()
|
|
|
|
|
|
profile_service = get_employee_profile_service()
|
|
|
|
|
|
|
|
|
|
|
|
# 获取全部员工(分页)
|
|
|
|
|
|
# TODO: 实现分页获取员工列表
|
|
|
|
|
|
# page = 1
|
|
|
|
|
|
# while True:
|
|
|
|
|
|
# employees = await get_employees_paginated(page, 100)
|
|
|
|
|
|
# if not employees:
|
|
|
|
|
|
# break
|
|
|
|
|
|
#
|
|
|
|
|
|
# for emp in employees:
|
|
|
|
|
|
# try:
|
|
|
|
|
|
# profile = await profile_service.get_profile(emp.id)
|
|
|
|
|
|
# profile_dict = {
|
|
|
|
|
|
# 'huorong_version': profile.huorong_version,
|
|
|
|
|
|
# 'huorong_virusdb_date': profile.huorong_virusdb_date,
|
|
|
|
|
|
# 'huorong_offline_days': profile.huorong_offline_days,
|
|
|
|
|
|
# 'unionsoft_patches_missing': profile.unionsoft_patches_missing,
|
|
|
|
|
|
# 'unionsoft_violations': profile.unionsoft_violations,
|
|
|
|
|
|
# }
|
|
|
|
|
|
# l2_recs = asset_service.match_profile_triggers(profile_dict)
|
|
|
|
|
|
#
|
|
|
|
|
|
# if l2_recs:
|
|
|
|
|
|
# ws_msg = asset_service.build_ws_message(l2_recs)
|
|
|
|
|
|
# from app.services.ws_manager import manager as ws_manager
|
|
|
|
|
|
# await ws_manager.broadcast_to_employees([emp.id], ws_msg)
|
|
|
|
|
|
#
|
|
|
|
|
|
# except Exception as e:
|
|
|
|
|
|
# logger.error(f"[Scheduler] 推送失败: {emp.id}, {e}")
|
|
|
|
|
|
#
|
|
|
|
|
|
# page += 1
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("[Scheduler] 每日运维提醒推送完成 (TODO: 实现员工列表获取)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def hourly_profile_sync():
|
|
|
|
|
|
"""每小时同步员工画像缓存"""
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("[Scheduler] 开始同步员工画像缓存")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
profile_service = get_employee_profile_service()
|
|
|
|
|
|
deleted = await profile_service.clear_expired_cache()
|
|
|
|
|
|
logger.info(f"[Scheduler] 画像缓存同步完成,清理 {deleted} 条")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"[Scheduler] 画像缓存同步失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def check_new_employees():
|
|
|
|
|
|
"""检查新员工并发送欢迎"""
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("[Scheduler] 检查新员工")
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: 实现新员工检测逻辑
|
|
|
|
|
|
# 获取过去 24 小时入职的员工
|
|
|
|
|
|
# new_employees = await get_new_employees(days=1)
|
|
|
|
|
|
#
|
|
|
|
|
|
# for emp in new_employees:
|
|
|
|
|
|
# asset_service = get_asset_recommend_service()
|
|
|
|
|
|
# role_recs = asset_service.get_by_role('new_employee')
|
|
|
|
|
|
#
|
|
|
|
|
|
# if role_recs:
|
|
|
|
|
|
# ws_msg = asset_service.build_ws_message(role_recs)
|
|
|
|
|
|
# from app.services.ws_manager import manager as ws_manager
|
|
|
|
|
|
# await ws_manager.broadcast_to_employees([emp.id], ws_msg)
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("[Scheduler] 新员工检查完成 (TODO: 实现)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def start_scheduler():
|
|
|
|
|
|
"""启动定时任务调度器"""
|
|
|
|
|
|
if not scheduler.running:
|
|
|
|
|
|
setup_scheduled_tasks()
|
|
|
|
|
|
scheduler.start()
|
|
|
|
|
|
logger.info("定时任务调度器已启动")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def stop_scheduler():
|
|
|
|
|
|
"""停止定时任务调度器"""
|
|
|
|
|
|
if scheduler.running:
|
|
|
|
|
|
scheduler.shutdown()
|
|
|
|
|
|
logger.info("定时任务调度器已停止")
|