275 lines
11 KiB
Python
275 lines
11 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Scheduler Schema - 定时任务数据验证和序列化
|
||
"""
|
||
from datetime import datetime
|
||
from typing import Optional, List
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||
|
||
from app.base_schema import CSTDatetime
|
||
|
||
|
||
# ==================== SchedulerJob Schemas ====================
|
||
|
||
class SchedulerJobBase(BaseModel):
|
||
"""定时任务基础Schema"""
|
||
application_id: Optional[str] = Field(None, description="所属应用ID")
|
||
name: str = Field(..., min_length=1, max_length=128, description="任务名称")
|
||
code: str = Field(..., min_length=1, max_length=128, description="任务编码")
|
||
description: Optional[str] = Field(None, description="任务描述")
|
||
group: str = Field(default="default", max_length=64, description="任务分组")
|
||
trigger_type: str = Field(..., description="触发器类型:cron/interval/date")
|
||
cron_expression: Optional[str] = Field(None, max_length=128, description="Cron表达式")
|
||
interval_seconds: Optional[int] = Field(None, ge=1, description="间隔时间(秒)")
|
||
run_date: Optional[datetime] = Field(None, description="指定执行时间")
|
||
task_func: str = Field(..., max_length=256, description="任务函数路径")
|
||
task_args: Optional[str] = Field(None, description="任务位置参数(JSON)")
|
||
task_kwargs: Optional[str] = Field(None, description="任务关键字参数(JSON)")
|
||
status: int = Field(default=0, description="任务状态:0-禁用,1-启用,2-暂停")
|
||
priority: int = Field(default=0, description="任务优先级")
|
||
max_instances: int = Field(default=1, ge=1, description="最大实例数")
|
||
max_retries: int = Field(default=0, ge=0, description="错误重试次数")
|
||
timeout: Optional[int] = Field(None, ge=1, description="超时时间(秒)")
|
||
coalesce: bool = Field(default=True, description="是否合并执行")
|
||
allow_concurrent: bool = Field(default=False, description="是否允许并发执行")
|
||
remark: Optional[str] = Field(None, description="备注信息")
|
||
sort: int = Field(default=0, description="排序")
|
||
|
||
@field_validator('trigger_type')
|
||
@classmethod
|
||
def validate_trigger_type(cls, v):
|
||
"""验证触发器类型"""
|
||
if v not in ['cron', 'interval', 'date']:
|
||
raise ValueError('触发器类型必须是 cron、interval 或 date')
|
||
return v
|
||
|
||
@field_validator('status')
|
||
@classmethod
|
||
def validate_status(cls, v):
|
||
"""验证状态"""
|
||
if v not in [0, 1, 2]:
|
||
raise ValueError('状态必须是 0(禁用)、1(启用)或 2(暂停)')
|
||
return v
|
||
|
||
@field_validator('code')
|
||
@classmethod
|
||
def validate_code(cls, v):
|
||
"""验证任务编码格式"""
|
||
if not v:
|
||
raise ValueError('任务编码不能为空')
|
||
if not v.replace('_', '').isalnum():
|
||
raise ValueError('任务编码只能包含字母、数字和下划线')
|
||
return v
|
||
|
||
|
||
class SchedulerJobCreate(SchedulerJobBase):
|
||
"""定时任务创建Schema"""
|
||
|
||
@field_validator('cron_expression')
|
||
@classmethod
|
||
def validate_cron_expression(cls, v, info):
|
||
"""验证 Cron 表达式"""
|
||
if info.data.get('trigger_type') == 'cron' and not v:
|
||
raise ValueError('Cron 类型任务必须提供 cron_expression')
|
||
return v
|
||
|
||
@field_validator('interval_seconds')
|
||
@classmethod
|
||
def validate_interval_seconds(cls, v, info):
|
||
"""验证间隔时间"""
|
||
if info.data.get('trigger_type') == 'interval' and not v:
|
||
raise ValueError('Interval 类型任务必须提供 interval_seconds')
|
||
return v
|
||
|
||
@field_validator('run_date')
|
||
@classmethod
|
||
def validate_run_date(cls, v, info):
|
||
"""验证指定时间"""
|
||
if info.data.get('trigger_type') == 'date' and not v:
|
||
raise ValueError('Date 类型任务必须提供 run_date')
|
||
return v
|
||
|
||
|
||
class SchedulerJobUpdate(BaseModel):
|
||
"""定时任务更新Schema - 所有字段可选"""
|
||
application_id: Optional[str] = Field(None, description="所属应用ID")
|
||
name: Optional[str] = Field(None, min_length=1, max_length=128, description="任务名称")
|
||
code: Optional[str] = Field(None, min_length=1, max_length=128, description="任务编码")
|
||
description: Optional[str] = Field(None, description="任务描述")
|
||
group: Optional[str] = Field(None, max_length=64, description="任务分组")
|
||
trigger_type: Optional[str] = Field(None, description="触发器类型")
|
||
cron_expression: Optional[str] = Field(None, max_length=128, description="Cron表达式")
|
||
interval_seconds: Optional[int] = Field(None, ge=1, description="间隔时间(秒)")
|
||
run_date: Optional[datetime] = Field(None, description="指定执行时间")
|
||
task_func: Optional[str] = Field(None, max_length=256, description="任务函数路径")
|
||
task_args: Optional[str] = Field(None, description="任务位置参数(JSON)")
|
||
task_kwargs: Optional[str] = Field(None, description="任务关键字参数(JSON)")
|
||
status: Optional[int] = Field(None, description="任务状态")
|
||
priority: Optional[int] = Field(None, description="任务优先级")
|
||
max_instances: Optional[int] = Field(None, ge=1, description="最大实例数")
|
||
max_retries: Optional[int] = Field(None, ge=0, description="错误重试次数")
|
||
timeout: Optional[int] = Field(None, ge=1, description="超时时间(秒)")
|
||
coalesce: Optional[bool] = Field(None, description="是否合并执行")
|
||
allow_concurrent: Optional[bool] = Field(None, description="是否允许并发执行")
|
||
remark: Optional[str] = Field(None, description="备注信息")
|
||
sort: Optional[int] = Field(None, description="排序")
|
||
|
||
|
||
class SchedulerJobResponse(BaseModel):
|
||
"""定时任务响应Schema"""
|
||
id: str
|
||
application_id: Optional[str] = None
|
||
name: str
|
||
code: str
|
||
description: Optional[str] = None
|
||
group: str
|
||
trigger_type: str
|
||
trigger_type_display: Optional[str] = None
|
||
cron_expression: Optional[str] = None
|
||
interval_seconds: Optional[int] = None
|
||
run_date: Optional[CSTDatetime] = None
|
||
task_func: str
|
||
task_args: Optional[str] = None
|
||
task_kwargs: Optional[str] = None
|
||
status: int
|
||
status_display: Optional[str] = None
|
||
priority: int
|
||
max_instances: int
|
||
max_retries: int
|
||
timeout: Optional[int] = None
|
||
coalesce: bool
|
||
allow_concurrent: bool
|
||
total_run_count: int
|
||
success_count: int
|
||
failure_count: int
|
||
success_rate: Optional[float] = None
|
||
last_run_time: Optional[CSTDatetime] = None
|
||
next_run_time: Optional[CSTDatetime] = None
|
||
last_run_status: Optional[str] = None
|
||
last_run_result: Optional[str] = None
|
||
remark: Optional[str] = None
|
||
sort: int = 0
|
||
sys_create_datetime: Optional[CSTDatetime] = None
|
||
sys_update_datetime: Optional[CSTDatetime] = None
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
|
||
class SchedulerJobSimple(BaseModel):
|
||
"""定时任务简化输出(用于选择器)"""
|
||
id: str
|
||
application_id: Optional[str] = None
|
||
name: str
|
||
code: str
|
||
group: str
|
||
status: int
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
|
||
class SchedulerJobBatchDeleteIn(BaseModel):
|
||
"""批量删除输入"""
|
||
ids: List[str] = Field(..., description="任务ID列表")
|
||
|
||
|
||
class SchedulerJobBatchDeleteOut(BaseModel):
|
||
"""批量删除输出"""
|
||
count: int = Field(..., description="删除成功数量")
|
||
failed_ids: List[str] = Field(default=[], description="删除失败的ID列表")
|
||
|
||
|
||
class SchedulerJobBatchUpdateStatusIn(BaseModel):
|
||
"""批量更新状态输入"""
|
||
ids: List[str] = Field(..., description="任务ID列表")
|
||
status: int = Field(..., description="目标状态:0-禁用,1-启用,2-暂停")
|
||
|
||
|
||
class SchedulerJobBatchUpdateStatusOut(BaseModel):
|
||
"""批量更新状态输出"""
|
||
count: int = Field(..., description="更新成功数量")
|
||
|
||
|
||
class SchedulerJobExecuteIn(BaseModel):
|
||
"""立即执行任务输入"""
|
||
job_id: str = Field(..., description="任务ID")
|
||
|
||
|
||
class SchedulerJobExecuteOut(BaseModel):
|
||
"""立即执行任务输出"""
|
||
success: bool = Field(..., description="是否成功")
|
||
message: str = Field(..., description="消息")
|
||
log_id: Optional[str] = Field(None, description="日志ID")
|
||
|
||
|
||
class SchedulerJobStatisticsOut(BaseModel):
|
||
"""任务统计输出"""
|
||
total_jobs: int = Field(..., description="总任务数")
|
||
enabled_jobs: int = Field(..., description="启用任务数")
|
||
disabled_jobs: int = Field(..., description="禁用任务数")
|
||
paused_jobs: int = Field(..., description="暂停任务数")
|
||
total_executions: int = Field(..., description="总执行次数")
|
||
success_executions: int = Field(..., description="成功执行次数")
|
||
failed_executions: int = Field(..., description="失败执行次数")
|
||
success_rate: float = Field(..., description="成功率")
|
||
|
||
|
||
class SchedulerJobSearchRequest(BaseModel):
|
||
"""搜索任务请求"""
|
||
keyword: str = Field(..., description="搜索关键词")
|
||
|
||
|
||
# ==================== SchedulerLog Schemas ====================
|
||
|
||
class SchedulerLogResponse(BaseModel):
|
||
"""定时任务日志响应Schema"""
|
||
id: str
|
||
job_id: str
|
||
job_name: str
|
||
job_code: str
|
||
status: str
|
||
status_display: Optional[str] = None
|
||
start_time: CSTDatetime
|
||
end_time: Optional[CSTDatetime] = None
|
||
duration: Optional[float] = None
|
||
result: Optional[str] = None
|
||
exception: Optional[str] = None
|
||
traceback: Optional[str] = None
|
||
hostname: Optional[str] = None
|
||
process_id: Optional[int] = None
|
||
retry_count: int
|
||
sys_create_datetime: Optional[CSTDatetime] = None
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
|
||
class SchedulerLogBatchDeleteIn(BaseModel):
|
||
"""批量删除日志输入"""
|
||
ids: List[str] = Field(..., description="日志ID列表")
|
||
|
||
|
||
class SchedulerLogBatchDeleteOut(BaseModel):
|
||
"""批量删除日志输出"""
|
||
count: int = Field(..., description="删除成功数量")
|
||
|
||
|
||
class SchedulerLogCleanIn(BaseModel):
|
||
"""清理日志输入"""
|
||
days: int = Field(..., ge=1, description="保留最近N天的日志")
|
||
status: Optional[str] = Field(None, description="只清理指定状态的日志")
|
||
|
||
|
||
class SchedulerLogCleanOut(BaseModel):
|
||
"""清理日志输出"""
|
||
count: int = Field(..., description="清理数量")
|
||
|
||
|
||
# ==================== Scheduler Status Schemas ====================
|
||
|
||
class SchedulerStatusOut(BaseModel):
|
||
"""调度器状态输出"""
|
||
is_running: bool = Field(..., description="是否运行中")
|
||
job_count: int = Field(..., description="任务数量")
|
||
jobs: List[dict] = Field(default=[], description="任务列表")
|