import threading from time import sleep from typing import List, Dict from mycode.DBManager import DBManager from datetime import datetime, timedelta from mycode.TaskManager import g_TaskM class PollingManager: def __init__(self): self.DBM = DBManager() self.brun = True self.bUpdate = False self.p_th = None def parse_time(self,time_str: str) -> datetime: """将时间字符串转为 datetime 对象""" if not time_str: return None try: return datetime.datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S') except ValueError: return None def need_check(self,target: Dict) -> bool: now = datetime.datetime.now() period = target[5] start_time_str = target[6] last_time = self.parse_time(target[7]) # 不巡检的目标 if target[4] == 0 or period == 0: return False # 当前时间是否达到设定开始时间 if start_time_str: try: # 只取时间部分用于每天/每周的对比 st_hour, st_minute = map(int, start_time_str.strip().split(':')[:2]) except Exception: return False else: st_hour, st_minute = 0, 0 # 当天设定执行时间点 target_time = now.replace(hour=st_hour, minute=st_minute, second=0, microsecond=0) # 如果 last_time 已经检查过今天了,就跳过 if last_time and last_time >= target_time: return False if period == 1: # 每天 return now >= target_time elif period == 2: # 每周 return now.weekday() == 0 and now >= target_time # 每周一执行 elif period == 3: # 每月 return now.day == 1 and now >= target_time # 每月1号执行 else: return False def should_poll(self,polling_period: int, start_time_str: str, last_time_str: str = None) -> bool: now = datetime.now() # 无周期,直接返回 False if polling_period == 0: return False try: # 获取比较基准时间 if last_time_str: base_time = datetime.strptime(last_time_str, "%Y-%m-%d %H:%M:%S") elif start_time_str: base_time = datetime.strptime(start_time_str, "%Y-%m-%d %H:%M:%S") if now > base_time: return True else: return False except Exception as e: print(f"时间格式错误: {e}") return False if polling_period == 1: # 每天:超过 24 小时 return (now - base_time) >= timedelta(days=1) elif polling_period == 2: # 每周:要到下一个“周一的那个时间点” weekday = base_time.weekday() # 0=周一, ..., 6=周日 days_to_next_monday = (7 - weekday) % 7 or 7 # 至少是下一个周一 next_monday = base_time + timedelta(days=days_to_next_monday) next_monday = next_monday.replace(hour=base_time.hour, minute=base_time.minute, second=base_time.second) return now >= next_monday elif polling_period == 3: # 每月:下个月的 1 号,时间点与原始时间相同 year = base_time.year + (base_time.month // 12) month = (base_time.month % 12) + 1 next_month_first = datetime(year, month, 1, base_time.hour, base_time.minute, base_time.second) return now >= next_month_first return False def do_check(self,target): print(f"巡检中: {target[2]} (类型: {target[9]})") #创建task---并初始化待办 ----尝试执行 g_TaskM.create_polling_task(target) def update_last_time(self, target_id): now_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S') strsql = "UPDATE target SET polling_last_time=%s WHERE ID=%s;" params = (now_str,target_id) bok,_ = self.DBM.safe_do_sql(strsql,params) def needUpdateTargets(self): self.bUpdate = True def polling_th(self): strsql = "select * from target;" targets = self.DBM.do_select(strsql) while self.brun: if self.bUpdate: targets = self.DBM.do_select(strsql) self.bUpdate =False for target in targets: if self.should_poll(target[5],target[6],target[7]): self.do_check(target) self.update_last_time(target[0]) sleep(60 * 60) #一个小时 def run_polling(self): self.p_th = threading.Thread(target=self.polling_th(), name=f"p_th") self.p_th.start() if __name__ == "__main__": PM = PollingManager() PM.polling_th()