241 lines
8.1 KiB
Python
241 lines
8.1 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Scheduler Model - 定时任务模型
|
||
用于管理定时任务和执行记录
|
||
"""
|
||
from sqlalchemy import Column, String, Integer, Boolean, Text, DateTime, Float, Index
|
||
|
||
from app.base_model import BaseModel
|
||
|
||
|
||
class SchedulerJob(BaseModel):
|
||
"""
|
||
定时任务模型 - 用于管理定时任务配置
|
||
|
||
功能特点:
|
||
1. 支持多种触发器类型(cron、interval、date)
|
||
2. 支持任务启用/禁用
|
||
3. 支持任务分组管理
|
||
4. 支持任务优先级
|
||
5. 记录任务执行统计信息
|
||
6. 支持任务参数配置
|
||
"""
|
||
__tablename__ = "core_scheduler_job"
|
||
|
||
# 所属应用(逻辑外键关联 core_application)
|
||
application_id = Column(String(21), nullable=True, index=True, comment="所属应用ID")
|
||
|
||
# 任务类型选择
|
||
TRIGGER_TYPE_CHOICES = {
|
||
'cron': 'Cron表达式',
|
||
'interval': '间隔执行',
|
||
'date': '指定时间',
|
||
}
|
||
|
||
# 任务状态选择
|
||
STATUS_CHOICES = {
|
||
0: '禁用',
|
||
1: '启用',
|
||
2: '暂停',
|
||
}
|
||
|
||
# 任务名称
|
||
name = Column(String(128), nullable=False, index=True, comment="任务名称")
|
||
|
||
# 任务编码(唯一标识)
|
||
code = Column(String(128), unique=True, nullable=False, index=True, comment="任务编码")
|
||
|
||
# 任务描述
|
||
description = Column(Text, nullable=True, comment="任务描述")
|
||
|
||
# 任务分组
|
||
group = Column(String(64), default='default', index=True, comment="任务分组")
|
||
|
||
# 触发器类型
|
||
trigger_type = Column(String(20), default='cron', index=True, comment="触发器类型")
|
||
|
||
# Cron 表达式(用于 cron 类型)
|
||
cron_expression = Column(String(128), nullable=True, comment="Cron表达式")
|
||
|
||
# 间隔时间(秒,用于 interval 类型)
|
||
interval_seconds = Column(Integer, nullable=True, comment="间隔时间(秒)")
|
||
|
||
# 指定执行时间(用于 date 类型)
|
||
run_date = Column(DateTime, nullable=True, comment="指定执行时间")
|
||
|
||
# 任务函数路径(如:scheduler.tasks.test_task)
|
||
task_func = Column(String(256), nullable=False, comment="任务函数路径")
|
||
|
||
# 任务参数(JSON格式)
|
||
task_args = Column(Text, nullable=True, comment="任务位置参数(JSON数组格式)")
|
||
|
||
# 任务关键字参数(JSON格式)
|
||
task_kwargs = Column(Text, nullable=True, comment="任务关键字参数(JSON对象格式)")
|
||
|
||
# 任务状态
|
||
status = Column(Integer, default=0, index=True, comment="任务状态(0-禁用,1-启用,2-暂停)")
|
||
|
||
# 任务优先级(数字越大优先级越高)
|
||
priority = Column(Integer, default=0, index=True, comment="任务优先级")
|
||
|
||
# 最大实例数(同时运行的任务实例数)
|
||
max_instances = Column(Integer, default=1, comment="最大实例数")
|
||
|
||
# 错误重试次数
|
||
max_retries = Column(Integer, default=0, comment="错误重试次数")
|
||
|
||
# 超时时间(秒)
|
||
timeout = Column(Integer, nullable=True, comment="超时时间(秒)")
|
||
|
||
# 是否合并执行(如果上次未执行完,是否跳过本次)
|
||
coalesce = Column(Boolean, default=True, comment="是否合并执行")
|
||
|
||
# 是否允许并发执行
|
||
allow_concurrent = Column(Boolean, default=False, comment="是否允许并发执行")
|
||
|
||
# 执行统计
|
||
total_run_count = Column(Integer, default=0, comment="总执行次数")
|
||
success_count = Column(Integer, default=0, comment="成功次数")
|
||
failure_count = Column(Integer, default=0, comment="失败次数")
|
||
|
||
# 最后执行时间
|
||
last_run_time = Column(DateTime, nullable=True, comment="最后执行时间")
|
||
|
||
# 下次执行时间
|
||
next_run_time = Column(DateTime, nullable=True, comment="下次执行时间")
|
||
|
||
# 最后执行状态
|
||
last_run_status = Column(String(20), nullable=True, comment="最后执行状态")
|
||
|
||
# 最后执行结果
|
||
last_run_result = Column(Text, nullable=True, comment="最后执行结果")
|
||
|
||
# 备注
|
||
remark = Column(Text, nullable=True, comment="备注信息")
|
||
|
||
# 复合索引
|
||
__table_args__ = (
|
||
Index('ix_scheduler_job_status_trigger', 'status', 'trigger_type'),
|
||
Index('ix_scheduler_job_group_status', 'group', 'status'),
|
||
Index('ix_scheduler_job_priority_status', 'priority', 'status'),
|
||
Index('ix_scheduler_job_next_run_status', 'next_run_time', 'status'),
|
||
)
|
||
|
||
def __str__(self):
|
||
return f"{self.name} ({self.code})"
|
||
|
||
def is_enabled(self) -> bool:
|
||
"""判断任务是否启用"""
|
||
return self.status == 1
|
||
|
||
def is_paused(self) -> bool:
|
||
"""判断任务是否暂停"""
|
||
return self.status == 2
|
||
|
||
def is_disabled(self) -> bool:
|
||
"""判断任务是否禁用"""
|
||
return self.status == 0
|
||
|
||
def get_status_display(self) -> str:
|
||
"""获取状态的显示名称"""
|
||
return self.STATUS_CHOICES.get(self.status, '未知')
|
||
|
||
def get_trigger_type_display(self) -> str:
|
||
"""获取触发器类型的显示名称"""
|
||
return self.TRIGGER_TYPE_CHOICES.get(self.trigger_type, '未知')
|
||
|
||
def get_success_rate(self) -> float:
|
||
"""获取成功率"""
|
||
if self.total_run_count == 0:
|
||
return 0.0
|
||
return round(self.success_count / self.total_run_count * 100, 2)
|
||
|
||
|
||
class SchedulerLog(BaseModel):
|
||
"""
|
||
定时任务执行日志模型
|
||
|
||
功能特点:
|
||
1. 记录每次任务执行的详细信息
|
||
2. 记录执行时间、状态、结果
|
||
3. 记录异常信息
|
||
4. 支持日志查询和统计
|
||
"""
|
||
__tablename__ = "core_scheduler_log"
|
||
|
||
# 执行状态选择
|
||
STATUS_CHOICES = {
|
||
'pending': '等待执行',
|
||
'running': '执行中',
|
||
'success': '执行成功',
|
||
'failed': '执行失败',
|
||
'timeout': '执行超时',
|
||
'skipped': '跳过执行',
|
||
}
|
||
|
||
# 关联的任务ID(逻辑外键)
|
||
job_id = Column(String(36), nullable=False, index=True, comment="任务ID")
|
||
|
||
# 任务名称(冗余字段,便于查询)
|
||
job_name = Column(String(128), nullable=False, index=True, comment="任务名称")
|
||
|
||
# 任务编码(冗余字段,便于查询)
|
||
job_code = Column(String(128), nullable=False, index=True, comment="任务编码")
|
||
|
||
# 执行状态
|
||
status = Column(String(20), default='pending', index=True, comment="执行状态")
|
||
|
||
# 开始时间
|
||
start_time = Column(DateTime, nullable=False, index=True, comment="开始时间")
|
||
|
||
# 结束时间
|
||
end_time = Column(DateTime, nullable=True, comment="结束时间")
|
||
|
||
# 执行耗时(秒)
|
||
duration = Column(Float, nullable=True, comment="执行耗时(秒)")
|
||
|
||
# 执行结果
|
||
result = Column(Text, nullable=True, comment="执行结果")
|
||
|
||
# 异常信息
|
||
exception = Column(Text, nullable=True, comment="异常信息")
|
||
|
||
# 异常堆栈
|
||
traceback = Column(Text, nullable=True, comment="异常堆栈")
|
||
|
||
# 执行主机
|
||
hostname = Column(String(128), nullable=True, comment="执行主机")
|
||
|
||
# 进程ID
|
||
process_id = Column(Integer, nullable=True, comment="进程ID")
|
||
|
||
# 重试次数
|
||
retry_count = Column(Integer, default=0, comment="重试次数")
|
||
|
||
# 复合索引
|
||
__table_args__ = (
|
||
Index('ix_scheduler_log_job_status', 'job_id', 'status'),
|
||
Index('ix_scheduler_log_status_start', 'status', 'start_time'),
|
||
Index('ix_scheduler_log_code_start', 'job_code', 'start_time'),
|
||
)
|
||
|
||
def __str__(self):
|
||
return f"{self.job_name} - {self.status} - {self.start_time}"
|
||
|
||
def is_success(self) -> bool:
|
||
"""判断是否执行成功"""
|
||
return self.status == 'success'
|
||
|
||
def is_failed(self) -> bool:
|
||
"""判断是否执行失败"""
|
||
return self.status == 'failed'
|
||
|
||
def is_running(self) -> bool:
|
||
"""判断是否正在执行"""
|
||
return self.status == 'running'
|
||
|
||
def get_status_display(self) -> str:
|
||
"""获取状态的显示名称"""
|
||
return self.STATUS_CHOICES.get(self.status, '未知')
|