refactor(scheduler): 优化定时任务配置和时间处理

- 支持CHECK_INTERVAL_HOURS设置为0以禁用密钥检查任务
- 调整日志清理任务执行时间从凌晨3点改为0点
- 移除timezone依赖,使用本地时间处理
- 优化代码格式和导入顺序
- 为配置编辑器添加CHECK_INTERVAL_HOURS输入验证
- 改进UI布局,为关键配置项添加警告提示
This commit is contained in:
snaily
2025-09-18 05:14:43 +08:00
parent 79f47c315e
commit 78f38cc981
5 changed files with 96 additions and 78 deletions
+24 -23
View File
@@ -1,4 +1,3 @@
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from app.config.config import settings
@@ -6,9 +5,9 @@ from app.domain.gemini_models import GeminiContent, GeminiRequest
from app.log.logger import Logger
from app.service.chat.gemini_chat_service import GeminiChatService
from app.service.error_log.error_log_service import delete_old_error_logs
from app.service.files.files_service import get_files_service
from app.service.key.key_manager import get_key_manager_instance
from app.service.request_log.request_log_service import delete_old_request_logs_task
from app.service.files.files_service import get_files_service
from app.utils.helpers import redact_key_for_logging
logger = Logger.setup_logger("scheduler")
@@ -106,15 +105,16 @@ async def cleanup_expired_files():
try:
files_service = await get_files_service()
deleted_count = await files_service.cleanup_expired_files()
if deleted_count > 0:
logger.info(f"Successfully cleaned up {deleted_count} expired files.")
else:
logger.info("No expired files to clean up.")
except Exception as e:
logger.error(
f"An error occurred during the scheduled file cleanup: {str(e)}", exc_info=True
f"An error occurred during the scheduled file cleanup: {str(e)}",
exc_info=True,
)
@@ -122,44 +122,45 @@ def setup_scheduler():
"""设置并启动 APScheduler"""
scheduler = AsyncIOScheduler(timezone=str(settings.TIMEZONE)) # 从配置读取时区
# 添加检查失败密钥的定时任务
scheduler.add_job(
check_failed_keys,
"interval",
hours=settings.CHECK_INTERVAL_HOURS,
id="check_failed_keys_job",
name="Check Failed API Keys",
)
logger.info(
f"Key check job scheduled to run every {settings.CHECK_INTERVAL_HOURS} hour(s)."
)
if settings.CHECK_INTERVAL_HOURS != 0:
scheduler.add_job(
check_failed_keys,
"interval",
hours=settings.CHECK_INTERVAL_HOURS,
id="check_failed_keys_job",
name="Check Failed API Keys",
)
logger.info(
f"Key check job scheduled to run every {settings.CHECK_INTERVAL_HOURS} hour(s)."
)
# 新增:添加自动删除错误日志的定时任务,每天凌晨3点执行
# 新增:添加自动删除错误日志的定时任务,每天凌晨0点执行
scheduler.add_job(
delete_old_error_logs,
"cron",
hour=3,
hour=0,
minute=0,
id="delete_old_error_logs_job",
name="Delete Old Error Logs",
)
logger.info("Auto-delete error logs job scheduled to run daily at 3:00 AM.")
# 新增:添加自动删除请求日志的定时任务,每天凌晨3点05分执行
# 新增:添加自动删除请求日志的定时任务,每天凌晨0点执行
scheduler.add_job(
delete_old_request_logs_task,
"cron",
hour=3,
minute=5,
hour=0,
minute=0,
id="delete_old_request_logs_job",
name="Delete Old Request Logs",
)
logger.info(
f"Auto-delete request logs job scheduled to run daily at 3:05 AM, if enabled and AUTO_DELETE_REQUEST_LOGS_DAYS is set to {settings.AUTO_DELETE_REQUEST_LOGS_DAYS} days."
)
# 新增:添加文件过期清理的定时任务,每小时执行一次
if getattr(settings, 'FILES_CLEANUP_ENABLED', True):
cleanup_interval = getattr(settings, 'FILES_CLEANUP_INTERVAL_HOURS', 1)
if getattr(settings, "FILES_CLEANUP_ENABLED", True):
cleanup_interval = getattr(settings, "FILES_CLEANUP_INTERVAL_HOURS", 1)
scheduler.add_job(
cleanup_expired_files,
"interval",
+2 -2
View File
@@ -1,4 +1,4 @@
from datetime import datetime, timedelta, timezone
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional
from sqlalchemy import delete, func, select
@@ -28,7 +28,7 @@ async def delete_old_error_logs():
)
return
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days_to_keep)
cutoff_date = datetime.now() - timedelta(days=days_to_keep)
logger.info(
f"Attempting to delete error logs older than {days_to_keep} days (before {cutoff_date.strftime('%Y-%m-%d %H:%M:%S %Z')})."
@@ -2,12 +2,12 @@
Service for request log operations.
"""
from datetime import datetime, timedelta, timezone
from datetime import datetime, timedelta
from sqlalchemy import delete
from app.database.connection import database
from app.config.config import settings
from app.database.connection import database
from app.database.models import RequestLog
from app.log.logger import get_request_log_logger
@@ -30,7 +30,7 @@ async def delete_old_request_logs_task():
)
try:
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days_to_keep)
cutoff_date = datetime.now() - timedelta(days=days_to_keep)
query = delete(RequestLog).where(RequestLog.request_time < cutoff_date)
+18
View File
@@ -104,6 +104,24 @@ document.addEventListener("DOMContentLoaded", function () {
});
}
// 检查间隔小时数输入控制
const checkIntervalInput = document.getElementById("CHECK_INTERVAL_HOURS");
if (checkIntervalInput) {
checkIntervalInput.addEventListener("input", function () {
let value = parseFloat(this.value);
if (isNaN(value) || value < 0) {
this.value = 0;
}
});
checkIntervalInput.addEventListener("change", function () {
let value = parseFloat(this.value);
if (isNaN(value) || value < 0) {
this.value = 0;
}
});
}
// Toggle switch events
const toggleSwitches = document.querySelectorAll(".toggle-switch");
toggleSwitches.forEach((toggleSwitch) => {
+49 -50
View File
@@ -1416,25 +1416,31 @@ endblock %} {% block head_extra_styles %}
</div>
<!-- 启用代码执行工具 -->
<div class="mb-6 flex items-center justify-between">
<label
for="TOOLS_CODE_EXECUTION_ENABLED"
class="font-semibold text-gray-700"
>启用代码执行工具</label
>
<div
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
>
<input
type="checkbox"
name="TOOLS_CODE_EXECUTION_ENABLED"
id="TOOLS_CODE_EXECUTION_ENABLED"
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
/>
<div class="mb-6">
<div class="flex items-center justify-between">
<label
for="TOOLS_CODE_EXECUTION_ENABLED"
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
></label>
class="font-semibold text-gray-700"
>启用代码执行工具</label
>
<div
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
>
<input
type="checkbox"
name="TOOLS_CODE_EXECUTION_ENABLED"
id="TOOLS_CODE_EXECUTION_ENABLED"
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
/>
<label
for="TOOLS_CODE_EXECUTION_ENABLED"
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
></label>
</div>
</div>
<div class="warning-text">
<i class="fas fa-exclamation-triangle"></i>
<span>启用代码执行工具与大多数工具调用冲突,不建议开启</span>
</div>
</div>
@@ -2007,25 +2013,31 @@ endblock %} {% block head_extra_styles %}
</h2>
<!-- 启用流式输出优化 -->
<div class="mb-6 flex items-center justify-between">
<label
for="STREAM_OPTIMIZER_ENABLED"
class="font-semibold text-gray-700"
>启用流式输出优化</label
>
<div
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
>
<input
type="checkbox"
name="STREAM_OPTIMIZER_ENABLED"
id="STREAM_OPTIMIZER_ENABLED"
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
/>
<div class="mb-6">
<div class="flex items-center justify-between">
<label
for="STREAM_OPTIMIZER_ENABLED"
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
></label>
class="font-semibold text-gray-700"
>启用流式输出优化</label
>
<div
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
>
<input
type="checkbox"
name="STREAM_OPTIMIZER_ENABLED"
id="STREAM_OPTIMIZER_ENABLED"
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
/>
<label
for="STREAM_OPTIMIZER_ENABLED"
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
></label>
</div>
</div>
<div class="warning-text">
<i class="fas fa-exclamation-triangle"></i>
<span>开启流式优化会在一定程度上减速返回,不建议开启</span>
</div>
</div>
@@ -2185,31 +2197,18 @@ endblock %} {% block head_extra_styles %}
for="CHECK_INTERVAL_HOURS"
class="block font-semibold mb-2 text-gray-700"
>检查间隔(小时)
<i class="fas fa-question-circle text-gray-400 ml-1 cursor-help" title="定时检查密钥状态的间隔时间(单位:小时)"></i>
<i class="fas fa-question-circle text-gray-400 ml-1 cursor-help" title="定时检查密钥状态的间隔时间(单位:小时),设置为0时不进行定时检查"></i>
</label>
<input
type="number"
id="CHECK_INTERVAL_HOURS"
name="CHECK_INTERVAL_HOURS"
min="1"
min="0"
step="1"
class="w-full px-4 py-3 rounded-lg form-input-themed"
/>
</div>
<!-- 时区 -->
<div class="mb-6">
<label for="TIMEZONE" class="block font-semibold mb-2 text-gray-700"
>时区
<i class="fas fa-question-circle text-gray-400 ml-1 cursor-help" title="定时任务使用的时区,格式如 Asia/Shanghai 或 UTC"></i>
</label>
<input
type="text"
id="TIMEZONE"
name="TIMEZONE"
placeholder="例如: Asia/Shanghai"
class="w-full px-4 py-3 rounded-lg form-input-themed"
/>
</div>
</div>
<!-- 日志配置 -->