Files
2026-06-08 18:14:59 +08:00

275 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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="任务列表")