befly 3.16.5 → 3.16.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/befly.js +247 -39
- package/dist/befly.min.js +16 -16
- package/dist/index.js +57 -16
- package/dist/lib/cacheHelper.d.ts +33 -0
- package/dist/lib/cacheHelper.js +185 -0
- package/dist/lib/cacheKeys.d.ts +6 -0
- package/dist/lib/cacheKeys.js +8 -0
- package/dist/lib/redisHelper.d.ts +8 -0
- package/dist/lib/redisHelper.js +57 -0
- package/dist/sync/syncCache.js +2 -0
- package/dist/types/cache.d.ts +27 -0
- package/dist/types/redis.d.ts +10 -0
- package/package.json +2 -2
package/dist/befly.js
CHANGED
|
@@ -9833,6 +9833,7 @@ async function syncCache(ctx) {
|
|
|
9833
9833
|
await ctx.cache.cacheApis();
|
|
9834
9834
|
await ctx.cache.cacheMenus();
|
|
9835
9835
|
await ctx.cache.rebuildRoleApiPermissions();
|
|
9836
|
+
await ctx.cache.rebuildRoleMenuPermissions();
|
|
9836
9837
|
}
|
|
9837
9838
|
|
|
9838
9839
|
// lib/cipher.ts
|
|
@@ -11482,32 +11483,6 @@ var calcPerfTime = (startTime, endTime = Bun.nanoseconds()) => {
|
|
|
11482
11483
|
}
|
|
11483
11484
|
};
|
|
11484
11485
|
|
|
11485
|
-
// utils/processInfo.ts
|
|
11486
|
-
function getProcessRole(env) {
|
|
11487
|
-
const runtimeEnv = env || {};
|
|
11488
|
-
const bunWorkerId = runtimeEnv["BUN_WORKER_ID"];
|
|
11489
|
-
const pm2InstanceId = runtimeEnv["PM2_INSTANCE_ID"];
|
|
11490
|
-
if (bunWorkerId !== undefined) {
|
|
11491
|
-
return {
|
|
11492
|
-
role: bunWorkerId === "" ? "primary" : "worker",
|
|
11493
|
-
instanceId: bunWorkerId || "0",
|
|
11494
|
-
env: "bun-cluster"
|
|
11495
|
-
};
|
|
11496
|
-
}
|
|
11497
|
-
if (pm2InstanceId !== undefined) {
|
|
11498
|
-
return {
|
|
11499
|
-
role: pm2InstanceId === "0" ? "primary" : "worker",
|
|
11500
|
-
instanceId: pm2InstanceId,
|
|
11501
|
-
env: "pm2-cluster"
|
|
11502
|
-
};
|
|
11503
|
-
}
|
|
11504
|
-
return {
|
|
11505
|
-
role: "primary",
|
|
11506
|
-
instanceId: null,
|
|
11507
|
-
env: "standalone"
|
|
11508
|
-
};
|
|
11509
|
-
}
|
|
11510
|
-
|
|
11511
11486
|
// utils/scanSources.ts
|
|
11512
11487
|
init_dist();
|
|
11513
11488
|
|
|
@@ -13109,6 +13084,9 @@ class CacheKeys {
|
|
|
13109
13084
|
static roleInfo(roleCode) {
|
|
13110
13085
|
return `role:info:${roleCode}`;
|
|
13111
13086
|
}
|
|
13087
|
+
static roleMenus(roleCode) {
|
|
13088
|
+
return `role:menus:${roleCode}`;
|
|
13089
|
+
}
|
|
13112
13090
|
static roleApis(roleCode) {
|
|
13113
13091
|
return `role:apis:${roleCode}`;
|
|
13114
13092
|
}
|
|
@@ -13694,6 +13672,25 @@ class CacheHelper {
|
|
|
13694
13672
|
}
|
|
13695
13673
|
return trimmed;
|
|
13696
13674
|
}
|
|
13675
|
+
assertMenuPathname(value, errorPrefix) {
|
|
13676
|
+
if (typeof value !== "string") {
|
|
13677
|
+
throw new Error(`${errorPrefix} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
|
|
13678
|
+
}
|
|
13679
|
+
const trimmed = value.trim();
|
|
13680
|
+
if (!trimmed) {
|
|
13681
|
+
throw new Error(`${errorPrefix} \u4E0D\u5141\u8BB8\u4E3A\u7A7A\u5B57\u7B26\u4E32`);
|
|
13682
|
+
}
|
|
13683
|
+
if (!trimmed.startsWith("/")) {
|
|
13684
|
+
throw new Error(`${errorPrefix} \u5FC5\u987B\u662F pathname\uFF08\u4EE5 / \u5F00\u5934\uFF09`);
|
|
13685
|
+
}
|
|
13686
|
+
if (trimmed.includes(" ")) {
|
|
13687
|
+
throw new Error(`${errorPrefix} \u4E0D\u5141\u8BB8\u5305\u542B\u7A7A\u683C`);
|
|
13688
|
+
}
|
|
13689
|
+
if (trimmed.length > 1 && trimmed.endsWith("/")) {
|
|
13690
|
+
throw new Error(`${errorPrefix} \u4E0D\u5141\u8BB8\u4EE5 / \u7ED3\u5C3E`);
|
|
13691
|
+
}
|
|
13692
|
+
return trimmed;
|
|
13693
|
+
}
|
|
13697
13694
|
assertApiPathList(value, roleCode) {
|
|
13698
13695
|
if (value === null || value === undefined)
|
|
13699
13696
|
return [];
|
|
@@ -13721,6 +13718,33 @@ class CacheHelper {
|
|
|
13721
13718
|
}
|
|
13722
13719
|
return out;
|
|
13723
13720
|
}
|
|
13721
|
+
assertMenuPathList(value, roleCode) {
|
|
13722
|
+
if (value === null || value === undefined)
|
|
13723
|
+
return [];
|
|
13724
|
+
let list = value;
|
|
13725
|
+
if (typeof list === "string") {
|
|
13726
|
+
const trimmed = list.trim();
|
|
13727
|
+
if (trimmed === "" || trimmed === "null") {
|
|
13728
|
+
return [];
|
|
13729
|
+
}
|
|
13730
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
13731
|
+
try {
|
|
13732
|
+
list = JSON.parse(trimmed);
|
|
13733
|
+
} catch {
|
|
13734
|
+
throw new Error(`\u89D2\u8272\u83DC\u5355\u6743\u9650\u6570\u636E\u4E0D\u5408\u6CD5\uFF1Aaddon_admin_role.menus JSON \u89E3\u6790\u5931\u8D25\uFF0CroleCode=${roleCode}`);
|
|
13735
|
+
}
|
|
13736
|
+
}
|
|
13737
|
+
}
|
|
13738
|
+
if (!Array.isArray(list)) {
|
|
13739
|
+
const typeLabel = typeof list;
|
|
13740
|
+
throw new Error(`\u89D2\u8272\u83DC\u5355\u6743\u9650\u6570\u636E\u4E0D\u5408\u6CD5\uFF1Aaddon_admin_role.menus \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4\u6216 JSON \u6570\u7EC4\u5B57\u7B26\u4E32\uFF0CroleCode=${roleCode}\uFF0Ctype=${typeLabel}`);
|
|
13741
|
+
}
|
|
13742
|
+
const out = [];
|
|
13743
|
+
for (const item of list) {
|
|
13744
|
+
out.push(this.assertMenuPathname(item, `\u89D2\u8272\u83DC\u5355\u6743\u9650\u6570\u636E\u4E0D\u5408\u6CD5\uFF1Aaddon_admin_role.menus \u5143\u7D20\uFF0CroleCode=${roleCode}`));
|
|
13745
|
+
}
|
|
13746
|
+
return out;
|
|
13747
|
+
}
|
|
13724
13748
|
async cacheApis() {
|
|
13725
13749
|
try {
|
|
13726
13750
|
const tableExists = await this.db.tableExists("addon_admin_api");
|
|
@@ -13807,6 +13831,56 @@ class CacheHelper {
|
|
|
13807
13831
|
});
|
|
13808
13832
|
}
|
|
13809
13833
|
}
|
|
13834
|
+
async rebuildRoleMenuPermissions() {
|
|
13835
|
+
try {
|
|
13836
|
+
const roleTableExists = await this.db.tableExists("addon_admin_role");
|
|
13837
|
+
if (!roleTableExists.data) {
|
|
13838
|
+
Logger.warn("\u26A0\uFE0F \u89D2\u8272\u8868\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u89D2\u8272\u83DC\u5355\u6743\u9650\u7F13\u5B58");
|
|
13839
|
+
return;
|
|
13840
|
+
}
|
|
13841
|
+
const roles = await this.db.getAll({
|
|
13842
|
+
table: "addon_admin_role",
|
|
13843
|
+
fields: ["code", "menus"]
|
|
13844
|
+
});
|
|
13845
|
+
const roleMenuPathsMap = new Map;
|
|
13846
|
+
for (const role of roles.data.lists) {
|
|
13847
|
+
if (!role?.code)
|
|
13848
|
+
continue;
|
|
13849
|
+
const menuPaths = this.assertMenuPathList(role.menus, role.code);
|
|
13850
|
+
roleMenuPathsMap.set(role.code, menuPaths);
|
|
13851
|
+
}
|
|
13852
|
+
const roleCodes = Array.from(roleMenuPathsMap.keys());
|
|
13853
|
+
if (roleCodes.length === 0) {
|
|
13854
|
+
Logger.info("\u2705 \u6CA1\u6709\u9700\u8981\u7F13\u5B58\u7684\u89D2\u8272\u83DC\u5355\u6743\u9650");
|
|
13855
|
+
return;
|
|
13856
|
+
}
|
|
13857
|
+
const roleKeys = roleCodes.map((code) => CacheKeys.roleMenus(code));
|
|
13858
|
+
await this.redis.delBatch(roleKeys);
|
|
13859
|
+
const items = [];
|
|
13860
|
+
for (const roleCode of roleCodes) {
|
|
13861
|
+
const menuPaths = roleMenuPathsMap.get(roleCode) || [];
|
|
13862
|
+
const members = Array.from(new Set(menuPaths)).sort();
|
|
13863
|
+
if (members.length > 0) {
|
|
13864
|
+
items.push({ key: CacheKeys.roleMenus(roleCode), members });
|
|
13865
|
+
}
|
|
13866
|
+
}
|
|
13867
|
+
if (items.length > 0) {
|
|
13868
|
+
await this.redis.saddBatch(items);
|
|
13869
|
+
}
|
|
13870
|
+
} catch (error) {
|
|
13871
|
+
Logger.error({ err: error, msg: "\u26A0\uFE0F \u89D2\u8272\u83DC\u5355\u6743\u9650\u7F13\u5B58\u5F02\u5E38\uFF08\u5C06\u963B\u65AD\u542F\u52A8\uFF09" });
|
|
13872
|
+
throw new CoreError({
|
|
13873
|
+
kind: "runtime",
|
|
13874
|
+
message: "\u26A0\uFE0F \u89D2\u8272\u83DC\u5355\u6743\u9650\u7F13\u5B58\u5F02\u5E38\uFF08\u5C06\u963B\u65AD\u542F\u52A8\uFF09",
|
|
13875
|
+
logged: true,
|
|
13876
|
+
cause: error,
|
|
13877
|
+
meta: {
|
|
13878
|
+
subsystem: "cache",
|
|
13879
|
+
operation: "rebuildRoleMenuPermissions"
|
|
13880
|
+
}
|
|
13881
|
+
});
|
|
13882
|
+
}
|
|
13883
|
+
}
|
|
13810
13884
|
async refreshRoleApiPermissions(roleCode, apiPaths) {
|
|
13811
13885
|
if (!roleCode || typeof roleCode !== "string") {
|
|
13812
13886
|
throw new Error("roleCode \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
@@ -13826,10 +13900,30 @@ class CacheHelper {
|
|
|
13826
13900
|
await this.redis.sadd(roleKey, members);
|
|
13827
13901
|
}
|
|
13828
13902
|
}
|
|
13903
|
+
async refreshRoleMenuPermissions(roleCode, menuPaths) {
|
|
13904
|
+
if (!roleCode || typeof roleCode !== "string") {
|
|
13905
|
+
throw new Error("roleCode \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
13906
|
+
}
|
|
13907
|
+
if (!Array.isArray(menuPaths)) {
|
|
13908
|
+
throw new Error("menuPaths \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
13909
|
+
}
|
|
13910
|
+
const normalizedPaths = menuPaths.map((p) => this.assertMenuPathname(p, `refreshRoleMenuPermissions: menuPaths \u5143\u7D20\uFF0CroleCode=${roleCode}`));
|
|
13911
|
+
const roleKey = CacheKeys.roleMenus(roleCode);
|
|
13912
|
+
if (normalizedPaths.length === 0) {
|
|
13913
|
+
await this.redis.del(roleKey);
|
|
13914
|
+
return;
|
|
13915
|
+
}
|
|
13916
|
+
const members = Array.from(new Set(normalizedPaths));
|
|
13917
|
+
await this.redis.del(roleKey);
|
|
13918
|
+
if (members.length > 0) {
|
|
13919
|
+
await this.redis.sadd(roleKey, members);
|
|
13920
|
+
}
|
|
13921
|
+
}
|
|
13829
13922
|
async cacheAll() {
|
|
13830
13923
|
await this.cacheApis();
|
|
13831
13924
|
await this.cacheMenus();
|
|
13832
13925
|
await this.rebuildRoleApiPermissions();
|
|
13926
|
+
await this.rebuildRoleMenuPermissions();
|
|
13833
13927
|
}
|
|
13834
13928
|
async getApis() {
|
|
13835
13929
|
try {
|
|
@@ -13858,6 +13952,15 @@ class CacheHelper {
|
|
|
13858
13952
|
return [];
|
|
13859
13953
|
}
|
|
13860
13954
|
}
|
|
13955
|
+
async getRoleMenuPermissions(roleCode) {
|
|
13956
|
+
try {
|
|
13957
|
+
const permissions = await this.redis.smembers(CacheKeys.roleMenus(roleCode));
|
|
13958
|
+
return permissions || [];
|
|
13959
|
+
} catch (error) {
|
|
13960
|
+
Logger.error({ err: error, roleCode, msg: "\u83B7\u53D6\u89D2\u8272\u83DC\u5355\u6743\u9650\u7F13\u5B58\u5931\u8D25" });
|
|
13961
|
+
return [];
|
|
13962
|
+
}
|
|
13963
|
+
}
|
|
13861
13964
|
async checkRolePermission(roleCode, apiPath) {
|
|
13862
13965
|
try {
|
|
13863
13966
|
const pathname = this.assertApiPathname(apiPath, "checkRolePermission: apiPath");
|
|
@@ -13867,6 +13970,15 @@ class CacheHelper {
|
|
|
13867
13970
|
return false;
|
|
13868
13971
|
}
|
|
13869
13972
|
}
|
|
13973
|
+
async checkRoleMenuPermission(roleCode, menuPath) {
|
|
13974
|
+
try {
|
|
13975
|
+
const pathname = this.assertMenuPathname(menuPath, "checkRoleMenuPermission: menuPath");
|
|
13976
|
+
return await this.redis.sismember(CacheKeys.roleMenus(roleCode), pathname);
|
|
13977
|
+
} catch (error) {
|
|
13978
|
+
Logger.error({ err: error, roleCode, msg: "\u68C0\u67E5\u89D2\u8272\u83DC\u5355\u6743\u9650\u5931\u8D25" });
|
|
13979
|
+
return false;
|
|
13980
|
+
}
|
|
13981
|
+
}
|
|
13870
13982
|
async deleteRolePermissions(roleCode) {
|
|
13871
13983
|
try {
|
|
13872
13984
|
const result = await this.redis.del(CacheKeys.roleApis(roleCode));
|
|
@@ -13880,6 +13992,19 @@ class CacheHelper {
|
|
|
13880
13992
|
return false;
|
|
13881
13993
|
}
|
|
13882
13994
|
}
|
|
13995
|
+
async deleteRoleMenuPermissions(roleCode) {
|
|
13996
|
+
try {
|
|
13997
|
+
const result = await this.redis.del(CacheKeys.roleMenus(roleCode));
|
|
13998
|
+
if (result > 0) {
|
|
13999
|
+
Logger.info(`\u2705 \u5DF2\u5220\u9664\u89D2\u8272 ${roleCode} \u7684\u83DC\u5355\u6743\u9650\u7F13\u5B58`);
|
|
14000
|
+
return true;
|
|
14001
|
+
}
|
|
14002
|
+
return false;
|
|
14003
|
+
} catch (error) {
|
|
14004
|
+
Logger.error({ err: error, roleCode, msg: "\u5220\u9664\u89D2\u8272\u83DC\u5355\u6743\u9650\u7F13\u5B58\u5931\u8D25" });
|
|
14005
|
+
return false;
|
|
14006
|
+
}
|
|
14007
|
+
}
|
|
13883
14008
|
}
|
|
13884
14009
|
|
|
13885
14010
|
// plugins/cache.ts
|
|
@@ -16293,6 +16418,52 @@ class RedisHelper {
|
|
|
16293
16418
|
return null;
|
|
16294
16419
|
}
|
|
16295
16420
|
}
|
|
16421
|
+
async tryAcquireLock(key, token, ttlMs) {
|
|
16422
|
+
try {
|
|
16423
|
+
if (!key || typeof key !== "string") {
|
|
16424
|
+
throw new Error("tryAcquireLock: key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
16425
|
+
}
|
|
16426
|
+
if (!token || typeof token !== "string") {
|
|
16427
|
+
throw new Error("tryAcquireLock: token \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
16428
|
+
}
|
|
16429
|
+
if (!(typeof ttlMs === "number" && Number.isFinite(ttlMs) && ttlMs > 0)) {
|
|
16430
|
+
throw new Error("tryAcquireLock: ttlMs \u5FC5\u987B\u662F\u6B63\u6570");
|
|
16431
|
+
}
|
|
16432
|
+
const pkey = `${this.prefix}${key}`;
|
|
16433
|
+
const startTime = Date.now();
|
|
16434
|
+
const ttlMsString = String(Math.floor(ttlMs));
|
|
16435
|
+
const res = await this.client.set(pkey, token, "NX", "PX", ttlMsString);
|
|
16436
|
+
const duration = Date.now() - startTime;
|
|
16437
|
+
this.logSlow("SET NX PX", pkey, duration, { ttlMs });
|
|
16438
|
+
return res === "OK";
|
|
16439
|
+
} catch (error) {
|
|
16440
|
+
Logger.error({ err: error, msg: "Redis tryAcquireLock \u9519\u8BEF" });
|
|
16441
|
+
return false;
|
|
16442
|
+
}
|
|
16443
|
+
}
|
|
16444
|
+
async releaseLock(key, token) {
|
|
16445
|
+
try {
|
|
16446
|
+
if (!key || typeof key !== "string") {
|
|
16447
|
+
throw new Error("releaseLock: key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
16448
|
+
}
|
|
16449
|
+
if (!token || typeof token !== "string") {
|
|
16450
|
+
throw new Error("releaseLock: token \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
16451
|
+
}
|
|
16452
|
+
const pkey = `${this.prefix}${key}`;
|
|
16453
|
+
const startTime = Date.now();
|
|
16454
|
+
const current = await this.client.get(pkey);
|
|
16455
|
+
if (current !== token) {
|
|
16456
|
+
return false;
|
|
16457
|
+
}
|
|
16458
|
+
const deleted = await this.client.del(pkey);
|
|
16459
|
+
const duration = Date.now() - startTime;
|
|
16460
|
+
this.logSlow("GET+DEL", pkey, duration);
|
|
16461
|
+
return deleted > 0;
|
|
16462
|
+
} catch (error) {
|
|
16463
|
+
Logger.error({ err: error, msg: "Redis releaseLock \u9519\u8BEF" });
|
|
16464
|
+
return false;
|
|
16465
|
+
}
|
|
16466
|
+
}
|
|
16296
16467
|
async getString(key) {
|
|
16297
16468
|
try {
|
|
16298
16469
|
const pkey = `${this.prefix}${key}`;
|
|
@@ -16884,17 +17055,57 @@ class Befly {
|
|
|
16884
17055
|
});
|
|
16885
17056
|
this.plugins = await loadPlugins(plugins, this.context);
|
|
16886
17057
|
this.assertStartContextReady();
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
const
|
|
16891
|
-
const
|
|
16892
|
-
|
|
16893
|
-
|
|
17058
|
+
const syncLockKey = "sync:lock";
|
|
17059
|
+
const syncReadyKey = "sync:ready";
|
|
17060
|
+
const syncLockTtlMs = 10 * 60 * 1000;
|
|
17061
|
+
const syncWaitReadyMaxMs = 120 * 1000;
|
|
17062
|
+
const syncWaitPollMs = 250;
|
|
17063
|
+
const syncToken = `${process.pid}:${Bun.nanoseconds()}`;
|
|
17064
|
+
const ctx = this.context;
|
|
17065
|
+
const acquired = await ctx.redis.tryAcquireLock(syncLockKey, syncToken, syncLockTtlMs);
|
|
17066
|
+
if (acquired) {
|
|
17067
|
+
Logger.info({ key: syncLockKey, msg: "\u2705 \u5DF2\u83B7\u53D6\u542F\u52A8\u540C\u6B65\u9501\uFF0C\u5C06\u6267\u884C\u81EA\u52A8\u540C\u6B65" });
|
|
17068
|
+
await ctx.redis.del(syncReadyKey);
|
|
17069
|
+
try {
|
|
17070
|
+
await new SyncTable(ctx).run(tables);
|
|
17071
|
+
await syncApi(ctx, apis);
|
|
17072
|
+
await syncMenu(ctx, checkedMenus);
|
|
17073
|
+
const devEmail = this.config.devEmail;
|
|
17074
|
+
const devPassword = this.config.devPassword;
|
|
17075
|
+
if (typeof devEmail === "string" && devEmail.length > 0 && typeof devPassword === "string" && devPassword.length > 0) {
|
|
17076
|
+
await syncDev(ctx, { devEmail, devPassword });
|
|
17077
|
+
} else {
|
|
17078
|
+
Logger.debug("\u8DF3\u8FC7 syncDev\uFF1A\u672A\u914D\u7F6E devEmail/devPassword");
|
|
17079
|
+
}
|
|
17080
|
+
await syncCache(ctx);
|
|
17081
|
+
await ctx.redis.setString(syncReadyKey, String(Date.now()), 60 * 60);
|
|
17082
|
+
} finally {
|
|
17083
|
+
const released = await ctx.redis.releaseLock(syncLockKey, syncToken);
|
|
17084
|
+
if (!released) {
|
|
17085
|
+
Logger.warn({ key: syncLockKey, msg: "\u540C\u6B65\u9501\u672A\u80FD\u4E3B\u52A8\u91CA\u653E\uFF08\u5C06\u4F9D\u8D56 TTL \u81EA\u52A8\u91CA\u653E\uFF09" });
|
|
17086
|
+
}
|
|
17087
|
+
}
|
|
16894
17088
|
} else {
|
|
16895
|
-
Logger.
|
|
17089
|
+
Logger.info({ key: syncLockKey, msg: "\u542F\u52A8\u540C\u6B65\u9501\u88AB\u5360\u7528\uFF1A\u7B49\u5F85\u540C\u6B65\u5B8C\u6210\u6807\u8BB0" });
|
|
17090
|
+
const waitStart = Date.now();
|
|
17091
|
+
while (true) {
|
|
17092
|
+
const ready = await ctx.redis.getString(syncReadyKey);
|
|
17093
|
+
if (typeof ready === "string" && ready.length > 0) {
|
|
17094
|
+
Logger.info({ key: syncReadyKey, msg: "\u2705 \u68C0\u6D4B\u5230\u540C\u6B65\u5B8C\u6210\u6807\u8BB0\uFF0C\u5C06\u8DF3\u8FC7\u81EA\u52A8\u540C\u6B65" });
|
|
17095
|
+
break;
|
|
17096
|
+
}
|
|
17097
|
+
const elapsed = Date.now() - waitStart;
|
|
17098
|
+
if (elapsed >= syncWaitReadyMaxMs) {
|
|
17099
|
+
throw new CoreError({
|
|
17100
|
+
kind: "runtime",
|
|
17101
|
+
message: `\u542F\u52A8\u7B49\u5F85\u540C\u6B65\u5B8C\u6210\u8D85\u65F6\uFF08${syncWaitReadyMaxMs}ms\uFF09\uFF1A\u8BF7\u68C0\u67E5\u662F\u5426\u6709\u5B9E\u4F8B\u5361\u5728\u540C\u6B65\u9636\u6BB5\u6216 Redis \u9501 TTL \u8FC7\u957F`,
|
|
17102
|
+
logged: true,
|
|
17103
|
+
meta: { subsystem: "start", operation: "waitSyncReady" }
|
|
17104
|
+
});
|
|
17105
|
+
}
|
|
17106
|
+
await Bun.sleep(syncWaitPollMs);
|
|
17107
|
+
}
|
|
16896
17108
|
}
|
|
16897
|
-
await syncCache(this.context);
|
|
16898
17109
|
this.hooks = await loadHooks(hooks);
|
|
16899
17110
|
this.apis = await loadApis(apis);
|
|
16900
17111
|
const apiFetch = apiHandler(this.apis, this.hooks, this.context);
|
|
@@ -16930,10 +17141,7 @@ class Befly {
|
|
|
16930
17141
|
}
|
|
16931
17142
|
});
|
|
16932
17143
|
const finalStartupTime = calcPerfTime(serverStartTime);
|
|
16933
|
-
|
|
16934
|
-
const roleLabel = processRole.role === "primary" ? "\u4E3B\u8FDB\u7A0B" : `\u5DE5\u4F5C\u8FDB\u7A0B #${processRole.instanceId}`;
|
|
16935
|
-
const envLabel = processRole.env === "standalone" ? "" : ` [${processRole.env}]`;
|
|
16936
|
-
Logger.info(`${this.config.appName} \u542F\u52A8\u6210\u529F! (${roleLabel}${envLabel})`);
|
|
17144
|
+
Logger.info(`${this.config.appName} \u542F\u52A8\u6210\u529F!`);
|
|
16937
17145
|
Logger.info(`\u670D\u52A1\u5668\u542F\u52A8\u8017\u65F6: ${finalStartupTime}`);
|
|
16938
17146
|
Logger.info(`\u670D\u52A1\u5668\u76D1\u542C\u5730\u5740: ${server.url}`);
|
|
16939
17147
|
return server;
|