monsqlize 1.3.0 → 2.0.0

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.
Files changed (172) hide show
  1. package/CHANGELOG.md +56 -60
  2. package/LICENSE +201 -21
  3. package/README.md +537 -1828
  4. package/changelogs/README.md +160 -0
  5. package/changelogs/v2.0.0.md +222 -0
  6. package/dist/cjs/index.cjs +10600 -0
  7. package/dist/cjs/mongodb/common/transaction-aware.cjs +10 -0
  8. package/dist/cjs/transaction/CacheLockManager.cjs +100 -0
  9. package/dist/cjs/transaction/Transaction.cjs +158 -0
  10. package/dist/cjs/transaction/TransactionManager.cjs +298 -0
  11. package/dist/esm/index.mjs +10650 -0
  12. package/dist/types/base.d.ts +81 -0
  13. package/dist/types/collection.d.ts +1031 -0
  14. package/dist/types/expression.d.ts +115 -0
  15. package/dist/types/index.d.ts +23 -0
  16. package/dist/types/lock.d.ts +74 -0
  17. package/dist/types/model.d.ts +526 -0
  18. package/dist/types/mongodb.d.ts +49 -0
  19. package/dist/types/monsqlize.d.ts +491 -0
  20. package/dist/types/pool.d.ts +84 -0
  21. package/dist/types/runtime.d.ts +362 -0
  22. package/dist/types/saga.d.ts +143 -0
  23. package/dist/types/slow-query-log.d.ts +126 -0
  24. package/dist/types/sync.d.ts +103 -0
  25. package/dist/types/transaction.d.ts +132 -0
  26. package/package.json +67 -69
  27. package/index.d.ts +0 -206
  28. package/index.mjs +0 -52
  29. package/lib/cache-invalidation.js +0 -279
  30. package/lib/cache.js +0 -530
  31. package/lib/common/cursor.js +0 -59
  32. package/lib/common/docs-urls.js +0 -73
  33. package/lib/common/index-options.js +0 -223
  34. package/lib/common/log.js +0 -61
  35. package/lib/common/namespace.js +0 -22
  36. package/lib/common/normalize.js +0 -34
  37. package/lib/common/page-result.js +0 -43
  38. package/lib/common/runner.js +0 -57
  39. package/lib/common/server-features.js +0 -232
  40. package/lib/common/shape-builders.js +0 -27
  41. package/lib/common/validation.js +0 -113
  42. package/lib/connect.js +0 -99
  43. package/lib/constants.js +0 -55
  44. package/lib/count-queue.js +0 -188
  45. package/lib/distributed-cache-invalidator.js +0 -260
  46. package/lib/errors.js +0 -168
  47. package/lib/expression/cache/ExpressionCache.js +0 -114
  48. package/lib/expression/compiler/ExpressionCompiler.js +0 -1090
  49. package/lib/expression/compiler/ExpressionCompilerExtensions.js +0 -531
  50. package/lib/expression/detector.js +0 -84
  51. package/lib/expression/factory.js +0 -29
  52. package/lib/expression/index.js +0 -19
  53. package/lib/function-cache.js +0 -533
  54. package/lib/index.js +0 -1251
  55. package/lib/infrastructure/ConnectionPoolManager.js +0 -464
  56. package/lib/infrastructure/HealthChecker.js +0 -281
  57. package/lib/infrastructure/PoolConfig.js +0 -199
  58. package/lib/infrastructure/PoolSelector.js +0 -225
  59. package/lib/infrastructure/PoolStats.js +0 -244
  60. package/lib/infrastructure/ssh-tunnel-ssh2.js +0 -212
  61. package/lib/infrastructure/ssh-tunnel.js +0 -41
  62. package/lib/infrastructure/uri-parser.js +0 -36
  63. package/lib/lock/Lock.js +0 -67
  64. package/lib/lock/errors.js +0 -28
  65. package/lib/lock/index.js +0 -13
  66. package/lib/logger.js +0 -225
  67. package/lib/model/examples/test.js +0 -311
  68. package/lib/model/features/defaults.js +0 -161
  69. package/lib/model/features/populate.js +0 -568
  70. package/lib/model/features/relations.js +0 -120
  71. package/lib/model/features/soft-delete.js +0 -349
  72. package/lib/model/features/version.js +0 -157
  73. package/lib/model/features/virtuals.js +0 -219
  74. package/lib/model/index.js +0 -1265
  75. package/lib/mongodb/common/accessor-helpers.js +0 -59
  76. package/lib/mongodb/common/agg-pipeline.js +0 -36
  77. package/lib/mongodb/common/aggregation-validator.js +0 -127
  78. package/lib/mongodb/common/iid.js +0 -28
  79. package/lib/mongodb/common/lexicographic-expr.js +0 -53
  80. package/lib/mongodb/common/shape.js +0 -32
  81. package/lib/mongodb/common/sort.js +0 -39
  82. package/lib/mongodb/common/transaction-aware.js +0 -25
  83. package/lib/mongodb/connect.js +0 -234
  84. package/lib/mongodb/index.js +0 -639
  85. package/lib/mongodb/management/admin-ops.js +0 -200
  86. package/lib/mongodb/management/bookmark-ops.js +0 -167
  87. package/lib/mongodb/management/cache-ops.js +0 -50
  88. package/lib/mongodb/management/collection-ops.js +0 -387
  89. package/lib/mongodb/management/database-ops.js +0 -202
  90. package/lib/mongodb/management/index-ops.js +0 -475
  91. package/lib/mongodb/management/index.js +0 -17
  92. package/lib/mongodb/management/namespace.js +0 -31
  93. package/lib/mongodb/management/validation-ops.js +0 -268
  94. package/lib/mongodb/queries/aggregate.js +0 -172
  95. package/lib/mongodb/queries/chain.js +0 -631
  96. package/lib/mongodb/queries/count.js +0 -99
  97. package/lib/mongodb/queries/distinct.js +0 -78
  98. package/lib/mongodb/queries/find-and-count.js +0 -193
  99. package/lib/mongodb/queries/find-by-ids.js +0 -236
  100. package/lib/mongodb/queries/find-one-by-id.js +0 -171
  101. package/lib/mongodb/queries/find-one.js +0 -71
  102. package/lib/mongodb/queries/find-page.js +0 -618
  103. package/lib/mongodb/queries/find.js +0 -171
  104. package/lib/mongodb/queries/index.js +0 -51
  105. package/lib/mongodb/queries/watch.js +0 -538
  106. package/lib/mongodb/writes/common/batch-retry.js +0 -65
  107. package/lib/mongodb/writes/delete-batch.js +0 -323
  108. package/lib/mongodb/writes/delete-many.js +0 -181
  109. package/lib/mongodb/writes/delete-one.js +0 -173
  110. package/lib/mongodb/writes/find-one-and-delete.js +0 -203
  111. package/lib/mongodb/writes/find-one-and-replace.js +0 -239
  112. package/lib/mongodb/writes/find-one-and-update.js +0 -240
  113. package/lib/mongodb/writes/increment-one.js +0 -259
  114. package/lib/mongodb/writes/index.js +0 -46
  115. package/lib/mongodb/writes/insert-batch.js +0 -508
  116. package/lib/mongodb/writes/insert-many.js +0 -223
  117. package/lib/mongodb/writes/insert-one.js +0 -169
  118. package/lib/mongodb/writes/replace-one.js +0 -226
  119. package/lib/mongodb/writes/result-handler.js +0 -237
  120. package/lib/mongodb/writes/update-batch.js +0 -416
  121. package/lib/mongodb/writes/update-many.js +0 -275
  122. package/lib/mongodb/writes/update-one.js +0 -273
  123. package/lib/mongodb/writes/upsert-one.js +0 -203
  124. package/lib/multi-level-cache.js +0 -244
  125. package/lib/operators.js +0 -330
  126. package/lib/redis-cache-adapter.js +0 -267
  127. package/lib/saga/SagaContext.js +0 -67
  128. package/lib/saga/SagaDefinition.js +0 -32
  129. package/lib/saga/SagaExecutor.js +0 -201
  130. package/lib/saga/SagaOrchestrator.js +0 -186
  131. package/lib/saga/index.js +0 -11
  132. package/lib/slow-query-log/base-storage.js +0 -70
  133. package/lib/slow-query-log/batch-queue.js +0 -97
  134. package/lib/slow-query-log/config-manager.js +0 -196
  135. package/lib/slow-query-log/index.js +0 -238
  136. package/lib/slow-query-log/mongodb-storage.js +0 -324
  137. package/lib/slow-query-log/query-hash.js +0 -39
  138. package/lib/sync/ChangeStreamSyncManager.js +0 -405
  139. package/lib/sync/ResumeTokenStore.js +0 -192
  140. package/lib/sync/SyncConfig.js +0 -127
  141. package/lib/sync/SyncTarget.js +0 -240
  142. package/lib/sync/index.js +0 -20
  143. package/lib/transaction/CacheLockManager.js +0 -162
  144. package/lib/transaction/DistributedCacheLockManager.js +0 -475
  145. package/lib/transaction/Transaction.js +0 -315
  146. package/lib/transaction/TransactionManager.js +0 -267
  147. package/lib/transaction/index.js +0 -11
  148. package/lib/utils/objectid-converter.js +0 -632
  149. package/types/README.md +0 -122
  150. package/types/base.ts +0 -94
  151. package/types/batch.ts +0 -187
  152. package/types/cache.ts +0 -71
  153. package/types/chain.ts +0 -254
  154. package/types/collection.ts +0 -357
  155. package/types/expression.ts +0 -109
  156. package/types/function-cache.d.ts +0 -135
  157. package/types/lock.ts +0 -95
  158. package/types/model/definition.ts +0 -152
  159. package/types/model/index.ts +0 -10
  160. package/types/model/instance.ts +0 -121
  161. package/types/model/relations.ts +0 -121
  162. package/types/model/virtuals.ts +0 -32
  163. package/types/monsqlize.ts +0 -245
  164. package/types/options.ts +0 -192
  165. package/types/pagination.ts +0 -154
  166. package/types/pool.ts +0 -125
  167. package/types/query.ts +0 -71
  168. package/types/saga.ts +0 -125
  169. package/types/stream.ts +0 -64
  170. package/types/sync.ts +0 -79
  171. package/types/transaction.ts +0 -79
  172. package/types/write.ts +0 -77
