monsqlize 1.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 (77) hide show
  1. package/CHANGELOG.md +2474 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1368 -0
  4. package/index.d.ts +1052 -0
  5. package/lib/cache.js +491 -0
  6. package/lib/common/cursor.js +58 -0
  7. package/lib/common/docs-urls.js +72 -0
  8. package/lib/common/index-options.js +222 -0
  9. package/lib/common/log.js +60 -0
  10. package/lib/common/namespace.js +21 -0
  11. package/lib/common/normalize.js +33 -0
  12. package/lib/common/page-result.js +42 -0
  13. package/lib/common/runner.js +56 -0
  14. package/lib/common/server-features.js +231 -0
  15. package/lib/common/shape-builders.js +26 -0
  16. package/lib/common/validation.js +49 -0
  17. package/lib/connect.js +76 -0
  18. package/lib/constants.js +54 -0
  19. package/lib/count-queue.js +187 -0
  20. package/lib/distributed-cache-invalidator.js +259 -0
  21. package/lib/errors.js +157 -0
  22. package/lib/index.js +352 -0
  23. package/lib/logger.js +224 -0
  24. package/lib/model/examples/test.js +114 -0
  25. package/lib/mongodb/common/accessor-helpers.js +44 -0
  26. package/lib/mongodb/common/agg-pipeline.js +32 -0
  27. package/lib/mongodb/common/iid.js +27 -0
  28. package/lib/mongodb/common/lexicographic-expr.js +52 -0
  29. package/lib/mongodb/common/shape.js +31 -0
  30. package/lib/mongodb/common/sort.js +38 -0
  31. package/lib/mongodb/common/transaction-aware.js +24 -0
  32. package/lib/mongodb/connect.js +178 -0
  33. package/lib/mongodb/index.js +458 -0
  34. package/lib/mongodb/management/admin-ops.js +199 -0
  35. package/lib/mongodb/management/bookmark-ops.js +166 -0
  36. package/lib/mongodb/management/cache-ops.js +49 -0
  37. package/lib/mongodb/management/collection-ops.js +386 -0
  38. package/lib/mongodb/management/database-ops.js +201 -0
  39. package/lib/mongodb/management/index-ops.js +474 -0
  40. package/lib/mongodb/management/index.js +16 -0
  41. package/lib/mongodb/management/namespace.js +30 -0
  42. package/lib/mongodb/management/validation-ops.js +267 -0
  43. package/lib/mongodb/queries/aggregate.js +133 -0
  44. package/lib/mongodb/queries/chain.js +623 -0
  45. package/lib/mongodb/queries/count.js +88 -0
  46. package/lib/mongodb/queries/distinct.js +68 -0
  47. package/lib/mongodb/queries/find-and-count.js +183 -0
  48. package/lib/mongodb/queries/find-by-ids.js +235 -0
  49. package/lib/mongodb/queries/find-one-by-id.js +170 -0
  50. package/lib/mongodb/queries/find-one.js +61 -0
  51. package/lib/mongodb/queries/find-page.js +565 -0
  52. package/lib/mongodb/queries/find.js +161 -0
  53. package/lib/mongodb/queries/index.js +49 -0
  54. package/lib/mongodb/writes/delete-many.js +181 -0
  55. package/lib/mongodb/writes/delete-one.js +173 -0
  56. package/lib/mongodb/writes/find-one-and-delete.js +193 -0
  57. package/lib/mongodb/writes/find-one-and-replace.js +222 -0
  58. package/lib/mongodb/writes/find-one-and-update.js +223 -0
  59. package/lib/mongodb/writes/increment-one.js +243 -0
  60. package/lib/mongodb/writes/index.js +41 -0
  61. package/lib/mongodb/writes/insert-batch.js +498 -0
  62. package/lib/mongodb/writes/insert-many.js +218 -0
  63. package/lib/mongodb/writes/insert-one.js +171 -0
  64. package/lib/mongodb/writes/replace-one.js +199 -0
  65. package/lib/mongodb/writes/result-handler.js +236 -0
  66. package/lib/mongodb/writes/update-many.js +205 -0
  67. package/lib/mongodb/writes/update-one.js +207 -0
  68. package/lib/mongodb/writes/upsert-one.js +190 -0
  69. package/lib/multi-level-cache.js +189 -0
  70. package/lib/operators.js +330 -0
  71. package/lib/redis-cache-adapter.js +237 -0
  72. package/lib/transaction/CacheLockManager.js +161 -0
  73. package/lib/transaction/DistributedCacheLockManager.js +239 -0
  74. package/lib/transaction/Transaction.js +314 -0
  75. package/lib/transaction/TransactionManager.js +266 -0
  76. package/lib/transaction/index.js +10 -0
  77. package/package.json +111 -0
