befly 3.12.1 → 3.12.3

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/index.js CHANGED
@@ -134,35 +134,32 @@ export class Befly {
134
134
  Logger.info(`${this.config.appName} 启动成功! (${roleLabel}${envLabel})`);
135
135
  Logger.info(`服务器启动耗时: ${finalStartupTime}`);
136
136
  Logger.info(`服务器监听地址: ${server.url}`);
137
- // 7. 注册优雅关闭处理
138
- const gracefulShutdown = async (signal) => {
139
- Logger.info(`收到 ${signal} 信号,开始优雅关闭...`);
140
- // 优雅停止(等待进行中的请求完成)
141
- try {
142
- await server.stop();
143
- Logger.info("HTTP 服务器已停止");
144
- }
145
- catch (error) {
146
- Logger.error({ err: error }, "停止 HTTP 服务器时出错");
147
- }
148
- // 关闭数据库连接
149
- try {
150
- await Connect.disconnect();
151
- Logger.info("数据库连接已关闭");
152
- }
153
- catch (error) {
154
- Logger.error({ err: error }, "关闭数据库连接时出错");
155
- }
156
- Logger.info("服务器已优雅关闭");
157
- process.exit(0);
158
- };
159
- process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
160
- process.on("SIGINT", () => gracefulShutdown("SIGINT"));
137
+ // 注意:作为库代码,这里不注册 SIGINT/SIGTERM 处理器,也不调用 process.exit。
138
+ // 宿主应用应自行处理信号并决定退出策略(包括是否调用 server.stop / Connect.disconnect / Logger.flush)。
161
139
  return server;
162
140
  }
163
141
  catch (error) {
142
+ // 注意:这里不能直接 process.exit(1)
143
+ // - Logger 是异步缓冲写入,exit 会导致日志来不及 flush(实际项目里表现为“完全没打印”)
144
+ // - 作为库代码,也不应该强行终止宿主进程
164
145
  Logger.error({ err: error }, "项目启动失败");
165
- process.exit(1);
146
+ // 尽力把错误日志落盘/输出后再把异常抛给上层。
147
+ try {
148
+ await Logger.flush();
149
+ }
150
+ catch {
151
+ // ignore
152
+ }
153
+ try {
154
+ await Logger.shutdown();
155
+ }
156
+ catch {
157
+ // ignore
158
+ }
159
+ if (error instanceof Error) {
160
+ throw error;
161
+ }
162
+ throw new Error(String(error));
166
163
  }
167
164
  }
168
165
  }
@@ -57,65 +57,12 @@ let appConsoleSink = null;
57
57
  let didWarnIoError = false;
58
58
  let didPruneOldLogFiles = false;
59
59
  let didEnsureLogDir = false;
60
- let didInstallGracefulExitHooks = false;
61
60
  let config = {
62
61
  debug: 0,
63
62
  dir: "./logs",
64
63
  console: 1,
65
64
  maxSize: 10
66
65
  };
67
- function installGracefulExitHooks() {
68
- if (didInstallGracefulExitHooks)
69
- return;
70
- didInstallGracefulExitHooks = true;
71
- const install = (signal, exitCode) => {
72
- // 若业务侧已经注册了 handler,避免我们抢占默认行为
73
- try {
74
- if (typeof process.listenerCount === "function" && process.listenerCount(signal) > 0) {
75
- return;
76
- }
77
- }
78
- catch {
79
- // ignore
80
- }
81
- try {
82
- process.once(signal, () => {
83
- let exited = false;
84
- // 给 flush 一个机会;超过上限则强制退出
85
- const timer = setTimeout(() => {
86
- if (exited)
87
- return;
88
- exited = true;
89
- try {
90
- process.exit(exitCode);
91
- }
92
- catch {
93
- // ignore
94
- }
95
- }, 2000);
96
- void shutdown()
97
- .catch(() => undefined)
98
- .finally(() => {
99
- if (exited)
100
- return;
101
- exited = true;
102
- clearTimeout(timer);
103
- try {
104
- process.exit(exitCode);
105
- }
106
- catch {
107
- // ignore
108
- }
109
- });
110
- });
111
- }
112
- catch {
113
- // ignore
114
- }
115
- };
116
- install("SIGINT", 130);
117
- install("SIGTERM", 143);
118
- }
119
66
  function formatLocalDate(date) {
120
67
  const y = date.getFullYear();
121
68
  const m = date.getMonth() + 1;
@@ -467,6 +414,8 @@ export async function shutdown() {
467
414
  appConsoleSink = null;
468
415
  instance = null;
469
416
  errorInstance = null;
417
+ // shutdown 后允许下一次重新初始化时再次校验/创建目录(测试会清理目录,避免 ENOENT)
418
+ didEnsureLogDir = false;
470
419
  }
471
420
  function normalizePositiveInt(value, fallback, min, max) {
472
421
  if (typeof value !== "number")
@@ -488,9 +437,6 @@ function resolveLogDir() {
488
437
  return nodePathResolve(INITIAL_CWD, rawDir);
489
438
  }
490
439
  function ensureLogDirExists() {
491
- if (didEnsureLogDir)
492
- return;
493
- didEnsureLogDir = true;
494
440
  const dir = resolveLogDir();
495
441
  try {
496
442
  if (!existsSync(dir)) {
@@ -501,6 +447,7 @@ function ensureLogDirExists() {
501
447
  // 不能在 Logger 初始化前调用 Logger 本身,直接抛错即可
502
448
  throw new Error(`创建 logs 目录失败: ${dir}. ${error?.message || error}`);
503
449
  }
450
+ didEnsureLogDir = true;
504
451
  }
505
452
  async function pruneOldLogFiles() {
506
453
  if (didPruneOldLogFiles)
@@ -627,7 +574,6 @@ export function getLogger() {
627
574
  if (instance)
628
575
  return instance;
629
576
  ensureLogDirExists();
630
- installGracefulExitHooks();
631
577
  // 启动时清理过期日志(异步,不阻塞初始化)
632
578
  void pruneOldLogFiles();
633
579
  const minLevel = normalizeLogLevelName();
@@ -647,7 +593,6 @@ function getErrorLogger() {
647
593
  if (errorInstance)
648
594
  return errorInstance;
649
595
  ensureLogDirExists();
650
- installGracefulExitHooks();
651
596
  void pruneOldLogFiles();
652
597
  const maxFileBytes = (typeof config.maxSize === "number" && config.maxSize > 0 ? config.maxSize : 10) * 1024 * 1024;
653
598
  if (!errorFileSink) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "befly",
3
- "version": "3.12.1",
4
- "gitHead": "2ff9d8fc0422aa7332afdd7c19d16493004cdfcf",
3
+ "version": "3.12.3",
4
+ "gitHead": "f940226faa94e51a2593cc826b255acd8cf882c6",
5
5
  "private": false,
6
6
  "description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
7
7
  "keywords": [