@@ -1,201 +0,0 @@
1
- /**
2
- * Saga 执行器
3
- * 负责步骤执行和补偿
4
- */
5
- const SagaContext = require('./SagaContext');
6
-
7
- class SagaExecutor {
8
- /**
9
- * 构造函数
10
- * @param {Object} definition - Saga 定义
11
- * @param {Object} data - 执行数据
12
- * @param {Object} orchestrator - Saga 协调器
13
- */
14
- constructor(definition, data, orchestrator) {
15
- this.definition = definition;
16
- this.orchestrator = orchestrator;
17
- this.context = new SagaContext(this._generateSagaId(), data);
18
- this.completedSteps = [];
19
- }
20
-
21
- /**
22
- * 执行 Saga
23
- * @returns {Promise<Object>} 执行结果
24
- */
25
- async execute() {
26
- const startTime = Date.now();
27
-
28
- this.orchestrator.logger?.info(
29
- `[Saga] 开始执行: ${this.definition.name} (${this.context.sagaId})`
30
- );
31
-
32
- try {
33
- // 顺序执行步骤
34
- for (let i = 0; i < this.definition.steps.length; i++) {
35
- const step = this.definition.steps[i];
36
-
37
- this.orchestrator.logger?.info(
38
- `[Saga] 执行步骤 ${i + 1}/${this.definition.steps.length}: ${step.name}`
39
- );
40
-
41
- const stepStartTime = Date.now();
42
-
43
- // 执行步骤
44
- const result = await step.execute(this.context);
45
-
46
- const stepDuration = Date.now() - stepStartTime;
47
-
48
- // 记录成功的步骤
49
- this.completedSteps.push({
50
- step,
51
- index: i,
52
- result,
53
- duration: stepDuration,
54
- timestamp: Date.now()
55
- });
56
-
57
- // 标记步骤完成
58
- this.context.markStepCompleted(step.name, result);
59
-
60
- this.orchestrator.logger?.info(
61
- `[Saga] 步骤完成: ${step.name} (耗时 ${stepDuration}ms)`
62
- );
63
- }
64
-
65
- const totalDuration = Date.now() - startTime;
66
-
67
- this.orchestrator.logger?.info(
68
- `[Saga] 执行成功: ${this.definition.name} (总耗时 ${totalDuration}ms)`
69
- );
70
-
71
- return {
72
- success: true,
73
- sagaId: this.context.sagaId,
74
- sagaName: this.definition.name,
75
- completedSteps: this.completedSteps.length,
76
- duration: totalDuration
77
- };
78
-
79
- } catch (error) {
80
- const totalDuration = Date.now() - startTime;
81
-
82
- this.orchestrator.logger?.error(
83
- `[Saga] 执行失败: ${this.definition.name}, 错误: ${error.message}`
84
- );
85
-
86
- // 自动补偿
87
- const compensationResult = await this._compensate(error);
88
-
89
- return {
90
- success: false,
91
- sagaId: this.context.sagaId,
92
- sagaName: this.definition.name,
93
- completedSteps: this.completedSteps.length,
94
- failedStep: this.completedSteps.length,
95
- error: error.message,
96
- duration: totalDuration,
97
- compensation: compensationResult
98
- };
99
- }
100
- }
101
-
102
- /**
103
- * 补偿已完成的步骤
104
- * @private
105
- * @param {Error} originalError - 原始错误
106
- * @returns {Promise<Object>} 补偿结果
107
- */
108
- async _compensate(originalError) {
109
- this.orchestrator.logger?.warn(
110
- `[Saga] 开始补偿: ${this.completedSteps.length} 个已完成步骤`
111
- );
112
-
113
- const compensationResults = [];
114
-
115
- // 逆序补偿
116
- for (let i = this.completedSteps.length - 1; i >= 0; i--) {
117
- const completed = this.completedSteps[i];
118
- const step = completed.step;
119
-
120
- if (!step.compensate) {
121
- this.orchestrator.logger?.warn(
122
- `[Saga] 步骤 ${step.name} 没有定义补偿操作,跳过`
123
- );
124
-
125
- compensationResults.push({
126
- stepName: step.name,
127
- success: false,
128
- reason: 'no-compensate-defined'
129
- });
130
-
131
- continue;
132
- }
133
-
134
- try {
135
- this.orchestrator.logger?.info(
136
- `[Saga] 补偿步骤: ${step.name}`
137
- );
138
-
139
- const startTime = Date.now();
140
-
141
- await step.compensate(this.context, completed.result);
142
-
143
- const duration = Date.now() - startTime;
144
-
145
- this.orchestrator.logger?.info(
146
- `[Saga] 补偿成功: ${step.name} (耗时 ${duration}ms)`
147
- );
148
-
149
- compensationResults.push({
150
- stepName: step.name,
151
- success: true,
152
- duration
153
- });
154
-
155
- } catch (compensateError) {
156
- this.orchestrator.logger?.error(
157
- `[Saga] 补偿失败: ${step.name}, 错误: ${compensateError.message}`
158
- );
159
-
160
- compensationResults.push({
161
- stepName: step.name,
162
- success: false,
163
- error: compensateError.message
164
- });
165
- }
166
- }
167
-
168
- // 检查是否所有补偿都成功
169
- const allSuccess = compensationResults.every(
170
- r => r.success || r.reason === 'no-compensate-defined'
171
- );
172
-
173
- if (!allSuccess) {
174
- this.orchestrator.logger?.error(
175
- '[Saga] 部分补偿失败,需要人工介入'
176
- );
177
- } else {
178
- this.orchestrator.logger?.info(
179
- '[Saga] 所有补偿完成'
180
- );
181
- }
182
-
183
- return {
184
- success: allSuccess,
185
- results: compensationResults
186
- };
187
- }
188
-
189
- /**
190
- * 生成 Saga ID
191
- * @private
192
- * @returns {string} Saga ID
193
- */
194
- _generateSagaId() {
195
- return `saga_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
196
- }
197
- }
198
-
199
- module.exports = SagaExecutor;
200
-
201
-
@@ -1,186 +0,0 @@
1
- /**
2
- * Saga 协调器
3
- * 负责管理所有 Saga 定义
4
- * 支持 Redis 存储(多进程共享)或内存存储(单进程)
5
- */
6
- const SagaDefinition = require('./SagaDefinition');
7
-
8
- class SagaOrchestrator {
9
- /**
10
- * 构造函数
11
- * @param {Object} options - 配置选项
12
- * @param {Object} [options.cache] - 缓存实例(可选,Redis 或内存)
13
- * @param {Object} [options.logger] - 日志记录器(可选)
14
- */
15
- constructor(options = {}) {
16
- this.cache = options.cache;
17
- this.logger = options.logger;
18
-
19
- // 存储策略:根据 cache 配置自动选择
20
- // 只有当 cache 存在且是 Redis 实例时才使用 Redis 存储
21
- if (this.cache && this.cache !== false && typeof this.cache.set === 'function') {
22
- // 检测是否为 Redis(通过检查特定方法)
23
- const isRedis = typeof this.cache.keys === 'function' &&
24
- typeof this.cache.publish === 'function';
25
-
26
- if (isRedis) {
27
- // Redis 模式:使用 cache.set/get 存储 Saga 元数据
28
- this.useRedis = true;
29
- this.sagaKeyPrefix = 'monsqlize:saga:def:';
30
- this.logger?.debug('[Saga] 使用 Redis 存储(多进程共享)');
31
- } else {
32
- // 内存缓存模式:使用 Map 存储
33
- this.sagas = new Map();
34
- this.useRedis = false;
35
- this.logger?.debug('[Saga] 使用内存缓存(单进程,Saga 元数据不共享)');
36
- }
37
- } else {
38
- // 内存模式:使用 Map 存储
39
- this.sagas = new Map();
40
- this.useRedis = false;
41
- this.logger?.debug('[Saga] 使用内存存储(单进程)');
42
- }
43
-
44
- // 统计信息
45
- this.stats = {
46
- totalExecutions: 0,
47
- successfulExecutions: 0,
48
- failedExecutions: 0,
49
- compensatedExecutions: 0
50
- };
51
- }
52
-
53
- /**
54
- * 定义 Saga
55
- * @param {Object} config - Saga 配置
56
- * @param {string} config.name - Saga 名称
57
- * @param {Array} config.steps - Saga 步骤列表
58
- * @returns {SagaDefinition} Saga 定义实例
59
- */
60
- async defineSaga(config) {
61
- this._validateConfig(config);
62
-
63
- const saga = new SagaDefinition(config, this);
64
-
65
- if (this.useRedis) {
66
- // 存储元数据到 Redis
67
- await this.cache.set(
68
- this.sagaKeyPrefix + config.name,
69
- {
70
- name: config.name,
71
- steps: config.steps.map(s => ({
72
- name: s.name,
73
- hasCompensate: !!s.compensate
74
- }))
75
- },
76
- 0 // TTL=0 永久存储
77
- );
78
-
79
- // 函数保存在内存
80
- if (!this.sagas) this.sagas = new Map();
81
- this.sagas.set(config.name, saga);
82
- } else {
83
- this.sagas.set(config.name, saga);
84
- }
85
-
86
- this.logger?.debug(`[Saga] 定义 Saga: ${config.name}`);
87
- return saga;
88
- }
89
-
90
- /**
91
- * 执行 Saga
92
- * @param {string} sagaName - Saga 名称
93
- * @param {Object} data - 执行数据
94
- * @returns {Promise<Object>} 执行结果
95
- */
96
- async execute(sagaName, data) {
97
- const saga = this.sagas?.get(sagaName);
98
-
99
- if (!saga && this.useRedis) {
100
- // 检查 Redis 中是否存在
101
- const key = this.sagaKeyPrefix + sagaName;
102
- const def = await this.cache.get(key);
103
-
104
- if (def) {
105
- throw new Error(
106
- `Saga '${sagaName}' 在 Redis 中存在但未在当前进程注册。` +
107
- '请在进程启动时调用 defineSaga() 注册。'
108
- );
109
- }
110
- }
111
-
112
- if (!saga) {
113
- throw new Error(`Saga '${sagaName}' 未定义`);
114
- }
115
-
116
- this.stats.totalExecutions++;
117
-
118
- try {
119
- const result = await saga.execute(data);
120
-
121
- if (result.success) {
122
- this.stats.successfulExecutions++;
123
- } else {
124
- this.stats.failedExecutions++;
125
- this.stats.compensatedExecutions++;
126
- }
127
-
128
- return result;
129
- } catch (error) {
130
- this.stats.failedExecutions++;
131
- throw error;
132
- }
133
- }
134
-
135
- /**
136
- * 列出所有已定义的 Saga
137
- * @returns {Promise<string[]>} Saga 名称列表
138
- */
139
- async listSagas() {
140
- if (this.useRedis) {
141
- const keys = await this.cache.keys(this.sagaKeyPrefix + '*');
142
- return keys.map(key => key.replace(this.sagaKeyPrefix, ''));
143
- } else {
144
- return Array.from(this.sagas.keys());
145
- }
146
- }
147
-
148
- /**
149
- * 获取统计信息
150
- * @returns {Object} 统计信息
151
- */
152
- getStats() {
153
- return {
154
- ...this.stats,
155
- successRate: this.stats.totalExecutions > 0
156
- ? ((this.stats.successfulExecutions / this.stats.totalExecutions) * 100).toFixed(2) + '%'
157
- : '0%',
158
- storageMode: this.useRedis ? 'Redis' : '内存'
159
- };
160
- }
161
-
162
- /**
163
- * 验证 Saga 配置
164
- * @private
165
- * @param {Object} config - Saga 配置
166
- */
167
- _validateConfig(config) {
168
- if (!config.name) {
169
- throw new Error('Saga name is required');
170
- }
171
-
172
- if (!Array.isArray(config.steps) || config.steps.length === 0) {
173
- throw new Error('Saga steps must be a non-empty array');
174
- }
175
-
176
- for (const step of config.steps) {
177
- if (!step.name || !step.execute) {
178
- throw new Error('Each step must have name and execute function');
179
- }
180
- }
181
- }
182
- }
183
-
184
- module.exports = SagaOrchestrator;
185
-
186
-
package/lib/saga/index.js DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * Saga 模块导出
3
- */
4
- module.exports = {
5
- SagaOrchestrator: require('./SagaOrchestrator'),
6
- SagaDefinition: require('./SagaDefinition'),
7
- SagaExecutor: require('./SagaExecutor'),
8
- SagaContext: require('./SagaContext')
9
- };
10
-
11
-
@@ -1,70 +0,0 @@
1
- /**
2
- * 慢查询日志存储接口
3
- * 所有存储适配器必须实现此接口
4
- *
5
- * @version 1.3.0
6
- * @since 2025-12-22
7
- */
8
-
9
- class ISlowQueryLogStorage {
10
- /**
11
- * 初始化存储(创建集合/表、索引等)
12
- * @returns {Promise<void>}
13
- */
14
- async initialize() {
15
- throw new Error('ISlowQueryLogStorage.initialize() must be implemented');
16
- }
17
-
18
- /**
19
- * 保存单条慢查询日志
20
- * @param {Object} log - 慢查询日志对象
21
- * @param {string} log.db - 数据库名
22
- * @param {string} log.collection - 集合名
23
- * @param {string} log.operation - 操作类型
24
- * @param {Object} log.queryShape - 查询模式(已脱敏)
25
- * @param {number} log.executionTimeMs - 执行时间(毫秒)
26
- * @param {Date} log.timestamp - 时间戳
27
- * @param {Object} [log.metadata] - 扩展元数据
28
- * @returns {Promise<void>}
29
- */
30
- async save(log) {
31
- throw new Error('ISlowQueryLogStorage.save() must be implemented');
32
- }
33
-
34
- /**
35
- * 批量保存慢查询日志
36
- * @param {Object[]} logs - 慢查询日志数组
37
- * @returns {Promise<void>}
38
- */
39
- async saveBatch(logs) {
40
- throw new Error('ISlowQueryLogStorage.saveBatch() must be implemented');
41
- }
42
-
43
- /**
44
- * 查询慢查询日志
45
- * @param {Object} filter - 查询条件
46
- * @param {string} [filter.db] - 数据库名
47
- * @param {string} [filter.collection] - 集合名
48
- * @param {string} [filter.operation] - 操作类型
49
- * @param {Object} options - 查询选项
50
- * @param {Object} [options.sort] - 排序规则
51
- * @param {number} [options.limit] - 限制数量
52
- * @param {number} [options.skip] - 跳过数量
53
- * @returns {Promise<Object[]>}
54
- */
55
- async query(filter, options) {
56
- throw new Error('ISlowQueryLogStorage.query() must be implemented');
57
- }
58
-
59
- /**
60
- * 关闭连接
61
- * @returns {Promise<void>}
62
- */
63
- async close() {
64
- throw new Error('ISlowQueryLogStorage.close() must be implemented');
65
- }
66
- }
67
-
68
- module.exports = { ISlowQueryLogStorage };
69
-
70
-
@@ -1,97 +0,0 @@
1
- /**
2
- * 批量队列管理器
3
- * 用于批量写入慢查询日志,优化性能
4
- *
5
- * @version 1.3.0
6
- * @since 2025-12-22
7
- */
8
-
9
- class BatchQueue {
10
- /**
11
- * 创建批量队列
12
- * @param {Object} storage - 存储适配器实例
13
- * @param {Object} options - 队列配置
14
- * @param {number} [options.batchSize=10] - 批量大小
15
- * @param {number} [options.flushInterval=5000] - 刷新间隔(毫秒)
16
- * @param {number} [options.maxBufferSize=100] - 最大缓冲区大小
17
- * @param {Object} [logger] - 日志记录器
18
- */
19
- constructor(storage, options = {}, logger) {
20
- this.storage = storage;
21
- this.buffer = [];
22
- this.batchSize = options.batchSize || 10;
23
- this.flushInterval = options.flushInterval || 5000;
24
- this.maxBufferSize = options.maxBufferSize || 100;
25
- this.timer = null;
26
- this.flushing = false;
27
- this.logger = logger || console;
28
- }
29
-
30
- /**
31
- * 添加日志到队列
32
- * @param {Object} log - 慢查询日志对象
33
- * @returns {Promise<void>}
34
- */
35
- async add(log) {
36
- this.buffer.push(log);
37
-
38
- // 防止内存溢出:达到最大缓冲区,立即刷新
39
- if (this.buffer.length >= this.maxBufferSize) {
40
- await this.flush();
41
- return;
42
- }
43
-
44
- // 达到批量大小,立即刷新
45
- if (this.buffer.length >= this.batchSize) {
46
- await this.flush();
47
- } else if (!this.timer) {
48
- // 启动定时器(防止数据积压)
49
- this.timer = setTimeout(() => this.flush(), this.flushInterval);
50
- }
51
- }
52
-
53
- /**
54
- * 刷新队列(批量写入)
55
- * @returns {Promise<void>}
56
- */
57
- async flush() {
58
- // 防止并发刷新
59
- if (this.flushing || this.buffer.length === 0) {
60
- return;
61
- }
62
-
63
- this.flushing = true;
64
- const logs = this.buffer.splice(0); // 清空缓冲区
65
- clearTimeout(this.timer);
66
- this.timer = null;
67
-
68
- try {
69
- // 批量写入
70
- await this.storage.saveBatch(logs);
71
- if (this.logger.debug) {
72
- this.logger.debug(`[SlowQueryLog] Batch flushed: ${logs.length} logs`);
73
- }
74
- } catch (err) {
75
- // ⚠️ 失败不阻塞主流程,仅记录错误
76
- if (this.logger.error) {
77
- this.logger.error('[SlowQueryLog] Failed to save slow query logs batch:', err);
78
- }
79
- } finally {
80
- this.flushing = false;
81
- }
82
- }
83
-
84
- /**
85
- * 关闭队列(确保数据不丢失)
86
- * @returns {Promise<void>}
87
- */
88
- async close() {
89
- clearTimeout(this.timer);
90
- this.timer = null;
91
- await this.flush(); // 最后刷新一次
92
- }
93
- }
94
-
95
- module.exports = { BatchQueue };
96
-
97
-