mm_sqlite 1.3.9 → 1.4.2

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/index.js CHANGED
@@ -3,6 +3,8 @@ const {
3
3
  DB
4
4
  } = require('./db');
5
5
  const { Base } = require('mm_expand');
6
+ const SQLitePool = require('./pool');
7
+
6
8
 
7
9
  /**
8
10
  * SQLite数据库操作类
@@ -21,23 +23,15 @@ class SQLite extends Base {
21
23
  database: 'mm',
22
24
  charset: 'utf8mb4',
23
25
  timezone: '+08:00',
24
- connect_timeout: 5000, // 减少连接超时时间
25
- acquire_timeout: 5000, // 减少获取连接超时时间
26
- query_timeout: 10000, // 减少查询超时时间
27
- connection_limit: 10, // 减少最大连接数
28
- queue_limit: 0,
29
- enable_keep_alive: false, // SQLite不需要保持连接
30
- keep_alive_initial_delay: 0,
31
- enable_reconnect: false, // SQLite不需要重连
32
- reconnect_interval: 0,
33
- max_reconnect_attempts: 0,
34
- wait_for_connections: false,
35
- // 连接池相关配置
36
- pool_min: 1,
37
- pool_max: 3, // 减少最大连接池大小
38
- pool_acquire_timeout: 5000, // 减少连接池获取超时
39
- pool_idle_timeout: 30000, // 减少空闲超时
40
- pool_reap_interval: 5000 // 减少回收间隔
26
+ connect_timeout: 5000, // 连接超时时间
27
+ acquire_timeout: 5000, // 获取连接超时时间
28
+ query_timeout: 10000, // 查询超时时间
29
+ // 连接池配置(统一使用连接池模式)
30
+ pool_min: 1, // 最小连接数
31
+ pool_max: 3, // 最大连接数
32
+ pool_acquire_timeout: 5000, // 连接池获取超时
33
+ pool_idle_timeout: 30000, // 空闲超时
34
+ pool_reap_interval: 5000 // 回收间隔
41
35
  };
42
36
 
43
37
  /**
@@ -46,9 +40,6 @@ class SQLite extends Base {
46
40
  */
47
41
  constructor(config) {
48
42
  super(config);
49
- this._pool_connections = [];
50
- this._pool_available = [];
51
- this._pool_waiting = [];
52
43
  }
53
44
  }
54
45
 
