From e26c412c47134ba7dc34563cc3026a2103ad117e Mon Sep 17 00:00:00 2001 From: mtvpls Date: Wed, 24 Dec 2025 23:43:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3getAllUsers()=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=90=AF=E5=8A=A8=E6=97=B6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E6=89=A7=E8=A1=8C=E5=A4=9A=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/config.ts | 105 ++++++++++++++++++++++----------------- src/lib/redis-base.db.ts | 13 +++-- src/lib/upstash.db.ts | 13 +++-- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/lib/config.ts b/src/lib/config.ts index bfbebbf..4762d6e 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -55,6 +55,7 @@ export const API_CONFIG = { // 在模块加载时根据环境决定配置来源 let cachedConfig: AdminConfig; +let configInitPromise: Promise | null = null; // 从配置文件补充管理员配置 @@ -303,57 +304,69 @@ export async function getConfig(): Promise { return cachedConfig; } - // 读 db - let adminConfig: AdminConfig | null = null; - let dbReadFailed = false; - try { - adminConfig = await db.getAdminConfig(); - } catch (e) { - console.error('获取管理员配置失败:', e); - dbReadFailed = true; + // 如果正在初始化,等待初始化完成 + if (configInitPromise) { + return configInitPromise; } - // db 中无配置,执行一次初始化 - if (!adminConfig) { - if (dbReadFailed) { - // 数据库读取失败,使用默认配置但不保存,避免覆盖数据库 - console.warn('数据库读取失败,使用临时默认配置(不会保存到数据库)'); - adminConfig = await getInitConfig(""); - } else { - // 数据库中确实没有配置,首次初始化并保存 - console.log('首次初始化配置'); - adminConfig = await getInitConfig(""); - await db.saveAdminConfig(adminConfig); - } - } - adminConfig = configSelfCheck(adminConfig); - cachedConfig = adminConfig; - - // 自动迁移用户(如果配置中有用户且V2存储支持) - // 过滤掉站长后检查是否有需要迁移的用户 - const nonOwnerUsers = adminConfig.UserConfig.Users.filter( - (u) => u.username !== process.env.USERNAME - ); - if (!dbReadFailed && nonOwnerUsers.length > 0) { + // 创建初始化 Promise + configInitPromise = (async () => { + // 读 db + let adminConfig: AdminConfig | null = null; + let dbReadFailed = false; try { - // 检查是否支持V2存储 - const storage = (db as any).storage; - if (storage && typeof storage.createUserV2 === 'function') { - console.log('检测到配置中有用户,开始自动迁移...'); - await db.migrateUsersFromConfig(adminConfig); - // 迁移完成后,清空配置中的用户列表并保存 - adminConfig.UserConfig.Users = []; - await db.saveAdminConfig(adminConfig); - cachedConfig = adminConfig; - console.log('用户自动迁移完成'); - } - } catch (error) { - console.error('自动迁移用户失败:', error); - // 不影响主流程,继续执行 + adminConfig = await db.getAdminConfig(); + } catch (e) { + console.error('获取管理员配置失败:', e); + dbReadFailed = true; } - } - return cachedConfig; + // db 中无配置,执行一次初始化 + if (!adminConfig) { + if (dbReadFailed) { + // 数据库读取失败,使用默认配置但不保存,避免覆盖数据库 + console.warn('数据库读取失败,使用临时默认配置(不会保存到数据库)'); + adminConfig = await getInitConfig(""); + } else { + // 数据库中确实没有配置,首次初始化并保存 + console.log('首次初始化配置'); + adminConfig = await getInitConfig(""); + await db.saveAdminConfig(adminConfig); + } + } + adminConfig = configSelfCheck(adminConfig); + cachedConfig = adminConfig; + + // 自动迁移用户(如果配置中有用户且V2存储支持) + // 过滤掉站长后检查是否有需要迁移的用户 + const nonOwnerUsers = adminConfig.UserConfig.Users.filter( + (u) => u.username !== process.env.USERNAME + ); + if (!dbReadFailed && nonOwnerUsers.length > 0) { + try { + // 检查是否支持V2存储 + const storage = (db as any).storage; + if (storage && typeof storage.createUserV2 === 'function') { + console.log('检测到配置中有用户,开始自动迁移...'); + await db.migrateUsersFromConfig(adminConfig); + // 迁移完成后,清空配置中的用户列表并保存 + adminConfig.UserConfig.Users = []; + await db.saveAdminConfig(adminConfig); + cachedConfig = adminConfig; + console.log('用户自动迁移完成'); + } + } catch (error) { + console.error('自动迁移用户失败:', error); + // 不影响主流程,继续执行 + } + } + + // 清除初始化 Promise + configInitPromise = null; + return cachedConfig; + })(); + + return configInitPromise; } export function configSelfCheck(adminConfig: AdminConfig): AdminConfig { diff --git a/src/lib/redis-base.db.ts b/src/lib/redis-base.db.ts index 9a93c48..e513c67 100644 --- a/src/lib/redis-base.db.ts +++ b/src/lib/redis-base.db.ts @@ -645,13 +645,12 @@ export abstract class BaseRedisStorage implements IStorage { // ---------- 获取全部用户 ---------- async getAllUsers(): Promise { - const keys = await this.withRetry(() => this.client.keys('u:*:pwd')); - return keys - .map((k) => { - const match = k.match(/^u:(.+?):pwd$/); - return match ? ensureString(match[1]) : undefined; - }) - .filter((u): u is string => typeof u === 'string'); + // 从新版用户列表获取 + const userListKey = this.userListKey(); + const users = await this.withRetry(() => + this.client.zRange(userListKey, 0, -1) + ); + return users.map(u => ensureString(u)); } // ---------- 管理员配置 ---------- diff --git a/src/lib/upstash.db.ts b/src/lib/upstash.db.ts index b8ed0b1..a0856ed 100644 --- a/src/lib/upstash.db.ts +++ b/src/lib/upstash.db.ts @@ -673,13 +673,12 @@ export class UpstashRedisStorage implements IStorage { // ---------- 获取全部用户 ---------- async getAllUsers(): Promise { - const keys = await withRetry(() => this.client.keys('u:*:pwd')); - return keys - .map((k) => { - const match = k.match(/^u:(.+?):pwd$/); - return match ? ensureString(match[1]) : undefined; - }) - .filter((u): u is string => typeof u === 'string'); + // 从新版用户列表获取 + const userListKey = this.userListKey(); + const users = await withRetry(() => + this.client.zrange(userListKey, 0, -1) + ); + return users.map(u => ensureString(u)); } // ---------- 管理员配置 ----------