Spaces:
Sleeping
Sleeping
Upload main.py
Browse files
main.py
CHANGED
|
@@ -61,6 +61,7 @@ from core.account import (
|
|
| 61 |
format_account_expiration,
|
| 62 |
load_multi_account_config,
|
| 63 |
load_accounts_from_source,
|
|
|
|
| 64 |
update_accounts_config as _update_accounts_config,
|
| 65 |
delete_account as _delete_account,
|
| 66 |
update_account_disabled_status as _update_account_disabled_status
|
|
@@ -263,6 +264,7 @@ MAX_ACCOUNT_SWITCH_TRIES = config.retry.max_account_switch_tries
|
|
| 263 |
ACCOUNT_FAILURE_THRESHOLD = config.retry.account_failure_threshold
|
| 264 |
RATE_LIMIT_COOLDOWN_SECONDS = config.retry.rate_limit_cooldown_seconds
|
| 265 |
SESSION_CACHE_TTL_SECONDS = config.retry.session_cache_ttl_seconds
|
|
|
|
| 266 |
|
| 267 |
# ---------- 模型映射配置 ----------
|
| 268 |
MODEL_MAPPING = {
|
|
@@ -429,6 +431,71 @@ else:
|
|
| 429 |
logger.info(f"[SYSTEM] 图片静态服务已启用: /images/ -> {IMAGE_DIR} (本地持久化)")
|
| 430 |
|
| 431 |
# ---------- 后台任务启动 ----------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
@app.on_event("startup")
|
| 433 |
async def startup_event():
|
| 434 |
"""应用启动时初始化后台任务"""
|
|
@@ -458,6 +525,15 @@ async def startup_event():
|
|
| 458 |
asyncio.create_task(multi_account_mgr.start_background_cleanup())
|
| 459 |
logger.info("[SYSTEM] 后台缓存清理任务已启动(间隔: 5分钟)")
|
| 460 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
# ---------- 日志脱敏函数 ----------
|
| 462 |
def get_sanitized_logs(limit: int = 100) -> list:
|
| 463 |
"""获取脱敏后的日志列表,按请求ID分组并提取关键事件"""
|
|
|
|
| 61 |
format_account_expiration,
|
| 62 |
load_multi_account_config,
|
| 63 |
load_accounts_from_source,
|
| 64 |
+
reload_accounts as _reload_accounts,
|
| 65 |
update_accounts_config as _update_accounts_config,
|
| 66 |
delete_account as _delete_account,
|
| 67 |
update_account_disabled_status as _update_account_disabled_status
|
|
|
|
| 264 |
ACCOUNT_FAILURE_THRESHOLD = config.retry.account_failure_threshold
|
| 265 |
RATE_LIMIT_COOLDOWN_SECONDS = config.retry.rate_limit_cooldown_seconds
|
| 266 |
SESSION_CACHE_TTL_SECONDS = config.retry.session_cache_ttl_seconds
|
| 267 |
+
AUTO_REFRESH_ACCOUNTS_SECONDS = config.retry.auto_refresh_accounts_seconds
|
| 268 |
|
| 269 |
# ---------- 模型映射配置 ----------
|
| 270 |
MODEL_MAPPING = {
|
|
|
|
| 431 |
logger.info(f"[SYSTEM] 图片静态服务已启用: /images/ -> {IMAGE_DIR} (本地持久化)")
|
| 432 |
|
| 433 |
# ---------- 后台任务启动 ----------
|
| 434 |
+
|
| 435 |
+
# 全局变量:记录上次检测到的账号更新时间(用于自动刷新检测)
|
| 436 |
+
_last_known_accounts_version: float | None = None
|
| 437 |
+
|
| 438 |
+
|
| 439 |
+
async def auto_refresh_accounts_task():
|
| 440 |
+
"""后台任务:定期检查数据库中的账号变化,自动刷新"""
|
| 441 |
+
global multi_account_mgr, _last_known_accounts_version
|
| 442 |
+
|
| 443 |
+
# 初始化:记录当前账号更新时间
|
| 444 |
+
if storage.is_database_enabled() and not os.environ.get("ACCOUNTS_CONFIG"):
|
| 445 |
+
_last_known_accounts_version = await asyncio.to_thread(
|
| 446 |
+
storage.get_accounts_updated_at_sync
|
| 447 |
+
)
|
| 448 |
+
|
| 449 |
+
while True:
|
| 450 |
+
try:
|
| 451 |
+
# 获取配置的刷新间隔(支持热更新)
|
| 452 |
+
refresh_interval = config_manager.auto_refresh_accounts_seconds
|
| 453 |
+
if refresh_interval <= 0:
|
| 454 |
+
# 自动刷新已禁用,等待一段时间后再检查配置
|
| 455 |
+
await asyncio.sleep(60)
|
| 456 |
+
continue
|
| 457 |
+
|
| 458 |
+
await asyncio.sleep(refresh_interval)
|
| 459 |
+
|
| 460 |
+
# 环境变量优先时无需自动刷新
|
| 461 |
+
if os.environ.get("ACCOUNTS_CONFIG"):
|
| 462 |
+
continue
|
| 463 |
+
|
| 464 |
+
# 检查数据库是否启用
|
| 465 |
+
if not storage.is_database_enabled():
|
| 466 |
+
continue
|
| 467 |
+
|
| 468 |
+
# 获取数据库中的账号更新时间
|
| 469 |
+
db_version = await asyncio.to_thread(storage.get_accounts_updated_at_sync)
|
| 470 |
+
if db_version is None:
|
| 471 |
+
continue
|
| 472 |
+
|
| 473 |
+
# 比较更新时间变化
|
| 474 |
+
if _last_known_accounts_version != db_version:
|
| 475 |
+
logger.info("[AUTO-REFRESH] 检测到账号变化,正在自动刷新...")
|
| 476 |
+
|
| 477 |
+
# 重新加载账号配置
|
| 478 |
+
multi_account_mgr = _reload_accounts(
|
| 479 |
+
multi_account_mgr,
|
| 480 |
+
http_client,
|
| 481 |
+
USER_AGENT,
|
| 482 |
+
ACCOUNT_FAILURE_THRESHOLD,
|
| 483 |
+
RATE_LIMIT_COOLDOWN_SECONDS,
|
| 484 |
+
SESSION_CACHE_TTL_SECONDS,
|
| 485 |
+
global_stats
|
| 486 |
+
)
|
| 487 |
+
|
| 488 |
+
_last_known_accounts_version = db_version
|
| 489 |
+
logger.info(f"[AUTO-REFRESH] 账号刷新完成,当前账号数: {len(multi_account_mgr.accounts)}")
|
| 490 |
+
|
| 491 |
+
except asyncio.CancelledError:
|
| 492 |
+
logger.info("[AUTO-REFRESH] 自动刷新任务已停止")
|
| 493 |
+
break
|
| 494 |
+
except Exception as e:
|
| 495 |
+
logger.error(f"[AUTO-REFRESH] 自动刷新任务异常: {type(e).__name__}: {str(e)[:100]}")
|
| 496 |
+
await asyncio.sleep(60) # 出错后等待60秒再重试
|
| 497 |
+
|
| 498 |
+
|
| 499 |
@app.on_event("startup")
|
| 500 |
async def startup_event():
|
| 501 |
"""应用启动时初始化后台任务"""
|
|
|
|
| 525 |
asyncio.create_task(multi_account_mgr.start_background_cleanup())
|
| 526 |
logger.info("[SYSTEM] 后台缓存清理任务已启动(间隔: 5分钟)")
|
| 527 |
|
| 528 |
+
# 启动自动刷新账号任务(仅数据库模式有效)
|
| 529 |
+
if os.environ.get("ACCOUNTS_CONFIG"):
|
| 530 |
+
logger.info("[SYSTEM] 自动刷新账号已跳过(使用 ACCOUNTS_CONFIG)")
|
| 531 |
+
elif storage.is_database_enabled() and AUTO_REFRESH_ACCOUNTS_SECONDS > 0:
|
| 532 |
+
asyncio.create_task(auto_refresh_accounts_task())
|
| 533 |
+
logger.info(f"[SYSTEM] 自动刷新账号任务已启动(间隔: {AUTO_REFRESH_ACCOUNTS_SECONDS}秒)")
|
| 534 |
+
elif storage.is_database_enabled():
|
| 535 |
+
logger.info("[SYSTEM] 自动刷新账号功能已禁用(配置为0)")
|
| 536 |
+
|
| 537 |
# ---------- 日志脱敏函数 ----------
|
| 538 |
def get_sanitized_logs(limit: int = 100) -> list:
|
| 539 |
"""获取脱敏后的日志列表,按请求ID分组并提取关键事件"""
|