@@ -58,7 +49,6 @@ class SQLite extends Base {
58
49
  */
59
50
  SQLite.prototype._preset = function () {
60
51
  this._connection = null;
61
- this._pool = null;
62
52
  this._status = 'closed';
63
53
  this._last_connect_time = 0;
64
54
  this._reconnecting = false;
@@ -67,29 +57,8 @@ SQLite.prototype._preset = function () {
67
57
  this._db = null;
68
58
  this._open = false;
69
59
  this._conn_retry_count = 0;
70
-
71
- // 连接池相关属性
72
- this._use_pool = this.config.connection_limit > 1;
73
- this._pool_reaper = null;
74
- };
75
-
76
- /**
77
- * 初始化服务
78
- * @returns {Promise<void>}
79
- */
80
- SQLite.prototype._initService = async function () {
81
- if (this._is_inited) {
82
- this.log('warn', 'SQLite服务已初始化');
83
- return;
84
- }
85
-
86
- try {
87
- this.log('debug', '初始化SQLite服务', { config: this.config });
88
- this._is_inited = true;
89
- this.log('debug', 'SQLite服务初始化完成');
90
- } catch (error) {
91
- this.log('error', 'SQLite服务初始化失败', error);
92
- }
60
+ // 初始化连接池实例
61
+ this._pool = new SQLitePool(this.config, this._getDbFilename.bind(this), this.log.bind(this));
93
62
  };
94
63
 
95
64
  /**
@@ -106,24 +75,7 @@ SQLite.prototype._getDbFilename = function () {
106
75
  };
107
76
 
108
77
  /**
109
- * 内部打开数据库连接
110
- * @private
111
- * @returns {Promise<void>}
112
- */
113
- SQLite.prototype._openInternal = async function () {
114
- return new Promise((resolve, reject) => {
115
- this._db = new sqlite3.Database(this._getDbFilename(), (err) => {
116
- if (err) {
117
- reject(err);
118
- } else {
119
- resolve();
120
- }
121
- });
122
- });
123
- };
124
-
125
- /**
126
- * 打开数据库连接
78
+ * 打开数据库连接(统一使用连接池模式)
127
79
  * @param {number} timeout - 超时时间(毫秒)
128
80
  * @returns {Promise<boolean>}
129
81
  * @throws {TypeError} 当timeout参数无效时
@@ -139,65 +91,16 @@ SQLite.prototype.open = async function (timeout) {
139
91
  return true;
140
92
  }
141
93
 
142
- const connect_timeout = timeout || this.config.connect_timeout || 10000;
143
94
  this._status = 'connecting';
144
95
 
145
96
  try {
146
97
  this.config.dir.addDir();
147
- if (this._use_pool) {
148
- // 使用连接池模式
149
- await this._initPool();
150
- this._last_connect_time = Date.now();
151
- this._status = 'connected';
152
- this.log('info', '数据库连接池初始化成功', {
153
- dir: this.config.dir,
154
- database: this.config.database,
155
- pool_min: this.config.pool_min,
156
- pool_max: this.config.pool_max
157
- });
158
- return true;
159
- } else {
160
- // 使用单连接模式 - 替换Promise.race为更可靠的超时控制
161
- let timeout_id = null;
162
- let connection_success = false;
163
-
164
- try {
165
- // 设置超时控制
166
- const timeout_promise = new Promise((resolve, reject) => {
167
- timeout_id = setTimeout(() => {
168
- if (!connection_success) {
169
- reject(new Error(`数据库连接超时(${connect_timeout}ms)`));
170
- }
171
- }, connect_timeout);
172
- });
173
-
174
- // 执行连接
175
- await this._openInternal();
176
- connection_success = true;
177
-
178
- // 清除超时定时器
179
- if (timeout_id) {
180
- clearTimeout(timeout_id);
181
- timeout_id = null;
182
- }
183
98
 
184
- this._last_connect_time = Date.now();
185
- this._status = 'connected';
186
- this.log('info', '数据库连接成功', {
187
- dir: this.config.dir,
188
- database: this.config.database
189
- });
190
- return true;
191
- } catch (connection_err) {
192
- // 确保超时定时器被清除
193
- if (timeout_id) {
194
- clearTimeout(timeout_id);
195
- timeout_id = null;
196
- }
197
- this.log('error', '连接过程错误详情', connection_err);
198
- throw connection_err;
199
- }
200
- }
99
+ // 统一使用连接池模式
100
+ await this._pool.init();
101
+ this._last_connect_time = Date.now();
102
+ this._status = 'connected';
103
+ return true;
201
104
  } catch (err) {
202
105
  this._status = 'closed';
203
106
  this.log('error', '数据库连接失败', err);
@@ -206,7 +109,7 @@ SQLite.prototype.open = async function (timeout) {
206
109
  };
207
110
 
208
111
  /**
209
- * 关闭数据库连接
112
+ * 关闭数据库连接(统一使用连接池模式)
210
113
  * @returns {Promise<boolean>}
211
114
  */
212
115
  SQLite.prototype.close = function () {
@@ -217,32 +120,12 @@ SQLite.prototype.close = function () {
217
120
 
218
121
  return new Promise((resolve) => {
219
122
  try {
220
- if (this._use_pool) {
221
- // 关闭连接池
222
- this._closePool();
223
- this._db = null;
224
- this._open = false;
225
- this._status = 'closed';
226
- this.log('info', '数据库连接池已关闭');
227
- resolve(true);
228
- } else if (this._db) {
229
- // 单连接模式
230
- this.log('debug', '关闭数据库连接');
231
- this._db.close((err) => {
232
- if (err) {
233
- this.log('error', '关闭数据库失败', err);
234
- } else {
235
- this.log('info', '数据库已关闭');
236
- }
237
- this._db = null;
238
- this._open = false;
239
- this._status = 'closed';
240
- resolve(!err);
241
- });
242
- } else {
243
- this._status = 'closed';
244
- resolve(true);
245
- }
123
+ // 统一关闭连接池
124
+ this._pool.close();
125
+ this._db = null;
126
+ this._open = false;
127
+ this._status = 'closed';
128
+ resolve(true);
246
129
  } catch (err) {
247
130
  this.log('error', '关闭数据库连接时发生异常', err);
248
131
  this._status = 'closed';
@@ -252,7 +135,7 @@ SQLite.prototype.close = function () {
252
135
  };
253
136
 
254
137
  /**
255
- * 获取数据库连接
138
+ * 获取数据库连接(统一使用连接池模式)
256
139
  * @param {number} timeout - 超时时间(毫秒)
257
140
  * @returns {Promise<object>}
258
141
  * @throws {TypeError} 当timeout参数无效时
@@ -269,37 +152,8 @@ SQLite.prototype.getConn = async function (timeout) {
269
152
  await this.open(acquire_timeout);
270
153
  }
271
154
 
272
- try {
273
- if (this._use_pool) {
274
- // 从连接池获取连接
275
- return await this._getPoolConnection();
276
- } else {
277
- // 单连接模式 - 替换Promise.race为更可靠的超时控制
278
- let timeout_id = null;
279
-
280
- try {
281
- return await new Promise((resolve, reject) => {
282
- // 设置超时定时器
283
- timeout_id = setTimeout(() => {
284
- reject(new Error(`获取数据库连接超时(${acquire_timeout}ms)`));
285
- }, acquire_timeout);
286
-
287
- // 直接返回连接,因为这是单连接模式
288
- resolve(this._db);
289
- });
290
- } catch (error) {
291
- // 确保超时定时器被清除
292
- if (timeout_id) {
293
- clearTimeout(timeout_id);
294
- timeout_id = null;
295
- }
296
- throw error;
297
- }
298
- }
299
- } catch (error) {
300
- this.log('error', '获取连接失败', error);
301
- return null;
302
- }
155
+ // 统一从连接池获取连接
156
+ return await this._pool.getConnection(acquire_timeout);
303
157
  };
304
158
 
305
159
  /**
@@ -323,23 +177,21 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
323
177
  }
324
178
 
325
179
  this.error = null;
180
+ this.sql = '';
326
181
  let conn = null;
327
182
  const query_timeout = timeout || this.config.query_timeout || 30000;
328
-
183
+ let ret = [];
329
184
  try {
330
185
  // 获取连接
331
186
  conn = await this.getConn(query_timeout);
332
-
333
- const self = this;
334
- // 替换Promise.race为更可靠的超时控制
335
187
  let timeout_id = null;
336
-
337
- const result = await new Promise((resolve, reject) => {
188
+
189
+ ret = await new Promise((resolve, reject) => {
338
190
  // 设置超时定时器
339
191
  timeout_id = setTimeout(() => {
340
192
  reject(new Error(`SQL查询超时: ${timeout}ms`));
341
193
  }, timeout);
342
-
194
+
343
195
  // 执行SQL查询
344
196
  conn.all(sql, params || [], (error, rows) => {
345
197
  // 清除超时定时器
@@ -347,14 +199,8 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
347
199
  clearTimeout(timeout_id);
348
200
  timeout_id = null;
349
201
  }
350
-
351
202
  if (error) {
352
- self.sql = sql;
353
- self.error = {
354
- code: error.errno,
355
- message: error.message
356
- };
357
- // 不抛出错误,保持与MySQL一致的错误处理行为
203
+ reject(error);
358
204
  resolve([]);
359
205
  } else {
360
206
  // 保持与MySQL兼容的返回值格式,始终返回数组
@@ -362,25 +208,19 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
362
208
  }
363
209
  });
364
210
  });
365
-
366
- // 连接池模式下释放连接
367
- if (this._use_pool && conn) {
368
- this._releasePoolConnection(conn);
369
- }
370
-
371
- return result;
372
- } catch (err) {
373
- this.log('error', 'SQL执行失败', err);
374
-
375
- // 连接池模式下释放连接
376
- if (this._use_pool && conn) {
377
- this._releasePoolConnection(conn);
378
- }
379
-
380
- // 简化错误处理:SQLite不需要复杂的连接错误处理
381
- // 直接返回空数组,保持与MySQL一致的错误处理行为
382
- return [];
211
+ } catch (error) {
212
+ this.log('error', 'SQL执行失败', error);
213
+ this.sql = sql;
214
+ this.error = {
215
+ code: error.errno,
216
+ message: error.message
217
+ };
218
+ ret = [];
219
+ }
220
+ finally {
221
+ await releaseConn(conn);
383
222
  }
223
+ return ret;
384
224
  };
385
225
 
386
226
  /**
@@ -404,22 +244,22 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
404
244
  }
405
245
 
406
246
  this.error = null;
247
+ this.sql = '';
407
248
  let conn = null;
408
249
  timeout = timeout || this.config.query_timeout || 30000;
409
-
250
+ let ret = 0;
410
251
  try {
411
252
  // 获取连接
412
253
  conn = await this.getConn(timeout);
413
- var _this = this;
254
+ this.sql = sql;
414
255
  // 替换Promise.race为更可靠的超时控制
415
256
  let timeout_id = null;
416
-
417
- const result = await new Promise((resolve, reject) => {
257
+ ret = await new Promise((resolve, reject) => {
418
258
  // 设置超时定时器
419
259
  timeout_id = setTimeout(() => {
420
260
  reject(new Error(`SQL执行超时: ${timeout}ms`));
421
261
  }, timeout);
422
-
262
+
423
263
  // 执行SQL语句
424
264
  conn.run(sql, params || [], function (error) {
425
265
  // 清除超时定时器
@@ -427,40 +267,28 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
427
267
  clearTimeout(timeout_id);
428
268
  timeout_id = null;
429
269
  }
430
-
431
270
  if (error) {
432
- _this.sql = sql;
433
- _this.error = {
434
- code: error.errno,
435
- message: error.message
436
- };
437
- // 不抛出错误,保持与MySQL一致的错误处理行为
438
- resolve(0);
271
+ reject(error);
439
272
  } else {
440
- // 保持与MySQL兼容的返回值格式
441
273
  resolve(this.lastID || this.changes || 1);
442
274
  }
443
275
  });
444
276
  });
445
-
446
- // 连接池模式下释放连接
447
- if (this._use_pool && conn) {
448
- this._releasePoolConnection(conn);
449
- }
450
-
451
- return result;
452
- } catch (err) {
453
- this.log('error', 'SQL执行失败', err);
454
-
455
- // 连接池模式下释放连接
456
- if (this._use_pool && conn) {
457
- this._releasePoolConnection(conn);
458
- }
459
-
277
+ } catch (error) {
278
+ this.log('error', 'SQL执行失败', error);
279
+ this.sql = sql;
280
+ this.error = {
281
+ code: error.errno,
282
+ message: error.message
283
+ };
460
284
  // 简化错误处理:SQLite不需要复杂的连接错误处理
461
285
  // 返回0,保持与MySQL一致的错误处理行为
462
- return 0;
286
+ ret = 0;
463
287
  }
288
+ finally {
289
+ await releaseConn(conn);
290
+ }
291
+ return ret;
464
292
  };
465
293
 
466
294
  /**
@@ -483,59 +311,53 @@ SQLite.prototype.read = async function (table, condition, options) {
483
311
  throw new TypeError('options must be object');
484
312
  }
485
313
 
486
- try {
487
- // 检查连接状态
488
- if (this._status !== 'connected') {
489
- throw new Error('数据库连接未建立');
490
- }
491
-
492
- // 构建基础SQL查询
493
- let sql = `SELECT * FROM ${table}`;
494
- const params = [];
314
+ // 检查连接状态
315
+ if (this._status !== 'connected') {
316
+ throw new Error('数据库连接未建立');
317
+ }
495
318
 
496
- // 处理条件
497
- if (condition && Object.keys(condition).length > 0) {
498
- const where_clauses = [];
499
- for (const [field, value] of Object.entries(condition)) {
500
- where_clauses.push(`${field} = ?`);
501
- params.push(value);
502
- }
503
- sql += ` WHERE ${where_clauses.join(' AND ')}`;
504
- }
319
+ // 构建基础SQL查询
320
+ let sql = `SELECT * FROM ${table}`;
321
+ const params = [];
505
322
 
506
- // 处理排序
507
- if (options && options.order_by) {
508
- sql += ` ORDER BY ${options.order_by}`;
323
+ // 处理条件
324
+ if (condition && Object.keys(condition).length > 0) {
325
+ const where_clauses = [];
326
+ for (const [field, value] of Object.entries(condition)) {
327
+ where_clauses.push(`${field} = ?`);
328
+ params.push(value);
509
329
  }
330
+ sql += ` WHERE ${where_clauses.join(' AND ')}`;
331
+ }
510
332
 
511
- // 处理分页
512
- if (options && options.limit) {
513
- sql += ` LIMIT ${options.limit}`;
514
- }
333
+ // 处理排序
334
+ if (options && options.order_by) {
335
+ sql += ` ORDER BY ${options.order_by}`;
336
+ }
515
337
 
516
- if (options && options.offset) {
517
- sql += ` OFFSET ${options.offset}`;
518
- }
338
+ // 处理分页
339
+ if (options && options.limit) {
340
+ sql += ` LIMIT ${options.limit}`;
341
+ }
519
342
 
520
- // 记录查询日志
521
- if (this.config.debug) {
522
- this.log('debug', '查询数据', { sql, params });
523
- }
343
+ if (options && options.offset) {
344
+ sql += ` OFFSET ${options.offset}`;
345
+ }
524
346
 
525
- // 执行查询
526
- const results = await this.run(sql, params);
347
+ // 记录查询日志
348
+ if (this.config.debug) {
349
+ this.log('debug', '查询数据', { sql, params });
350
+ }
527
351
 
528
- if (this.config.debug) {
529
- this.log('info', '查询成功', { count: Array.isArray(results) ? results.length : 1 });
530
- }
352
+ // 执行查询
353
+ const results = await this.run(sql, params);
531
354
 
532
- // 确保返回数组格式
533
- return Array.isArray(results) ? results : [results];
534
- } catch (error) {
535
- this.log('error', '查询失败', error);
536
- // 返回空数组作为默认值,保持返回值类型一致
537
- return [];
355
+ if (this.config.debug) {
356
+ this.log('debug', '查询成功', { count: Array.isArray(results) ? results.length : 1 });
538
357
  }
358
+
359
+ // 确保返回数组格式
360
+ return Array.isArray(results) ? results : [results];
539
361
  };
540
362
 
541
363
  /**
@@ -582,7 +404,7 @@ SQLite.prototype.db = function () {
582
404
  * 开始事务
583
405
  * @returns {Promise<object>} 事务连接对象
584
406
  */
585
- SQLite.prototype.beginTrans = async function () {
407
+ SQLite.prototype.beginTransaction = async function () {
586
408
  try {
587
409
  // 检查连接状态
588
410
  if (this._status !== 'connected') {
@@ -592,10 +414,15 @@ SQLite.prototype.beginTrans = async function () {
592
414
  // 获取连接
593
415
  const conn = await this.getConn();
594
416
 
417
+ // 标记连接为事务中
418
+ conn._in_transaction = true;
419
+
595
420
  // 开始事务
596
421
  await new Promise((resolve, reject) => {
597
422
  conn.run('BEGIN TRANSACTION', (error) => {
598
423
  if (error) {
424
+ // 事务开始失败,清除事务标记
425
+ conn._in_transaction = false;
599
426
  reject(error);
600
427
  } else {
601
428
  resolve();
@@ -624,10 +451,9 @@ SQLite.prototype.beginTrans = async function () {
624
451
  this.log('debug', '事务提交');
625
452
  }
626
453
 
627
- // 连接池模式下释放连接
628
- if (this._use_pool) {
629
- this._releasePoolConnection(conn);
630
- }
454
+ // 清除事务标记并释放连接
455
+ conn._in_transaction = false;
456
+ await releaseConn(conn);
631
457
  },
632
458
  rollback: async () => {
633
459
  await new Promise((resolve, reject) => {
@@ -642,11 +468,9 @@ SQLite.prototype.beginTrans = async function () {
642
468
  if (this.config.debug) {
643
469
  this.log('debug', '事务回滚');
644
470
  }
645
-
646
- // 连接池模式下释放连接
647
- if (this._use_pool) {
648
- this._releasePoolConnection(conn);
649
- }
471
+ // 清除事务标记并释放连接
472
+ conn._in_transaction = false;
473
+ await releaseConn(conn);
650
474
  },
651
475
  exec: async (sql, params) => {
652
476
  // 在事务中执行SQL
@@ -680,7 +504,7 @@ SQLite.prototype.beginTrans = async function () {
680
504
  * @returns {Promise<*>} 回调函数的返回值
681
505
  * @throws {TypeError} 当callback参数无效时
682
506
  */
683
- SQLite.prototype.trans = async function (callback) {
507
+ SQLite.prototype.transaction = async function (callback) {
684
508
  // 参数校验
685
509
  if (typeof callback !== 'function') {
686
510
  throw new TypeError('callback must be function');
@@ -690,7 +514,7 @@ SQLite.prototype.trans = async function (callback) {
690
514
 
691
515
  try {
692
516
  // 开始事务
693
- trans = await this.beginTrans();
517
+ trans = await this.beginTransaction();
694
518
 
695
519
  // 执行回调函数,传入事务对象
696
520
  const result = await callback(trans);
@@ -737,223 +561,6 @@ SQLite.prototype.table = function (name, key) {
737
561
  return db;
738
562
  };
739
563
 
740
- /**
741
- * 创建SQLite连接
742
- * @private
743
- * @returns {Promise<object>} 数据库连接对象
744
- */
745
- SQLite.prototype._createConnection = function () {
746
- return new Promise((resolve, reject) => {
747
- const db = new sqlite3.Database(this._getDbFilename(), (err) => {
748
- if (err) {
749
- reject(err);
750
- } else {
751
- resolve(db);
752
- }
753
- });
754
- });
755
- };
756
-
757
- /**
758
- * 初始化连接池
759
- * @private
760
- * @returns {Promise<void>}
761
- */
762
- SQLite.prototype._initPool = async function () {
763
- if (this._pool_reaper) {
764
- return; // 连接池已初始化
765
- }
766
-
767
- try {
768
- // 创建最小连接数
769
- for (let i = 0; i < this.config.pool_min; i++) {
770
- const conn = await this._createConnection();
771
- this._pool_connections.push(conn);
772
- this._pool_available.push(conn);
773
- }
774
-
775
- // 启动连接回收器
776
- this._pool_reaper = setInterval(() => {
777
- this._reapIdleConnections();
778
- }, this.config.pool_reap_interval);
779
-
780
- this.log('debug', '连接池初始化完成', {
781
- min: this.config.pool_min,
782
- max: this.config.pool_max,
783
- current: this._pool_connections.length
784
- });
785
- } catch (error) {
786
- this.log('error', '连接池初始化失败', error);
787
- throw error;
788
- }
789
- };
790
-
791
- /**
792
- * 回收空闲连接
793
- * @private
794
- */
795
- SQLite.prototype._reapIdleConnections = function () {
796
- const now = Date.now();
797
- const idle_timeout = this.config.pool_idle_timeout;
798
-
799
- for (let i = this._pool_available.length - 1; i >= 0; i--) {
800
- const conn = this._pool_available[i];
801
- if (conn._last_used && now - conn._last_used > idle_timeout) {
802
- // 关闭并移除空闲连接
803
- conn.close((err) => {
804
- if (err) {
805
- this.log('error', '关闭空闲连接失败', err);
806
- }
807
- });
808
-
809
- // 从连接池中移除
810
- const conn_idx = this._pool_connections.indexOf(conn);
811
- if (conn_idx > -1) {
812
- this._pool_connections.splice(conn_idx, 1);
813
- }
814
- this._pool_available.splice(i, 1);
815
-
816
- this.log('debug', '回收空闲连接');
817
- }
818
- }
819
- };
820
-
821
- /**
822
- * 从连接池获取连接
823
- * @private
824
- * @returns {Promise<object>} 数据库连接
825
- */
826
- SQLite.prototype._getPoolConnection = async function () {
827
- const acquire_timeout = this.config.pool_acquire_timeout || 10000;
828
- const start_time = Date.now();
829
-
830
- return new Promise((resolve, reject) => {
831
- let timeout_id = null;
832
-
833
- const cleanup = () => {
834
- if (timeout_id) {
835
- clearTimeout(timeout_id);
836
- timeout_id = null;
837
- }
838
- };
839
-
840
- const tryGetConnection = () => {
841
- // 检查超时
842
- if (Date.now() - start_time > acquire_timeout) {
843
- cleanup();
844
- reject(new Error(`获取连接超时(${acquire_timeout}ms)`));
845
- return;
846
- }
847
-
848
- // 检查是否有可用连接
849
- if (this._pool_available.length > 0) {
850
- const conn = this._pool_available.shift();
851
- conn._last_used = Date.now();
852
- cleanup();
853
- resolve(conn);
854
- return;
855
- }
856
-
857
- // 检查是否可以创建新连接
858
- if (this._pool_connections.length < this.config.pool_max) {
859
- this._createConnection()
860
- .then(conn => {
861
- this._pool_connections.push(conn);
862
- conn._last_used = Date.now();
863
- cleanup();
864
- resolve(conn);
865
- })
866
- .catch(err => {
867
- cleanup();
868
- reject(err);
869
- });
870
- return;
871
- }
872
-
873
- // 没有可用连接,等待一段时间后重试(避免无限循环)
874
- timeout_id = setTimeout(tryGetConnection, 50);
875
- };
876
-
877
- tryGetConnection();
878
- });
879
- };
880
-
881
- /**
882
- * 释放连接回连接池
883
- * @private
884
- * @param {object} conn - 数据库连接
885
- */
886
- SQLite.prototype._releaseConn = function (conn) {
887
- if (this._pool_connections.includes(conn)) {
888
- conn._last_used = Date.now();
889
- this._pool_available.push(conn);
890
-
891
- // 处理等待队列
892
- if (this._pool_waiting.length > 0) {
893
- const waiting = this._pool_waiting.shift();
894
- waiting.resolve(conn);
895
- }
896
- }
897
- };
898
-
899
- /**
900
- * 释放连接池连接
901
- * @private
902
- * @param {object} conn - 数据库连接
903
- */
904
- SQLite.prototype._releasePoolConnection = function (conn) {
905
- if (!conn || !this._pool_connections.includes(conn)) {
906
- return;
907
- }
908
-
909
- // 标记连接最后使用时间
910
- conn._last_used = Date.now();
911
-
912
- // 将连接放回可用连接池
913
- if (!this._pool_available.includes(conn)) {
914
- this._pool_available.push(conn);
915
- }
916
-
917
- // 如果有等待的连接请求,立即处理
918
- if (this._pool_waiting.length > 0) {
919
- const waiting = this._pool_waiting.shift();
920
- const next_conn = this._pool_available.shift();
921
- if (next_conn && waiting.resolve) {
922
- waiting.resolve(next_conn);
923
- }
924
- }
925
- };
926
-
927
- /**
928
- * 关闭连接池
929
- * @private
930
- */
931
- SQLite.prototype._closePool = function () {
932
- if (this._pool_reaper) {
933
- clearInterval(this._pool_reaper);
934
- this._pool_reaper = null;
935
- }
936
-
937
- // 关闭所有连接
938
- this._pool_connections.forEach(conn => {
939
- try {
940
- conn.close((err) => {
941
- if (err) {
942
- this.log('error', '关闭连接池连接失败', err);
943
- }
944
- });
945
- } catch (error) {
946
- this.log('error', '关闭连接池连接异常', error);
947
- }
948
- });
949
-
950
- this._pool_connections = [];
951
- this._pool_available = [];
952
- this._pool_waiting = [];
953
-
954
- this.log('debug', '连接池已关闭');
955
- };
956
-
957
564
  /**
958
565
  * 确保连接池对象存在
959
566
  */
@@ -982,6 +589,18 @@ function sqliteAdmin(scope, config) {
982
589
  return obj;
983
590
  }
984
591
 
592
+ /**
593
+ * 安全释放数据库连接
594
+ * @param {object} conn - 数据库连接对象
595
+ * @returns {Promise<void>}
596
+ */
597
+ async function releaseConn(conn) {
598
+ if (!conn) {
599
+ return;
600
+ }
601
+ await conn.release();
602
+ }
603
+
985
604
  // 模块导出
986
605
  exports.SQLite = SQLite;
987
606
  exports.sqliteAdmin = sqliteAdmin;