diff --git a/app/api/endpoints/dashboard.py b/app/api/endpoints/dashboard.py index 043d3df7..954ededd 100644 --- a/app/api/endpoints/dashboard.py +++ b/app/api/endpoints/dashboard.py @@ -7,7 +7,10 @@ from app import schemas from app.chain.dashboard import DashboardChain from app.core.config import settings from app.core.security import verify_token +from app.scheduler import SchedulerChain, Scheduler +from app.utils.string import StringUtils from app.utils.system import SystemUtils +from app.utils.timer import TimerUtils router = APIRouter() @@ -60,3 +63,30 @@ def downloader(_: schemas.TokenPayload = Depends(verify_token)) -> Any: upload_size=transfer_info.upload_size, free_space=free_space ) + + +@router.get("/schedule", summary="后台服务", response_model=List[schemas.ScheduleInfo]) +def schedule(_: schemas.TokenPayload = Depends(verify_token)) -> Any: + """ + 查询后台服务信息 + """ + # 返回计时任务 + schedulers = [] + # 去重 + added = [] + jobs = Scheduler().list() + for job in jobs: + if job.name not in added: + added.append(job.name) + else: + continue + if not StringUtils.is_chinese(job.name): + continue + schedulers.append(schemas.ScheduleInfo( + id=job.id, + name=job.name, + status="等待" if job.pending else "运行中", + next_run=TimerUtils.time_difference(job.next_run_time) or "已停止" + )) + + return schedulers diff --git a/app/scheduler.py b/app/scheduler.py index b27c2370..81eb3289 100644 --- a/app/scheduler.py +++ b/app/scheduler.py @@ -45,24 +45,28 @@ class Scheduler(metaclass=Singleton): self._scheduler.add_job(CookieCloudChain().process, "interval", minutes=settings.COOKIECLOUD_INTERVAL, - next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=1)) + next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=1), + name="CookieCloud同步") # 新增订阅时搜索(5分钟检查一次) - self._scheduler.add_job(SubscribeChain().search, "interval", minutes=5, kwargs={'state': 'N'}) + self._scheduler.add_job(SubscribeChain().search, "interval", + minutes=5, kwargs={'state': 'N'}) - # 订阅状态每隔12小时刷新一次 - self._scheduler.add_job(SubscribeChain().search, "interval", hours=12, kwargs={'state': 'R'}) + # 订阅状态每隔12小时搜索一次 + self._scheduler.add_job(SubscribeChain().search, "interval", + hours=12, kwargs={'state': 'R'}, name="订阅搜索") # 站点首页种子定时刷新缓存并匹配订阅 triggers = TimerUtils.random_scheduler(num_executions=20) for trigger in triggers: - self._scheduler.add_job(SubscribeChain().refresh, "cron", hour=trigger.hour, minute=trigger.minute) + self._scheduler.add_job(SubscribeChain().refresh, "cron", + hour=trigger.hour, minute=trigger.minute, name="订阅刷新") # 豆瓣同步(每30分钟) - self._scheduler.add_job(DoubanChain().sync, "interval", minutes=30) + self._scheduler.add_job(DoubanChain().sync, "interval", minutes=30, name="同步豆瓣想看") # 下载器文件转移(每5分钟) - self._scheduler.add_job(TransferChain().process, "interval", minutes=5) + self._scheduler.add_job(TransferChain().process, "interval", minutes=5, name="下载文件整理") # 公共定时服务 self._scheduler.add_job(SchedulerChain().scheduler_job, "interval", minutes=10) @@ -73,6 +77,12 @@ class Scheduler(metaclass=Singleton): # 启动定时服务 self._scheduler.start() + def list(self): + """ + 当前所有任务 + """ + return self._scheduler.get_jobs() + def stop(self): """ 关闭定时服务 diff --git a/app/schemas/dashboard.py b/app/schemas/dashboard.py index 621574b9..02dbbd23 100644 --- a/app/schemas/dashboard.py +++ b/app/schemas/dashboard.py @@ -49,3 +49,14 @@ class DownloaderInfo(BaseModel): upload_size: Optional[float] = 0.0 # 剩余空间 free_space: Optional[float] = 0.0 + + +class ScheduleInfo(BaseModel): + # ID + id: Optional[str] = None + # 名称 + name: Optional[str] = None + # 状态 + status: Optional[str] = None + # 下次执行时间 + next_run: Optional[str] = None diff --git a/app/utils/timer.py b/app/utils/timer.py index 1969f288..5a86898d 100644 --- a/app/utils/timer.py +++ b/app/utils/timer.py @@ -37,3 +37,24 @@ class TimerUtils: trigger.append(random_trigger) return trigger + + from datetime import datetime, timedelta + + @staticmethod + def time_difference(input_datetime: datetime) -> str: + current_datetime = datetime.datetime.now(datetime.timezone.utc).astimezone() + time_difference = input_datetime - current_datetime + + days = time_difference.days + hours, remainder = divmod(time_difference.seconds, 3600) + minutes, _ = divmod(remainder, 60) + + time_difference_string = "" + if days > 0: + time_difference_string += f"{days}天" + if hours > 0: + time_difference_string += f"{hours}小时" + if minutes > 0: + time_difference_string += f"{minutes}分钟" + + return time_difference_string