feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
"""
|
||||
定时任务调度器模块
|
||||
|
||||
提供定时任务的创建、调度、执行和管理功能。
|
||||
"""
|
||||
|
||||
import time
|
||||
import threading
|
||||
import uuid
|
||||
from typing import Any, Callable, Dict, List, Optional
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
import heapq
|
||||
|
||||
|
||||
class TaskStatus(Enum):
|
||||
"""任务状态"""
|
||||
PENDING = "pending"
|
||||
RUNNING = "running"
|
||||
COMPLETED = "completed"
|
||||
CANCELLED = "cancelled"
|
||||
ERROR = "error"
|
||||
|
||||
|
||||
class SchedulerState(Enum):
|
||||
"""调度器状态"""
|
||||
RUNNING = "running"
|
||||
PAUSED = "paused"
|
||||
STOPPED = "stopped"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Task:
|
||||
"""任务定义"""
|
||||
name: str
|
||||
func: Callable
|
||||
interval: float = 0 # 执行间隔(秒)
|
||||
delay: float = 0 # 延迟执行时间(秒)
|
||||
repeat: bool = False # 是否重复执行
|
||||
priority: int = 5 # 优先级(1-10,数字越大优先级越高)
|
||||
on_error: Optional[Callable[[Exception], None]] = None
|
||||
max_retries: int = 0
|
||||
|
||||
# 内部字段
|
||||
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
||||
status: TaskStatus = TaskStatus.PENDING
|
||||
next_run_time: float = 0
|
||||
execution_count: int = 0
|
||||
error_count: int = 0
|
||||
|
||||
def __post_init__(self):
|
||||
if self.next_run_time == 0:
|
||||
self.next_run_time = time.time() + self.delay
|
||||
|
||||
def __lt__(self, other):
|
||||
# 用于优先级队列比较
|
||||
if self.next_run_time != other.next_run_time:
|
||||
return self.next_run_time < other.next_run_time
|
||||
return self.priority > other.priority
|
||||
|
||||
|
||||
@dataclass
|
||||
class TaskExecutionRecord:
|
||||
"""任务执行记录"""
|
||||
task_id: str
|
||||
task_name: str
|
||||
start_time: float
|
||||
end_time: float
|
||||
success: bool
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
class TaskScheduler:
|
||||
"""
|
||||
任务调度器
|
||||
|
||||
特性:
|
||||
- 支持定时和周期性任务
|
||||
- 支持任务优先级
|
||||
- 支持任务取消
|
||||
- 支持错误处理
|
||||
- 支持暂停/恢复
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化调度器"""
|
||||
self._tasks: Dict[str, Task] = {}
|
||||
self._task_queue: List[Task] = []
|
||||
self._lock = threading.RLock()
|
||||
self._condition = threading.Condition(self._lock)
|
||||
self._state = SchedulerState.STOPPED
|
||||
self._worker_thread: Optional[threading.Thread] = None
|
||||
self._execution_records: List[TaskExecutionRecord] = []
|
||||
self._total_executions = 0
|
||||
self._total_errors = 0
|
||||
|
||||
def start(self) -> None:
|
||||
"""启动调度器"""
|
||||
with self._lock:
|
||||
if self._state == SchedulerState.RUNNING:
|
||||
return
|
||||
|
||||
self._state = SchedulerState.RUNNING
|
||||
self._worker_thread = threading.Thread(target=self._worker_loop, daemon=True)
|
||||
self._worker_thread.start()
|
||||
|
||||
def stop(self) -> None:
|
||||
"""停止调度器"""
|
||||
with self._lock:
|
||||
self._state = SchedulerState.STOPPED
|
||||
self._condition.notify_all()
|
||||
|
||||
if self._worker_thread and self._worker_thread.is_alive():
|
||||
self._worker_thread.join(timeout=5)
|
||||
|
||||
def pause(self) -> None:
|
||||
"""暂停调度器"""
|
||||
with self._lock:
|
||||
self._state = SchedulerState.PAUSED
|
||||
|
||||
def resume(self) -> None:
|
||||
"""恢复调度器"""
|
||||
with self._lock:
|
||||
if self._state == SchedulerState.PAUSED:
|
||||
self._state = SchedulerState.RUNNING
|
||||
self._condition.notify_all()
|
||||
|
||||
def schedule(self, task: Task) -> str:
|
||||
"""
|
||||
调度任务
|
||||
|
||||
Args:
|
||||
task: 要调度的任务
|
||||
|
||||
Returns:
|
||||
任务ID
|
||||
"""
|
||||
with self._lock:
|
||||
self._tasks[task.id] = task
|
||||
heapq.heappush(self._task_queue, task)
|
||||
self._condition.notify()
|
||||
|
||||
# 自动启动调度器
|
||||
if self._state == SchedulerState.STOPPED:
|
||||
self.start()
|
||||
|
||||
return task.id
|
||||
|
||||
def cancel(self, task_id: str) -> bool:
|
||||
"""
|
||||
取消任务
|
||||
|
||||
Args:
|
||||
task_id: 任务ID
|
||||
|
||||
Returns:
|
||||
是否成功取消
|
||||
"""
|
||||
with self._lock:
|
||||
if task_id in self._tasks:
|
||||
task = self._tasks[task_id]
|
||||
task.status = TaskStatus.CANCELLED
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_stats(self) -> Dict[str, Any]:
|
||||
"""
|
||||
获取统计信息
|
||||
|
||||
Returns:
|
||||
统计信息字典
|
||||
"""
|
||||
with self._lock:
|
||||
return {
|
||||
"total_executions": self._total_executions,
|
||||
"total_errors": self._total_errors,
|
||||
"pending_tasks": len([t for t in self._tasks.values() if t.status == TaskStatus.PENDING]),
|
||||
"running_tasks": len([t for t in self._tasks.values() if t.status == TaskStatus.RUNNING]),
|
||||
"state": self._state.value,
|
||||
}
|
||||
|
||||
def _worker_loop(self) -> None:
|
||||
"""工作线程循环"""
|
||||
while True:
|
||||
with self._lock:
|
||||
# 检查状态
|
||||
if self._state == SchedulerState.STOPPED:
|
||||
break
|
||||
|
||||
# 如果暂停,等待恢复
|
||||
while self._state == SchedulerState.PAUSED:
|
||||
self._condition.wait()
|
||||
if self._state == SchedulerState.STOPPED:
|
||||
return
|
||||
|
||||
# 获取下一个要执行的任务
|
||||
task = self._get_next_task()
|
||||
|
||||
if task is None:
|
||||
# 没有任务,等待一段时间
|
||||
self._condition.wait(timeout=0.1)
|
||||
continue
|
||||
|
||||
# 检查任务是否被取消
|
||||
if task.status == TaskStatus.CANCELLED:
|
||||
continue
|
||||
|
||||
# 执行任务
|
||||
task.status = TaskStatus.RUNNING
|
||||
|
||||
# 在锁外执行任务
|
||||
self._execute_task(task)
|
||||
|
||||
def _get_next_task(self) -> Optional[Task]:
|
||||
"""获取下一个要执行的任务"""
|
||||
now = time.time()
|
||||
|
||||
while self._task_queue:
|
||||
task = heapq.heappop(self._task_queue)
|
||||
|
||||
# 检查任务是否有效
|
||||
if task.status == TaskStatus.CANCELLED:
|
||||
continue
|
||||
|
||||
# 检查是否到执行时间
|
||||
if task.next_run_time <= now:
|
||||
return task
|
||||
else:
|
||||
# 还没到时间,放回队列
|
||||
heapq.heappush(self._task_queue, task)
|
||||
break
|
||||
|
||||
return None
|
||||
|
||||
def _execute_task(self, task: Task) -> None:
|
||||
"""执行任务"""
|
||||
# 再次检查任务是否被取消
|
||||
if task.status == TaskStatus.CANCELLED:
|
||||
return
|
||||
|
||||
start_time = time.time()
|
||||
success = False
|
||||
error_msg = None
|
||||
|
||||
try:
|
||||
task.func()
|
||||
success = True
|
||||
task.execution_count += 1
|
||||
except Exception as e:
|
||||
success = False
|
||||
error_msg = str(e)
|
||||
task.error_count += 1
|
||||
|
||||
# 调用错误处理回调
|
||||
if task.on_error:
|
||||
try:
|
||||
task.on_error(e)
|
||||
except:
|
||||
pass
|
||||
|
||||
with self._lock:
|
||||
self._total_errors += 1
|
||||
|
||||
end_time = time.time()
|
||||
|
||||
# 记录执行
|
||||
with self._lock:
|
||||
self._total_executions += 1
|
||||
self._execution_records.append(TaskExecutionRecord(
|
||||
task_id=task.id,
|
||||
task_name=task.name,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
success=success,
|
||||
error=error_msg
|
||||
))
|
||||
|
||||
# 处理周期性任务
|
||||
with self._lock:
|
||||
if task.repeat and task.status != TaskStatus.CANCELLED:
|
||||
if task.error_count <= task.max_retries or task.max_retries == 0:
|
||||
task.status = TaskStatus.PENDING
|
||||
task.next_run_time = time.time() + task.interval
|
||||
heapq.heappush(self._task_queue, task)
|
||||
else:
|
||||
task.status = TaskStatus.ERROR
|
||||
else:
|
||||
task.status = TaskStatus.COMPLETED if success else TaskStatus.ERROR
|
||||
Reference in New Issue
Block a user