171 lines
5.6 KiB
Python
171 lines
5.6 KiB
Python
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
|
||
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
|
||
from apscheduler.triggers.cron import CronTrigger
|
||
from apscheduler.triggers.interval import IntervalTrigger
|
||
from apscheduler.triggers.date import DateTrigger
|
||
from datetime import datetime
|
||
import logging
|
||
import pytz
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
class TaskScheduler:
|
||
"""定时任务调度器"""
|
||
|
||
def __init__(self, timezone='Asia/Shanghai'):
|
||
"""初始化调度器"""
|
||
self.timezone = pytz.timezone(timezone)
|
||
|
||
# 配置作业存储和执行器
|
||
jobstores = {
|
||
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
|
||
}
|
||
|
||
executors = {
|
||
'default': ThreadPoolExecutor(20), # 默认线程池
|
||
'processpool': ProcessPoolExecutor(5) # 进程池
|
||
}
|
||
|
||
job_defaults = {
|
||
'coalesce': False, # 是否合并执行
|
||
'max_instances': 3, # 最大实例数
|
||
'misfire_grace_time': 60 # 任务错过执行时间的宽限时间(秒)
|
||
}
|
||
|
||
# 创建调度器
|
||
self.scheduler = AsyncIOScheduler(
|
||
jobstores=jobstores,
|
||
executors=executors,
|
||
job_defaults=job_defaults,
|
||
timezone=self.timezone
|
||
)
|
||
|
||
def start(self):
|
||
"""启动调度器"""
|
||
if not self.scheduler.running:
|
||
self.scheduler.start()
|
||
logger.info("定时任务调度器已启动")
|
||
|
||
def shutdown(self):
|
||
"""关闭调度器"""
|
||
if self.scheduler.running:
|
||
self.scheduler.shutdown()
|
||
logger.info("定时任务调度器已关闭")
|
||
|
||
def add_cron_job(self, func, job_id=None, **trigger_args):
|
||
"""添加Cron定时任务
|
||
|
||
参数:
|
||
func: 要执行的函数
|
||
job_id: 任务ID,如果不指定则自动生成
|
||
trigger_args: cron触发器参数,如:
|
||
year (int|str) – 4位数年份
|
||
month (int|str) – 月份 (1-12)
|
||
day (int|str) – 日期 (1-31)
|
||
week (int|str) – ISO周数 (1-53)
|
||
day_of_week (int|str) – 工作日 (0-6 或 mon,tue,wed,thu,fri,sat,sun)
|
||
hour (int|str) – 小时 (0-23)
|
||
minute (int|str) – 分钟 (0-59)
|
||
second (int|str) – 秒 (0-59)
|
||
|
||
示例:
|
||
# 每天凌晨2点执行
|
||
scheduler.add_cron_job(my_function, hour=2)
|
||
|
||
# 每周一、三、五的下午5:30执行
|
||
scheduler.add_cron_job(my_function, day_of_week='mon,wed,fri', hour=17, minute=30)
|
||
"""
|
||
trigger = CronTrigger(**trigger_args, timezone=self.timezone)
|
||
return self.scheduler.add_job(
|
||
func,
|
||
trigger=trigger,
|
||
id=job_id,
|
||
replace_existing=True
|
||
)
|
||
|
||
def add_interval_job(self, func, seconds=0, minutes=0, hours=0, days=0, job_id=None):
|
||
"""添加间隔定时任务
|
||
|
||
参数:
|
||
func: 要执行的函数
|
||
seconds: 间隔秒数
|
||
minutes: 间隔分钟数
|
||
hours: 间隔小时数
|
||
days: 间隔天数
|
||
job_id: 任务ID,如果不指定则自动生成
|
||
|
||
示例:
|
||
# 每30分钟执行一次
|
||
scheduler.add_interval_job(my_function, minutes=30)
|
||
"""
|
||
trigger = IntervalTrigger(
|
||
seconds=seconds,
|
||
minutes=minutes,
|
||
hours=hours,
|
||
days=days,
|
||
timezone=self.timezone
|
||
)
|
||
return self.scheduler.add_job(
|
||
func,
|
||
trigger=trigger,
|
||
id=job_id,
|
||
replace_existing=True
|
||
)
|
||
|
||
def add_one_time_job(self, func, run_date, job_id=None):
|
||
"""添加一次性定时任务
|
||
|
||
参数:
|
||
func: 要执行的函数
|
||
run_date: 运行日期时间
|
||
job_id: 任务ID,如果不指定则自动生成
|
||
|
||
示例:
|
||
# 在指定时间执行一次
|
||
scheduler.add_one_time_job(my_function, datetime(2023, 12, 31, 23, 59, 59))
|
||
"""
|
||
trigger = DateTrigger(run_date=run_date, timezone=self.timezone)
|
||
return self.scheduler.add_job(
|
||
func,
|
||
trigger=trigger,
|
||
id=job_id,
|
||
replace_existing=True
|
||
)
|
||
|
||
def remove_job(self, job_id):
|
||
"""移除定时任务"""
|
||
try:
|
||
self.scheduler.remove_job(job_id)
|
||
logger.info(f"已移除任务: {job_id}")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"移除任务失败: {job_id}, 错误: {str(e)}")
|
||
return False
|
||
|
||
def get_jobs(self):
|
||
"""获取所有定时任务"""
|
||
return self.scheduler.get_jobs()
|
||
|
||
def pause_job(self, job_id):
|
||
"""暂停定时任务"""
|
||
try:
|
||
self.scheduler.pause_job(job_id)
|
||
logger.info(f"已暂停任务: {job_id}")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"暂停任务失败: {job_id}, 错误: {str(e)}")
|
||
return False
|
||
|
||
def resume_job(self, job_id):
|
||
"""恢复定时任务"""
|
||
try:
|
||
self.scheduler.resume_job(job_id)
|
||
logger.info(f"已恢复任务: {job_id}")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"恢复任务失败: {job_id}, 错误: {str(e)}")
|
||
return False
|
||
|
||
# 创建全局调度器实例
|
||
scheduler = TaskScheduler() |