mm_sqlite 1.3.7 → 1.3.8

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/db.js CHANGED
@@ -23,7 +23,7 @@ class DB extends Sql {
23
23
  * 获取上级
24
24
  * @returns {object} 返回上级管理器
25
25
  */
26
- this.parent = function () {
26
+ this.getParent = function () {
27
27
  return sqlite;
28
28
  };
29
29
  }
@@ -48,7 +48,7 @@ DB.prototype._createTimeoutPromise = function (timeout, message) {
48
48
  * @returns {string} 数据库
49
49
  */
50
50
  DB.prototype.database = function () {
51
- return this.parent().config.database;
51
+ return this.getParent().config.database;
52
52
  };
53
53
 
54
54
  /**
@@ -58,7 +58,7 @@ DB.prototype.database = function () {
58
58
  * @returns {object} 返回管理器
59
59
  */
60
60
  DB.prototype.new = function (table, key) {
61
- var db = this.parent().db();
61
+ var db = this.getParent().db();
62
62
  db.table = table;
63
63
  if (key) {
64
64
  db.key = key;
@@ -77,7 +77,7 @@ DB.prototype.new = function (table, key) {
77
77
  DB.prototype.getConn = async function (timeout = 15000) {
78
78
  try {
79
79
  // 直接使用SQLite实例的getConn方法,避免Promise.race导致的死锁
80
- return await this.parent().getConn(timeout);
80
+ return await this.getParent().getConn(timeout);
81
81
  } catch (error) {
82
82
  this.log('error', '获取连接失败', error);
83
83
  // 重新抛出异常,因为调用方需要连接对象
package/index.js CHANGED
@@ -21,23 +21,23 @@ class SQLite extends Base {
21
21
  database: 'mm',
22
22
  charset: 'utf8mb4',
23
23
  timezone: '+08:00',
24
- connect_timeout: 20000,
25
- acquire_timeout: 20000,
26
- query_timeout: 20000,
27
- connection_limit: 500,
24
+ connect_timeout: 5000, // 减少连接超时时间
25
+ acquire_timeout: 5000, // 减少获取连接超时时间
26
+ query_timeout: 10000, // 减少查询超时时间
27
+ connection_limit: 10, // 减少最大连接数
28
28
  queue_limit: 0,
29
- enable_keep_alive: true,
30
- keep_alive_initial_delay: 10000,
31
- enable_reconnect: true,
32
- reconnect_interval: 1000,
33
- max_reconnect_attempts: 5,
34
- wait_for_connections: true,
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
35
  // 连接池相关配置
36
36
  pool_min: 1,
37
- pool_max: 5,
38
- pool_acquire_timeout: 30000,
39
- pool_idle_timeout: 60000,
40
- pool_reap_interval: 1000
37
+ pool_max: 3, // 减少最大连接池大小
38
+ pool_acquire_timeout: 5000, // 减少连接池获取超时
39
+ pool_idle_timeout: 30000, // 减少空闲超时
40
+ pool_reap_interval: 5000 // 减少回收间隔
41
41
  };
42
42
 
43
43
  /**
@@ -46,26 +46,33 @@ class SQLite extends Base {
46
46
  */
47
47
  constructor(config) {
48
48
  super(config);
49
- this._connection = null;
50
- this._pool = null;
51
- this._status = 'closed';
52
- this._last_connect_time = 0;
53
- this._reconnecting = false;
54
- this._is_inited = false;
55
- this._is_destroyed = false;
56
- this._db = null;
57
- this._open = false;
58
- this._conn_retry_count = 0;
59
-
60
- // 连接池相关属性
61
- this._use_pool = this.config.connection_limit > 1;
62
49
  this._pool_connections = [];
63
50
  this._pool_available = [];
64
51
  this._pool_waiting = [];
65
- this._pool_reaper = null;
66
52
  }
67
53
  }
68
54
 
55
+ /**
56
+ * 预初始化数据库连接
57
+ * @private
58
+ */
59
+ SQLite.prototype._preset = function () {
60
+ this._connection = null;
61
+ this._pool = null;
62
+ this._status = 'closed';
63
+ this._last_connect_time = 0;
64
+ this._reconnecting = false;
65
+ this._is_inited = false;
66
+ this._is_destroyed = false;
67
+ this._db = null;
68
+ this._open = false;
69
+ this._conn_retry_count = 0;
70
+
71
+ // 连接池相关属性
72
+ this._use_pool = this.config.connection_limit > 1;
73
+ this._pool_reaper = null;
74
+ };
75
+
69
76
  /**
70
77
  * 初始化服务
71
78
  * @returns {Promise<void>}
@@ -150,16 +157,29 @@ SQLite.prototype.open = async function (timeout) {
150
157
  });
151
158
  return true;
152
159
  } else {
153
- // 使用单连接模式
154
- const conn_promise = this._openInternal();
155
- const timeout_promise = new Promise((unused_resolve, reject) => {
156
- setTimeout(() => {
157
- reject(new Error(`数据库连接超时(${connect_timeout}ms)`));
158
- }, connect_timeout);
159
- });
160
-
160
+ // 使用单连接模式 - 替换Promise.race为更可靠的超时控制
161
+ let timeout_id = null;
162
+ let connection_success = false;
163
+
161
164
  try {
162
- await Promise.race([conn_promise, timeout_promise]);
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
+ }
163
183
 
164
184
  this._last_connect_time = Date.now();
165
185
  this._status = 'connected';
@@ -169,7 +189,13 @@ SQLite.prototype.open = async function (timeout) {
169
189
  });
170
190
  return true;
171
191
  } catch (connection_err) {
192
+ // 确保超时定时器被清除
193
+ if (timeout_id) {
194
+ clearTimeout(timeout_id);
195
+ timeout_id = null;
196
+ }
172
197
  this.log('error', '连接过程错误详情', connection_err);
198
+ throw connection_err;
173
199
  }
174
200
  }
175
201
  } catch (err) {
@@ -248,25 +274,30 @@ SQLite.prototype.getConn = async function (timeout) {
248
274
  // 从连接池获取连接
249
275
  return await this._getPoolConnection();
250
276
  } else {
251
- // 单连接模式
252
- const conn_promise = new Promise((resolve) => {
253
- resolve(this._db);
254
- });
255
- const timeout_promise = new Promise((unused_resolve, reject) => {
256
- setTimeout(() => {
257
- reject(new Error(`获取数据库连接超时(${acquire_timeout}ms)`));
258
- }, acquire_timeout);
259
- });
260
-
261
- const conn = await Promise.race([conn_promise, timeout_promise]);
262
- return conn;
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
+ }
263
298
  }
264
299
  } catch (error) {
265
300
  this.log('error', '获取连接失败', error);
266
-
267
- if (error.code && (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT')) {
268
- this._handleConnectionError(error);
269
- }
270
301
  return null;
271
302
  }
272
303
  };
@@ -300,9 +331,23 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
300
331
  conn = await this.getConn(query_timeout);
301
332
 
302
333
  const self = this;
303
- // 直接在方法内部实现超时控制
304
- const query_promise = new Promise((resolve, reject) => {
334
+ // 替换Promise.race为更可靠的超时控制
335
+ let timeout_id = null;
336
+
337
+ const result = await new Promise((resolve, reject) => {
338
+ // 设置超时定时器
339
+ timeout_id = setTimeout(() => {
340
+ reject(new Error(`SQL查询超时: ${timeout}ms`));
341
+ }, timeout);
342
+
343
+ // 执行SQL查询
305
344
  conn.all(sql, params || [], (error, rows) => {
345
+ // 清除超时定时器
346
+ if (timeout_id) {
347
+ clearTimeout(timeout_id);
348
+ timeout_id = null;
349
+ }
350
+
306
351
  if (error) {
307
352
  self.sql = sql;
308
353
  self.error = {
@@ -318,14 +363,6 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
318
363
  });
319
364
  });
320
365
 
321
- const timeout_promise = new Promise((unused_resolve, reject) => {
322
- setTimeout(() => {
323
- reject(new Error(`SQL查询超时: ${timeout}ms`));
324
- }, timeout);
325
- });
326
-
327
- const result = await Promise.race([query_promise, timeout_promise]);
328
-
329
366
  // 连接池模式下释放连接
330
367
  if (this._use_pool && conn) {
331
368
  this._releasePoolConnection(conn);
@@ -340,11 +377,8 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
340
377
  this._releasePoolConnection(conn);
341
378
  }
342
379
 
343
- // 处理连接错误,触发重连
344
- if (err.code && (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT')) {
345
- this._handleConnectionError(err);
346
- }
347
- // 返回空数组,保持与MySQL一致的错误处理行为
380
+ // 简化错误处理:SQLite不需要复杂的连接错误处理
381
+ // 直接返回空数组,保持与MySQL一致的错误处理行为
348
382
  return [];
349
383
  }
350
384
  };
@@ -377,9 +411,23 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
377
411
  // 获取连接
378
412
  conn = await this.getConn(timeout);
379
413
  var _this = this;
380
- // 直接在方法内部实现超时控制
381
- const query_promise = new Promise((resolve, reject) => {
414
+ // 替换Promise.race为更可靠的超时控制
415
+ let timeout_id = null;
416
+
417
+ const result = await new Promise((resolve, reject) => {
418
+ // 设置超时定时器
419
+ timeout_id = setTimeout(() => {
420
+ reject(new Error(`SQL执行超时: ${timeout}ms`));
421
+ }, timeout);
422
+
423
+ // 执行SQL语句
382
424
  conn.run(sql, params || [], function (error) {
425
+ // 清除超时定时器
426
+ if (timeout_id) {
427
+ clearTimeout(timeout_id);
428
+ timeout_id = null;
429
+ }
430
+
383
431
  if (error) {
384
432
  _this.sql = sql;
385
433
  _this.error = {
@@ -395,14 +443,6 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
395
443
  });
396
444
  });
397
445
 
398
- const timeout_promise = new Promise((unused_resolve, reject) => {
399
- setTimeout(() => {
400
- reject(new Error(`SQL执行超时: ${timeout}ms`));
401
- }, timeout);
402
- });
403
-
404
- const result = await Promise.race([query_promise, timeout_promise]);
405
-
406
446
  // 连接池模式下释放连接
407
447
  if (this._use_pool && conn) {
408
448
  this._releasePoolConnection(conn);
@@ -417,10 +457,7 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
417
457
  this._releasePoolConnection(conn);
418
458
  }
419
459
 
420
- // 处理连接错误,触发重连
421
- if (err.code && (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT')) {
422
- this._handleConnectionError(err);
423
- }
460
+ // 简化错误处理:SQLite不需要复杂的连接错误处理
424
461
  // 返回0,保持与MySQL一致的错误处理行为
425
462
  return 0;
426
463
  }
@@ -787,13 +824,23 @@ SQLite.prototype._reapIdleConnections = function () {
787
824
  * @returns {Promise<object>} 数据库连接
788
825
  */
789
826
  SQLite.prototype._getPoolConnection = async function () {
790
- const acquire_timeout = this.config.pool_acquire_timeout;
827
+ const acquire_timeout = this.config.pool_acquire_timeout || 10000;
791
828
  const start_time = Date.now();
792
829
 
793
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
+
794
840
  const tryGetConnection = () => {
795
841
  // 检查超时
796
842
  if (Date.now() - start_time > acquire_timeout) {
843
+ cleanup();
797
844
  reject(new Error(`获取连接超时(${acquire_timeout}ms)`));
798
845
  return;
799
846
  }
@@ -802,6 +849,7 @@ SQLite.prototype._getPoolConnection = async function () {
802
849
  if (this._pool_available.length > 0) {
803
850
  const conn = this._pool_available.shift();
804
851
  conn._last_used = Date.now();
852
+ cleanup();
805
853
  resolve(conn);
806
854
  return;
807
855
  }
@@ -812,14 +860,18 @@ SQLite.prototype._getPoolConnection = async function () {
812
860
  .then(conn => {
813
861
  this._pool_connections.push(conn);
814
862
  conn._last_used = Date.now();
863
+ cleanup();
815
864
  resolve(conn);
816
865
  })
817
- .catch(reject);
866
+ .catch(err => {
867
+ cleanup();
868
+ reject(err);
869
+ });
818
870
  return;
819
871
  }
820
872
 
821
- // 没有可用连接,等待一段时间后重试
822
- setTimeout(tryGetConnection, 100);
873
+ // 没有可用连接,等待一段时间后重试(避免无限循环)
874
+ timeout_id = setTimeout(tryGetConnection, 50);
823
875
  };
824
876
 
825
877
  tryGetConnection();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_sqlite",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口,支持异步操作、事务处理和批量操作",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -38,7 +38,7 @@
38
38
  "node": ">=14.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "mm_expand": "^2.1.9",
41
+ "mm_expand": "^2.2.8",
42
42
  "sqlite3": "^6.0.1",
43
43
  "sqlstring": "^2.3.3"
44
44
  },
package/sql.js CHANGED
@@ -897,7 +897,6 @@ Sql.prototype.del = async function (query, like) {
897
897
  var sql = this.toDelSql(query, like);
898
898
  this.sql = sql;
899
899
  var bl = await this.exec(sql);
900
-
901
900
  return bl;
902
901
  } catch (err) {
903
902
  this.error = err.message;
Binary file
Binary file