From 5137addacc506d01368f8c80f5879840aba69c47 Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Tue, 6 Jan 2026 15:58:23 +0800 Subject: [PATCH] Optimize scheduler status lookups --- database.py | 1 + db/accounts.py | 31 ++++++++++++++++++++++++++++++- docker-compose.yml | 3 +++ services/scheduler.py | 15 ++++++++++++++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/database.py b/database.py index 8005013..50ea91d 100644 --- a/database.py +++ b/database.py @@ -40,6 +40,7 @@ from db.accounts import ( delete_user_accounts, get_account, get_account_status, + get_account_status_batch, get_user_accounts, increment_account_login_fail, reset_account_login_status, diff --git a/db/accounts.py b/db/accounts.py index c1211ec..85e4132 100644 --- a/db/accounts.py +++ b/db/accounts.py @@ -140,6 +140,36 @@ def get_account_status(account_id): return cursor.fetchone() +def get_account_status_batch(account_ids): + """批量获取账号状态信息""" + account_ids = [str(account_id) for account_id in (account_ids or []) if account_id] + if not account_ids: + return {} + + results = {} + chunk_size = 900 # 避免触发 SQLite 绑定参数上限 + with db_pool.get_db() as conn: + cursor = conn.cursor() + for idx in range(0, len(account_ids), chunk_size): + chunk = account_ids[idx : idx + chunk_size] + placeholders = ",".join("?" for _ in chunk) + cursor.execute( + f""" + SELECT id, status, login_fail_count, last_login_error + FROM accounts + WHERE id IN ({placeholders}) + """, + chunk, + ) + for row in cursor.fetchall(): + row_dict = dict(row) + account_id = str(row_dict.pop("id", "")) + if account_id: + results[account_id] = row_dict + + return results + + def delete_user_accounts(user_id): """删除用户的所有账号""" with db_pool.get_db() as conn: @@ -147,4 +177,3 @@ def delete_user_accounts(user_id): cursor.execute("DELETE FROM accounts WHERE user_id = ?", (user_id,)) conn.commit() return cursor.rowcount - diff --git a/docker-compose.yml b/docker-compose.yml index 0b7653e..0aaf3eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ services: # 数据库配置 - DB_FILE=data/app_data.db - DB_POOL_SIZE=5 + - SYSTEM_CONFIG_CACHE_TTL_SECONDS=30 # 并发控制配置 - MAX_CONCURRENT_GLOBAL=2 - MAX_CONCURRENT_PER_ACCOUNT=1 @@ -45,6 +46,8 @@ services: - LOG_FILE=logs/app.log - API_DIAGNOSTIC_LOG=0 - API_DIAGNOSTIC_SLOW_MS=0 + # 状态推送节流(秒) + - STATUS_PUSH_INTERVAL_SECONDS=2 # wkhtmltoimage 截图配置 - WKHTMLTOIMAGE_FULL_PAGE=0 # 知识管理平台配置 diff --git a/services/scheduler.py b/services/scheduler.py index 1275cb6..c562bb1 100644 --- a/services/scheduler.py +++ b/services/scheduler.py @@ -87,19 +87,32 @@ def run_scheduled_task(skip_weekday_check: bool = False) -> None: cfg = database.get_system_config() enable_screenshot_scheduled = cfg.get("enable_screenshot", 0) == 1 + user_accounts = {} + account_ids = [] for user in approved_users: user_id = user["id"] accounts = safe_get_user_accounts_snapshot(user_id) if not accounts: load_user_accounts(user_id) accounts = safe_get_user_accounts_snapshot(user_id) + if accounts: + user_accounts[user_id] = accounts + account_ids.extend(list(accounts.keys())) + + account_statuses = database.get_account_status_batch(account_ids) + + for user in approved_users: + user_id = user["id"] + accounts = user_accounts.get(user_id, {}) + if not accounts: + continue for account_id, account in accounts.items(): total_accounts += 1 if account.is_running: continue - account_status_info = database.get_account_status(account_id) + account_status_info = account_statuses.get(str(account_id)) if account_status_info: status = account_status_info["status"] if "status" in account_status_info.keys() else "active" if status == "suspended":