package/lib/errors.js ADDED
@@ -0,0 +1,157 @@
1
+ /**
2
+ * 统一错误码定义
3
+ * 集中管理所有错误类型,确保错误处理的一致性
4
+ */
5
+
6
+ const ErrorCodes = {
7
+ // 验证相关错误
8
+ VALIDATION_ERROR: 'VALIDATION_ERROR',
9
+ INVALID_ARGUMENT: 'INVALID_ARGUMENT',
10
+ INVALID_COLLECTION_NAME: 'INVALID_COLLECTION_NAME',
11
+ INVALID_DATABASE_NAME: 'INVALID_DATABASE_NAME',
12
+
13
+ // 游标相关错误
14
+ INVALID_CURSOR: 'INVALID_CURSOR',
15
+ CURSOR_SORT_MISMATCH: 'CURSOR_SORT_MISMATCH',
16
+
17
+ // 分页相关错误
18
+ JUMP_TOO_FAR: 'JUMP_TOO_FAR',
19
+ STREAM_NO_JUMP: 'STREAM_NO_JUMP',
20
+ STREAM_NO_TOTALS: 'STREAM_NO_TOTALS',
21
+ STREAM_NO_EXPLAIN: 'STREAM_NO_EXPLAIN',
22
+
23
+ // 连接相关错误
24
+ CONNECTION_TIMEOUT: 'CONNECTION_TIMEOUT',
25
+ CONNECTION_FAILED: 'CONNECTION_FAILED',
26
+ CONNECTION_CLOSED: 'CONNECTION_CLOSED',
27
+
28
+ // 数据库相关错误
29
+ DATABASE_ERROR: 'DATABASE_ERROR',
30
+ QUERY_TIMEOUT: 'QUERY_TIMEOUT',
31
+
32
+ // 缓存相关错误
33
+ CACHE_ERROR: 'CACHE_ERROR',
34
+ CACHE_TIMEOUT: 'CACHE_TIMEOUT',
35
+
36
+ // 配置相关错误
37
+ INVALID_CONFIG: 'INVALID_CONFIG',
38
+ UNSUPPORTED_DATABASE: 'UNSUPPORTED_DATABASE',
39
+
40
+ // 写操作相关错误
41
+ WRITE_ERROR: 'WRITE_ERROR',
42
+ DOCUMENT_REQUIRED: 'DOCUMENT_REQUIRED',
43
+ DOCUMENTS_REQUIRED: 'DOCUMENTS_REQUIRED',
44
+ DUPLICATE_KEY: 'DUPLICATE_KEY',
45
+ WRITE_CONFLICT: 'WRITE_CONFLICT',
46
+ };
47
+
48
+ /**
49
+ * 创建标准错误对象
50
+ * @param {string} code - 错误码
51
+ * @param {string} message - 错误消息
52
+ * @param {Array} [details] - 详细错误信息
53
+ * @param {Error} [cause] - 原始错误
54
+ * @returns {Error} 标准错误对象
55
+ */
56
+ function createError(code, message, details, cause) {
57
+ const error = new Error(message);
58
+ error.code = code;
59
+ if (details !== undefined) error.details = details;
60
+ if (cause !== undefined) error.cause = cause;
61
+ return error;
62
+ }
63
+
64
+ /**
65
+ * 创建验证错误
66
+ * @param {string|Array} messageOrDetails - 错误消息或验证错误详情(向后兼容)
67
+ * @param {Array} [details] - 详细信息(当第一个参数是字符串时使用)
68
+ * @returns {Error}
69
+ */
70
+ function createValidationError(messageOrDetails, details) {
71
+ // 向后兼容:如果第一个参数是数组,当作 details 处理
72
+ if (Array.isArray(messageOrDetails)) {
73
+ return createError(
74
+ ErrorCodes.VALIDATION_ERROR,
75
+ '参数校验失败',
76
+ messageOrDetails
77
+ );
78
+ }
79
+
80
+ // 新用法:第一个参数是消息字符串
81
+ return createError(
82
+ ErrorCodes.VALIDATION_ERROR,
83
+ messageOrDetails || '参数校验失败',
84
+ details
85
+ );
86
+ }
87
+
88
+ /**
89
+ * 创建游标错误
90
+ * @param {string} message - 错误消息
91
+ * @param {Array} [details] - 详细信息
92
+ * @returns {Error}
93
+ */
94
+ function createCursorError(message, details = null) {
95
+ return createError(
96
+ ErrorCodes.INVALID_CURSOR,
97
+ message || '游标无效',
98
+ details
99
+ );
100
+ }
101
+
102
+ /**
103
+ * 创建连接错误
104
+ * @param {string} message - 错误消息
105
+ * @param {Error} [cause] - 原始错误
106
+ * @returns {Error}
107
+ */
108
+ function createConnectionError(message, cause = null) {
109
+ return createError(
110
+ ErrorCodes.CONNECTION_FAILED,
111
+ message || '数据库连接失败',
112
+ null,
113
+ cause
114
+ );
115
+ }
116
+
117
+ /**
118
+ * 创建查询超时错误
119
+ * @param {number} timeoutMs - 超时时间(毫秒)
120
+ * @param {Error} [cause] - 原始错误
121
+ * @returns {Error}
122
+ */
123
+ function createQueryTimeoutError(timeoutMs, cause = null) {
124
+ return createError(
125
+ ErrorCodes.QUERY_TIMEOUT,
126
+ `查询超时 (${timeoutMs}ms)`,
127
+ null,
128
+ cause
129
+ );
130
+ }
131
+
132
+ /**
133
+ * 创建写操作错误
134
+ * @param {string} operation - 操作名称
135
+ * @param {string} message - 错误消息
136
+ * @param {Error} [cause] - 原始错误
137
+ * @returns {Error}
138
+ */
139
+ function createWriteError(operation, message, cause = null) {
140
+ return createError(
141
+ ErrorCodes.WRITE_ERROR,
142
+ `${operation} 失败: ${message}`,
143
+ null,
144
+ cause
145
+ );
146
+ }
147
+
148
+ module.exports = {
149
+ ErrorCodes,
150
+ createError,
151
+ createValidationError,
152
+ createCursorError,
153
+ createConnectionError,
154
+ createQueryTimeoutError,
155
+ createWriteError,
156
+ };
157
+
package/lib/index.js ADDED
@@ -0,0 +1,352 @@
1
+ const Logger = require('./logger');
2
+ const ConnectionManager = require('./connect');
3
+ const MemoryCache = require('./cache');
4
+ const { createRedisCacheAdapter } = require('./redis-cache-adapter');
5
+ const TransactionManager = require('./transaction/TransactionManager');
6
+ const CacheLockManager = require('./transaction/CacheLockManager');
7
+ const DistributedCacheInvalidator = require('./distributed-cache-invalidator');
8
+
9
+ module.exports = class {
10
+
11
+ /**
12
+ * 初始化数据库连接配置
13
+ * @param {Object} options - 数据库连接配置选项
14
+ * @param {string} options.type - 数据库类型,支持 mongodb
15
+ * @param {Object} options.config - 数据库连接配置
16
+ * @param {Object} [options.cache] - 缓存配置选项
17
+ * @param {Object} [options.logger] - 日志记录器
18
+ * @param {number} [options.maxTimeMS] - 全局默认查询超时时间(毫秒)
19
+ * @param {{instanceId?: string}} [options.namespace] - 命名空间设置(用于缓存隔离)
20
+ * @throws {Error} 如果数据库类型无效则抛出错误
21
+ */
22
+ constructor(options) {
23
+ if (!options.type || !['mongodb'].includes(options.type)) {
24
+ throw new Error('Invalid database type. Supported types are: mongodb');
25
+ }
26
+ const { type = 'mongodb', databaseName, config, cache, logger } = options;
27
+ this.type = type;
28
+ this.databaseName = databaseName;
29
+ this.config = config;
30
+
31
+ // 🔧 修复:保存 distributed 配置到单独的变量
32
+ this._cacheConfig = cache;
33
+
34
+ // Count 队列配置(高并发控制,避免压垮数据库)
35
+ // 默认值:
36
+ // - enabled: true (默认启用)
37
+ // - concurrency: CPU 核心数(最少 4,最多 16)
38
+ // - maxQueueSize: 10000
39
+ // - timeout: 60000ms (1分钟)
40
+ this.countQueue = options.countQueue !== undefined ? options.countQueue : {
41
+ enabled: true, // 默认启用
42
+ concurrency: undefined, // undefined 则使用 CPU 核心数
43
+ maxQueueSize: 10000, // 队列最大 10000
44
+ timeout: 60000 // 超时 60 秒
45
+ };
46
+
47
+ // 使用缓存工厂获取有效的缓存实例
48
+ this.cache = MemoryCache.getOrCreateCache(cache);
49
+
50
+ // 使用 Logger 工具类创建日志记录器
51
+ this.logger = Logger.create(logger);
52
+
53
+ // 集中默认配置(库内默认 + 用户覆盖)
54
+ const DEFAULTS = {
55
+ maxTimeMS: 2000,
56
+ findLimit: 10,
57
+ slowQueryMs: 500,
58
+ namespace: { scope: 'database' },
59
+ // 深分页/聚合相关
60
+ findPageMaxLimit: 500,
61
+ cursorSecret: undefined,
62
+ // 慢日志扩展
63
+ log: { slowQueryTag: { event: 'slow_query', code: 'SLOW_QUERY' } },
64
+ };
65
+ const deepMerge = (base, patch) => {
66
+ const out = { ...base };
67
+ for (const k of Object.keys(patch || {})) {
68
+ const v = patch[k];
69
+ if (v && typeof v === 'object' && !Array.isArray(v)) {
70
+ out[k] = deepMerge(base[k] || {}, v);
71
+ } else if (v !== undefined) {
72
+ out[k] = v;
73
+ }
74
+ }
75
+ return out;
76
+ };
77
+ this.defaults = deepMerge(DEFAULTS, {
78
+ maxTimeMS: options.maxTimeMS,
79
+ findLimit: options.findLimit,
80
+ namespace: options.namespace,
81
+ slowQueryMs: options.slowQueryMs,
82
+ // 新增可选项
83
+ findPageMaxLimit: options.findPageMaxLimit,
84
+ cursorSecret: options.cursorSecret,
85
+ log: options.log,
86
+ });
87
+ // 冻结默认配置,避免运行期被意外修改
88
+ this.defaults = Object.freeze(this.defaults);
89
+ }
90
+
91
+ /**
92
+ * 连接数据库并返回访问集合/表的对象
93
+ * @returns {{collection: Function, db: Function}} 返回包含 collection 与 db 方法的对象
94
+ * @throws {Error} 当连接失败时抛出错误
95
+ */
96
+ async connect() {
97
+ // 如果已经有连接,直接返回访问对象
98
+ if (this.dbInstance) {
99
+ return this.dbInstance;
100
+ }
101
+
102
+ // 防止并发连接:使用连接锁
103
+ if (this._connecting) {
104
+ return this._connecting;
105
+ }
106
+
107
+ try {
108
+ this._connecting = (async () => {
109
+ // 使用 ConnectionManager 建立连接
110
+ const { collection, db, instance } = await ConnectionManager.connect(
111
+ this.type,
112
+ this.databaseName,
113
+ this.config,
114
+ this.cache,
115
+ this.logger,
116
+ this.defaults,
117
+ );
118
+
119
+ // 保存连接状态(关键:缓存对象,保证多次调用幂等返回同一形态/引用)
120
+ this.dbInstance = { collection, db };
121
+ this._adapter = instance;
122
+
123
+ // 初始化分布式缓存失效器(如果配置了)
124
+ // 🔧 修复:使用 _cacheConfig 读取 distributed 配置
125
+ if (this._cacheConfig &&
126
+ typeof this._cacheConfig.distributed === 'object' &&
127
+ this._cacheConfig.distributed.enabled !== false) {
128
+ try {
129
+ // 🆕 自动从 cache.remote 提取 Redis 实例(如果未配置)
130
+ let redis = this._cacheConfig.distributed.redis;
131
+ if (!redis && !this._cacheConfig.distributed.redisUrl) {
132
+ // 尝试从 remote 缓存适配器中获取 Redis 实例
133
+ if (this.cache.remote && typeof this.cache.remote.getRedisInstance === 'function') {
134
+ redis = this.cache.remote.getRedisInstance();
135
+ if (this.logger) {
136
+ this.logger.info('[DistributedCache] Auto-detected Redis from cache.remote');
137
+ }
138
+ }
139
+ }
140
+
141
+ this._cacheInvalidator = new DistributedCacheInvalidator({
142
+ redisUrl: this._cacheConfig.distributed.redisUrl,
143
+ redis: redis,
144
+ channel: this._cacheConfig.distributed.channel,
145
+ instanceId: this._cacheConfig.distributed.instanceId,
146
+ cache: this.cache,
147
+ logger: this.logger
148
+ });
149
+
150
+ // 🆕 关键:将 invalidate 方法注入到 MultiLevelCache
151
+ if (this.cache && typeof this.cache.setPublish === 'function') {
152
+ this.cache.setPublish((msg) => {
153
+ if (msg && msg.type === 'invalidate' && msg.pattern) {
154
+ this._cacheInvalidator.invalidate(msg.pattern).catch((err) => {
155
+ this.logger.error('❌ Broadcast invalidation failed:', err.message);
156
+ });
157
+ }
158
+ });
159
+ this.logger.info('✅ Distributed cache invalidator initialized', {
160
+ channel: this._cacheInvalidator.channel,
161
+ integrated: true
162
+ });
163
+ } else {
164
+ this.logger.warn('⚠️ Cache does not support setPublish, distributed invalidation disabled');
165
+ }
166
+ } catch (error) {
167
+ this.logger.error('❌ Failed to initialize distributed cache invalidator:', error.message);
168
+ }
169
+ }
170
+
171
+ // 初始化事务管理器和缓存锁管理器
172
+ if (this.type === 'mongodb' && instance.client) {
173
+ // 检查是否配置了分布式事务锁
174
+ const useDistributedLock = this.cache &&
175
+ typeof this.cache.transaction === 'object' &&
176
+ this.cache.transaction.distributedLock &&
177
+ this.cache.transaction.distributedLock.redis;
178
+
179
+ if (useDistributedLock) {
180
+ // 使用分布式缓存锁管理器
181
+ const DistributedCacheLockManager = require('./transaction/DistributedCacheLockManager');
182
+ this._lockManager = new DistributedCacheLockManager({
183
+ redis: this.cache.transaction.distributedLock.redis,
184
+ lockKeyPrefix: this.cache.transaction.distributedLock.keyPrefix || 'monsqlize:cache:lock:',
185
+ maxDuration: 300000,
186
+ logger: this.logger
187
+ });
188
+ this.logger.info('✅ Distributed cache lock manager initialized');
189
+ } else {
190
+ // 使用本地缓存锁管理器
191
+ this._lockManager = new CacheLockManager({
192
+ logger: this.logger,
193
+ maxDuration: 300000, // 锁最长持续5分钟
194
+ cleanupInterval: 10000 // 每10秒清理一次
195
+ });
196
+ }
197
+
198
+ // 将锁管理器注入到缓存
199
+ if (this.cache && typeof this.cache.setLockManager === 'function') {
200
+ this.cache.setLockManager(this._lockManager);
201
+ }
202
+
203
+ // 创建事务管理器
204
+ this._transactionManager = new TransactionManager(
205
+ instance, // 传入完整的 adapter 实例
206
+ this.cache,
207
+ this.logger,
208
+ {
209
+ lockManager: this._lockManager
210
+ }
211
+ );
212
+
213
+ this.logger.info('✅ Transaction manager initialized', {
214
+ hasClient: !!instance.client,
215
+ hasLockManager: !!this._lockManager,
216
+ isDistributed: useDistributedLock
217
+ });
218
+ } else {
219
+ this.logger.warn('⚠️ Transaction manager not initialized', {
220
+ type: this.type,
221
+ hasClient: !!instance.client
222
+ });
223
+ }
224
+
225
+ return this.dbInstance;
226
+ })();
227
+
228
+ const result = await this._connecting;
229
+ this._connecting = null;
230
+ return result;
231
+ } catch (err) {
232
+ this._connecting = null;
233
+ throw err;
234
+ }
235
+ }
236
+
237
+ /**
238
+ * 获取底层缓存实例(用于查看统计或手动失效)
239
+ * @returns {Object} 缓存实例
240
+ */
241
+ getCache() {
242
+ return this.cache;
243
+ }
244
+
245
+ /**
246
+ * 获取当前实例的默认配置(只读视图)
247
+ * @returns {{maxTimeMS?:number, findLimit?:number, namespace?:object, slowQueryMs?:number}}
248
+ */
249
+ getDefaults() {
250
+ return { ...this.defaults };
251
+ }
252
+
253
+ /**
254
+ * 关闭底层数据库连接(释放资源)
255
+ */
256
+ async close() {
257
+ // 清理分布式缓存失效器
258
+ if (this._cacheInvalidator && typeof this._cacheInvalidator.close === 'function') {
259
+ await this._cacheInvalidator.close();
260
+ this._cacheInvalidator = null;
261
+ }
262
+
263
+ // 清理事务管理器
264
+ if (this._transactionManager && typeof this._transactionManager.destroy === 'function') {
265
+ await this._transactionManager.destroy();
266
+ this._transactionManager = null;
267
+ }
268
+
269
+ // 清理锁管理器
270
+ if (this._lockManager && typeof this._lockManager.destroy === 'function') {
271
+ this._lockManager.destroy();
272
+ this._lockManager = null;
273
+ }
274
+
275
+ // 关闭数据库连接
276
+ if (this._adapter && typeof this._adapter.close === 'function') {
277
+ await this._adapter.close();
278
+ }
279
+
280
+ // 清理状态
281
+ this.dbInstance = null;
282
+ this._adapter = null;
283
+ this._connecting = null;
284
+ }
285
+
286
+ /**
287
+ * 健康检查(适配器透传)
288
+ */
289
+ async health() {
290
+ if (this._adapter && typeof this._adapter.health === 'function') {
291
+ return this._adapter.health();
292
+ }
293
+ return { status: 'down', connected: false };
294
+ }
295
+
296
+ /**
297
+ * 事件订阅(适配器透传)
298
+ * @param {'connected'|'closed'|'error'|'slow-query'} event
299
+ * @param {(payload:any)=>void} handler
300
+ */
301
+ on(event, handler) {
302
+ if (this._adapter && typeof this._adapter.on === 'function') {
303
+ this._adapter.on(event, handler);
304
+ }
305
+ }
306
+
307
+
308
+ /**
309
+ * 启动一个事务会话(手动管理)
310
+ * @param {Object} options - 事务选项
311
+ * @param {Object} [options.readConcern] - 读关注级别 { level: 'majority' | 'local' | 'snapshot' }
312
+ * @param {string} [options.readPreference] - 读偏好
313
+ * @param {boolean} [options.causalConsistency=true] - 因果一致性
314
+ * @param {number} [options.timeout=30000] - 事务超时时间(毫秒)
315
+ * @returns {Promise<Transaction>}
316
+ */
317
+ async startSession(options = {}) {
318
+ if (!this._transactionManager) {
319
+ throw new Error('Connection not established. Call connect() first.');
320
+ }
321
+ return this._transactionManager.startSession(options);
322
+ }
323
+
324
+ /**
325
+ * 使用事务执行操作(自动管理,推荐)
326
+ * @param {Function} callback - 事务回调函数,接收 Transaction 对象作为参数
327
+ * @param {Object} options - 事务选项(同 startSession)
328
+ * @param {number} [options.maxRetries=3] - 最大重试次数
329
+ * @param {number} [options.retryDelay=100] - 重试延迟(毫秒)
330
+ * @param {number} [options.retryBackoff=2] - 重试退避系数
331
+ * @returns {Promise<any>} 返回 callback 的返回值
332
+ */
333
+ async withTransaction(callback, options = {}) {
334
+ if (!this._transactionManager) {
335
+ throw new Error('Connection not established. Call connect() first.');
336
+ }
337
+ return this._transactionManager.withTransaction(callback, options);
338
+ }
339
+
340
+ /** 取消事件订阅(适配器透传) */
341
+ off(event, handler) {
342
+ if (this._adapter && typeof this._adapter.off === 'function') {
343
+ this._adapter.off(event, handler);
344
+ }
345
+ }
346
+
347
+ /**
348
+ * 导出工具函数:创建 Redis 缓存适配器
349
+ * @static
350
+ */
351
+ static createRedisCacheAdapter = createRedisCacheAdapter;
352
+ }