@aetherframework/database 1.0.9 → 1.1.1
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/package.json +1 -2
- package/src/DatabaseManager.js +0 -565
- package/src/core/ConnectionManager.js +0 -351
- package/src/core/DatabaseFactory.js +0 -188
- package/src/core/MongoQueryBuilder.js +0 -576
- package/src/core/PluginManager.js +0 -968
- package/src/core/QueryBuilder.js +0 -4398
- package/src/core/TransactionManager.js +0 -40
- package/src/drivers/clickhouse-driver.js +0 -272
- package/src/drivers/index.js +0 -273
- package/src/drivers/mongodb-driver.js +0 -87
- package/src/drivers/mssql-driver.js +0 -117
- package/src/drivers/mysql-driver.js +0 -169
- package/src/drivers/oracle-driver.js +0 -101
- package/src/drivers/postgres-driver.js +0 -234
- package/src/drivers/redis-driver.js +0 -52
- package/src/drivers/sqlite-driver.js +0 -67
- package/src/middleware/connection-pool.js +0 -455
- package/src/middleware/performance-monitor.js +0 -652
- package/src/middleware/query-cache.js +0 -500
- package/src/middleware/query-logger.js +0 -262
- package/src/plugins/AuditPlugin.js +0 -447
- package/src/plugins/BasePlugin.js +0 -418
- package/src/plugins/BatchOperationPlugin.js +0 -165
- package/src/plugins/CachePlugin.js +0 -407
- package/src/plugins/CtePlugin.js +0 -523
- package/src/plugins/DistributedPlugin.js +0 -543
- package/src/plugins/EncryptionPlugin.js +0 -211
- package/src/plugins/FullTextSearchPlugin.js +0 -164
- package/src/plugins/GeospatialPlugin.js +0 -219
- package/src/plugins/GraphQLPlugin.js +0 -162
- package/src/plugins/HookPlugin.js +0 -211
- package/src/plugins/JsonPlugin.js +0 -366
- package/src/plugins/OptimisticLockPlugin.js +0 -374
- package/src/plugins/PerformancePlugin.js +0 -175
- package/src/plugins/ResiliencePlugin.js +0 -114
- package/src/plugins/ShardingPlugin.js +0 -227
- package/src/plugins/SoftDeletePlugin.js +0 -258
- package/src/plugins/SyncPlugin.js +0 -373
- package/src/plugins/VersioningPlugin.js +0 -314
- package/src/plugins/WindowFunctionPlugin.js +0 -343
- package/src/utils/config-loader.js +0 -632
- package/src/utils/error-handler.js +0 -724
- package/src/utils/migration-runner.js +0 -1066
|
@@ -1,543 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/plugin/DistributedPlugin
|
|
6
|
-
*/
|
|
7
|
-
import { BasePlugin } from "./BasePlugin.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Distributed feature plugin for QueryBuilder
|
|
11
|
-
* Provides distributed system capabilities: connection pool management, read-write splitting, service discovery integration
|
|
12
|
-
*
|
|
13
|
-
* @class DistributedPlugin
|
|
14
|
-
* @extends {BasePlugin}
|
|
15
|
-
* @description Plugin for handling distributed database operations including connection pooling,
|
|
16
|
-
* read-write splitting, shard routing, distributed locking, and cloud-native configuration
|
|
17
|
-
*/
|
|
18
|
-
export class DistributedPlugin extends BasePlugin {
|
|
19
|
-
/**
|
|
20
|
-
* Plugin name identifier
|
|
21
|
-
* @type {string}
|
|
22
|
-
* @static
|
|
23
|
-
*/
|
|
24
|
-
static name = 'distributed';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Supported distributed features
|
|
28
|
-
* @type {string[]}
|
|
29
|
-
* @static
|
|
30
|
-
*/
|
|
31
|
-
static supportedFeatures = ['connectionPool', 'readWriteSplit', 'shardRouting', 'distributedLock', 'configCenter'];
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Create a distributed plugin instance
|
|
35
|
-
* @param {Object} queryBuilder - QueryBuilder instance to attach to
|
|
36
|
-
* @param {Object} options - Plugin configuration options
|
|
37
|
-
* @param {Object} [options.connectionPool=null] - External connection pool instance
|
|
38
|
-
* @param {Object} [options.readWriteSplit=null] - Read-write split configuration
|
|
39
|
-
* @param {Object} [options.shardRouting=null] - Shard routing configuration
|
|
40
|
-
* @param {Object} [options.distributedLock=null] - Distributed lock client (Redis/ZooKeeper)
|
|
41
|
-
* @param {Object} [options.configCenter=null] - Cloud native config center client
|
|
42
|
-
*/
|
|
43
|
-
constructor(queryBuilder, options = {}) {
|
|
44
|
-
super(queryBuilder);
|
|
45
|
-
this.pluginName = "DistributedPlugin";
|
|
46
|
-
this.connectionPool = options.connectionPool || null;
|
|
47
|
-
this.readWriteSplit = options.readWriteSplit || null;
|
|
48
|
-
this.shardRouting = options.shardRouting || null;
|
|
49
|
-
this.distributedLockClient = options.distributedLock || null;
|
|
50
|
-
this.configCenter = options.configCenter || null;
|
|
51
|
-
this.primaryConnection = null;
|
|
52
|
-
this.replicaConnections = [];
|
|
53
|
-
this._roundRobinIndex = 0;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Register plugin methods to QueryBuilder
|
|
58
|
-
* @protected
|
|
59
|
-
* @override
|
|
60
|
-
*/
|
|
61
|
-
_registerMethods() {
|
|
62
|
-
// Register distributed methods to QueryBuilder
|
|
63
|
-
this.methods = {
|
|
64
|
-
executeWithPool: this.executeWithPool.bind(this),
|
|
65
|
-
executeWithDistributedLock: this.executeWithDistributedLock.bind(this),
|
|
66
|
-
routeToShard: this.routeToShard.bind(this),
|
|
67
|
-
getReadConnection: this.getReadConnection.bind(this),
|
|
68
|
-
isReadOnlyQuery: this.isReadOnlyQuery.bind(this),
|
|
69
|
-
getDistributedHealthStatus: this.getHealthStatus.bind(this),
|
|
70
|
-
updateDistributedConfig: this.updateConfig.bind(this)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Register hooks for the plugin
|
|
76
|
-
* @protected
|
|
77
|
-
* @override
|
|
78
|
-
*/
|
|
79
|
-
_registerHooks() {
|
|
80
|
-
// Register query execution hooks for automatic read-write splitting
|
|
81
|
-
this.registerHook('beforeExecute', async (sql, bindings) => {
|
|
82
|
-
// Automatically route read-only queries to replica connections
|
|
83
|
-
if (this.readWriteSplit && this.isReadOnlyQuery()) {
|
|
84
|
-
const readConn = this.getReadConnection();
|
|
85
|
-
if (readConn && this.queryBuilder.connection !== readConn) {
|
|
86
|
-
const oldConn = this.queryBuilder.connection;
|
|
87
|
-
this.queryBuilder.connection = readConn;
|
|
88
|
-
return () => {
|
|
89
|
-
// Cleanup hook: restore original connection
|
|
90
|
-
this.queryBuilder.connection = oldConn;
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}, { priority: 100 });
|
|
96
|
-
|
|
97
|
-
// Register after execution hook for metrics collection
|
|
98
|
-
this.registerHook('afterExecute', async (result) => {
|
|
99
|
-
if (this.configCenter) {
|
|
100
|
-
await this._recordMetrics(result);
|
|
101
|
-
}
|
|
102
|
-
return result;
|
|
103
|
-
}, { priority: 50 });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Register middlewares for the plugin
|
|
108
|
-
* @protected
|
|
109
|
-
* @override
|
|
110
|
-
*/
|
|
111
|
-
_registerMiddlewares() {
|
|
112
|
-
// Register connection pool middleware
|
|
113
|
-
this.registerMiddleware('connection', async (context, next) => {
|
|
114
|
-
if (this.connectionPool && context.usePool !== false) {
|
|
115
|
-
const connection = await this.connectionPool.getConnection();
|
|
116
|
-
try {
|
|
117
|
-
context.connection = connection;
|
|
118
|
-
const result = await next();
|
|
119
|
-
return result;
|
|
120
|
-
} finally {
|
|
121
|
-
this.connectionPool.release(connection);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return await next();
|
|
125
|
-
}, { priority: 100 });
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Initialize the plugin
|
|
130
|
-
* @async
|
|
131
|
-
* @returns {Promise<void>}
|
|
132
|
-
* @override
|
|
133
|
-
*/
|
|
134
|
-
async init() {
|
|
135
|
-
await super.init();
|
|
136
|
-
|
|
137
|
-
if (this.connectionPool) {
|
|
138
|
-
this._setupConnectionPool();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (this.readWriteSplit) {
|
|
142
|
-
this._setupReadWriteSplit();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (this.configCenter) {
|
|
146
|
-
this._watchConfigChanges();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Use connection pool to get connection for execution
|
|
154
|
-
* @async
|
|
155
|
-
* @param {QueryBuilder} qb - Query builder instance
|
|
156
|
-
* @returns {Promise<any>} Query execution result
|
|
157
|
-
*/
|
|
158
|
-
async executeWithPool(qb) {
|
|
159
|
-
const connection = await this.connectionPool.getConnection();
|
|
160
|
-
try {
|
|
161
|
-
qb.connection = connection;
|
|
162
|
-
const result = await qb.execute();
|
|
163
|
-
return result;
|
|
164
|
-
} finally {
|
|
165
|
-
this.connectionPool.release(connection);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Execute query with distributed lock protection
|
|
171
|
-
* @async
|
|
172
|
-
* @param {string} lockKey - Unique lock key
|
|
173
|
-
* @param {number} [timeout=5000] - Lock acquire timeout in milliseconds
|
|
174
|
-
* @returns {Promise<any>} Query execution result
|
|
175
|
-
* @throws {Error} If distributed lock client not configured
|
|
176
|
-
*/
|
|
177
|
-
async executeWithDistributedLock(lockKey, timeout = 5000) {
|
|
178
|
-
if (!this.distributedLockClient) {
|
|
179
|
-
throw new Error('Distributed lock client not configured. Please initialize plugin with distributedLock option.');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const lock = await this.distributedLockClient.acquire(lockKey, timeout);
|
|
183
|
-
try {
|
|
184
|
-
return await this.queryBuilder.execute();
|
|
185
|
-
} finally {
|
|
186
|
-
await lock.release();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Route query to specific shard by shard key
|
|
192
|
-
* @param {string|number} shardKey - Sharding key value
|
|
193
|
-
* @returns {QueryBuilder} Current query builder instance with correct connection
|
|
194
|
-
* @throws {Error} If shard routing not configured
|
|
195
|
-
*/
|
|
196
|
-
routeToShard(shardKey) {
|
|
197
|
-
if (!this.shardRouting) {
|
|
198
|
-
throw new Error('Shard routing not configured. Please initialize plugin with shardRouting option.');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const shard = this._calculateShard(shardKey);
|
|
202
|
-
this.queryBuilder.connection = shard.connection;
|
|
203
|
-
this.queryBuilder.tableName = shard.getTableName(this.queryBuilder.originalTableName, shardKey);
|
|
204
|
-
return this.queryBuilder;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Get read connection based on read-write split strategy
|
|
209
|
-
* @returns {Object} Read connection
|
|
210
|
-
*/
|
|
211
|
-
getReadConnection() {
|
|
212
|
-
if (!this.readWriteSplit || this.replicaConnections.length === 0) {
|
|
213
|
-
return this.primaryConnection;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return this._selectReplicaByStrategy();
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Check if current query is read-only operation
|
|
221
|
-
* @returns {boolean} True if query is read-only
|
|
222
|
-
*/
|
|
223
|
-
isReadOnlyQuery() {
|
|
224
|
-
const queryType = this.queryBuilder.query.type;
|
|
225
|
-
return ['select', 'exists', 'count'].includes(queryType);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Setup connection pool integration
|
|
230
|
-
* @returns {void}
|
|
231
|
-
* @private
|
|
232
|
-
*/
|
|
233
|
-
_setupConnectionPool() {
|
|
234
|
-
// Validate connection pool interface
|
|
235
|
-
if (typeof this.connectionPool.getConnection !== 'function' ||
|
|
236
|
-
typeof this.connectionPool.release !== 'function') {
|
|
237
|
-
throw new Error('Connection pool must implement getConnection and release methods');
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Setup read-write split connections
|
|
243
|
-
* @returns {void}
|
|
244
|
-
* @private
|
|
245
|
-
*/
|
|
246
|
-
_setupReadWriteSplit() {
|
|
247
|
-
this.primaryConnection = this.readWriteSplit.primary;
|
|
248
|
-
this.replicaConnections = this.readWriteSplit.replicas || [];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Watch dynamic configuration changes from config center
|
|
253
|
-
* @returns {void}
|
|
254
|
-
* @private
|
|
255
|
-
*/
|
|
256
|
-
_watchConfigChanges() {
|
|
257
|
-
if (!this.configCenter || !this.configCenter.watch) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Watch pool size changes
|
|
262
|
-
this.configCenter.watch('database.pool.size', (newSize) => {
|
|
263
|
-
if (this.connectionPool && this.connectionPool.resize) {
|
|
264
|
-
this.connectionPool.resize(newSize);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Watch replica node changes
|
|
269
|
-
this.configCenter.watch('database.readWriteSplit.replicas', (newReplicas) => {
|
|
270
|
-
this.replicaConnections = newReplicas;
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Calculate target shard by shard key using consistent hashing
|
|
276
|
-
* @param {string|number} shardKey - Sharding key
|
|
277
|
-
* @returns {Object} Target shard configuration
|
|
278
|
-
* @private
|
|
279
|
-
*/
|
|
280
|
-
_calculateShard(shardKey) {
|
|
281
|
-
const shards = this.shardRouting.shards;
|
|
282
|
-
const hash = this._hashString(String(shardKey));
|
|
283
|
-
const index = hash % shards.length;
|
|
284
|
-
return shards[index];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Select replica connection based on load balancing strategy
|
|
289
|
-
* @returns {Object} Selected replica connection
|
|
290
|
-
* @private
|
|
291
|
-
*/
|
|
292
|
-
_selectReplicaByStrategy() {
|
|
293
|
-
const strategy = this.readWriteSplit.strategy || 'round-robin';
|
|
294
|
-
|
|
295
|
-
switch (strategy) {
|
|
296
|
-
case 'round-robin':
|
|
297
|
-
const index = this._roundRobinIndex++ % this.replicaConnections.length;
|
|
298
|
-
return this.replicaConnections[index];
|
|
299
|
-
|
|
300
|
-
case 'random':
|
|
301
|
-
const randomIndex = Math.floor(Math.random() * this.replicaConnections.length);
|
|
302
|
-
return this.replicaConnections[randomIndex];
|
|
303
|
-
|
|
304
|
-
case 'least-connected':
|
|
305
|
-
return this.replicaConnections
|
|
306
|
-
.sort((a, b) => a.activeConnections - b.activeConnections);
|
|
307
|
-
|
|
308
|
-
default:
|
|
309
|
-
return this.replicaConnections;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Simple string hash function for consistent hashing
|
|
315
|
-
* @param {string} str - Input string
|
|
316
|
-
* @returns {number} Hash value
|
|
317
|
-
* @private
|
|
318
|
-
*/
|
|
319
|
-
_hashString(str) {
|
|
320
|
-
let hash = 0;
|
|
321
|
-
for (let i = 0; i < str.length; i++) {
|
|
322
|
-
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
|
323
|
-
hash |= 0; // Convert to 32bit integer
|
|
324
|
-
}
|
|
325
|
-
return Math.abs(hash);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Record metrics to config center
|
|
330
|
-
* @param {Object} result - Query execution result
|
|
331
|
-
* @returns {Promise<void>}
|
|
332
|
-
* @private
|
|
333
|
-
*/
|
|
334
|
-
async _recordMetrics(result) {
|
|
335
|
-
if (!this.configCenter || !this.configCenter.recordMetric) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const metrics = {
|
|
340
|
-
timestamp: Date.now(),
|
|
341
|
-
queryType: this.queryBuilder.query.type,
|
|
342
|
-
shardKey: this.shardRouting ? 'calculated' : 'none',
|
|
343
|
-
readWrite: this.readWriteSplit ? 'split' : 'single',
|
|
344
|
-
connectionPool: !!this.connectionPool
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
await this.configCenter.recordMetric('distributed_query', metrics);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Update plugin configuration dynamically
|
|
352
|
-
* @param {Object} newConfig - New configuration
|
|
353
|
-
* @returns {Promise<void>}
|
|
354
|
-
*/
|
|
355
|
-
async updateConfig(newConfig) {
|
|
356
|
-
// Cleanup old configuration
|
|
357
|
-
await this.cleanup();
|
|
358
|
-
|
|
359
|
-
// Update configuration
|
|
360
|
-
Object.assign(this.config, newConfig);
|
|
361
|
-
|
|
362
|
-
if (newConfig.connectionPool) {
|
|
363
|
-
this.connectionPool = newConfig.connectionPool;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (newConfig.readWriteSplit) {
|
|
367
|
-
this.readWriteSplit = newConfig.readWriteSplit;
|
|
368
|
-
this._setupReadWriteSplit();
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (newConfig.shardRouting) {
|
|
372
|
-
this.shardRouting = newConfig.shardRouting;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if (newConfig.distributedLock) {
|
|
376
|
-
this.distributedLockClient = newConfig.distributedLock;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (newConfig.configCenter) {
|
|
380
|
-
this.configCenter = newConfig.configCenter;
|
|
381
|
-
this._watchConfigChanges();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Re-initialize
|
|
385
|
-
await this.init();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Get plugin health status for cloud native monitoring
|
|
390
|
-
* @returns {Promise<Object>} Health status object
|
|
391
|
-
*/
|
|
392
|
-
async getHealthStatus() {
|
|
393
|
-
const status = {
|
|
394
|
-
healthy: true,
|
|
395
|
-
features: {
|
|
396
|
-
connectionPool: !!this.connectionPool,
|
|
397
|
-
readWriteSplit: !!this.readWriteSplit,
|
|
398
|
-
shardRouting: !!this.shardRouting,
|
|
399
|
-
distributedLock: !!this.distributedLockClient,
|
|
400
|
-
configCenter: !!this.configCenter
|
|
401
|
-
},
|
|
402
|
-
timestamp: Date.now()
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
if (this.connectionPool) {
|
|
406
|
-
try {
|
|
407
|
-
status.poolStats = await this.connectionPool.getStats();
|
|
408
|
-
} catch (error) {
|
|
409
|
-
status.poolStats = { error: error.message };
|
|
410
|
-
status.healthy = false;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
return status;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Cleanup resources when plugin is destroyed
|
|
419
|
-
* @returns {Promise<void>}
|
|
420
|
-
* @override
|
|
421
|
-
*/
|
|
422
|
-
async cleanup() {
|
|
423
|
-
// Cleanup config center watchers
|
|
424
|
-
if (this.configCenter && this.configCenter.unwatch) {
|
|
425
|
-
this.configCenter.unwatch('database.pool.size');
|
|
426
|
-
this.configCenter.unwatch('database.readWriteSplit.replicas');
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// Cleanup connection pool
|
|
430
|
-
if (this.connectionPool) {
|
|
431
|
-
await this.connectionPool.end();
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Call parent cleanup
|
|
435
|
-
await super.cleanup();
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Get plugin metadata
|
|
442
|
-
* @returns {Object} Plugin metadata
|
|
443
|
-
* @override
|
|
444
|
-
*/
|
|
445
|
-
getMetadata() {
|
|
446
|
-
const baseMetadata = super.getMetadata();
|
|
447
|
-
return {
|
|
448
|
-
...baseMetadata,
|
|
449
|
-
name: DistributedPlugin.name,
|
|
450
|
-
description: 'Distributed database operations plugin with connection pooling, read-write splitting, sharding, and distributed locking',
|
|
451
|
-
version: '1.0.0',
|
|
452
|
-
features: DistributedPlugin.supportedFeatures,
|
|
453
|
-
dependencies: ['BasePlugin']
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Validate plugin configuration
|
|
459
|
-
* @param {Object} config - Plugin configuration
|
|
460
|
-
* @returns {Object} Validation result
|
|
461
|
-
* @override
|
|
462
|
-
*/
|
|
463
|
-
validateConfig(config) {
|
|
464
|
-
const baseValidation = super.validateConfig(config);
|
|
465
|
-
const errors = [...baseValidation.errors];
|
|
466
|
-
const warnings = [...baseValidation.warnings];
|
|
467
|
-
|
|
468
|
-
// Validate connection pool configuration
|
|
469
|
-
if (config.connectionPool) {
|
|
470
|
-
if (typeof config.connectionPool.getConnection !== 'function') {
|
|
471
|
-
errors.push('connectionPool must have getConnection method');
|
|
472
|
-
}
|
|
473
|
-
if (typeof config.connectionPool.release !== 'function') {
|
|
474
|
-
errors.push('connectionPool must have release method');
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Validate read-write split configuration
|
|
479
|
-
if (config.readWriteSplit) {
|
|
480
|
-
if (!config.readWriteSplit.primary) {
|
|
481
|
-
errors.push('readWriteSplit must have primary connection');
|
|
482
|
-
}
|
|
483
|
-
if (!Array.isArray(config.readWriteSplit.replicas)) {
|
|
484
|
-
warnings.push('readWriteSplit.replicas should be an array');
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Validate sharding configuration
|
|
489
|
-
if (config.shardRouting) {
|
|
490
|
-
if (!Array.isArray(config.shardRouting.shards) || config.shardRouting.shards.length === 0) {
|
|
491
|
-
errors.push('shardRouting.shards must be a non-empty array');
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// Validate distributed lock configuration
|
|
496
|
-
if (config.distributedLock) {
|
|
497
|
-
if (typeof config.distributedLock.acquire !== 'function') {
|
|
498
|
-
errors.push('distributedLock must have acquire method');
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
return {
|
|
503
|
-
valid: errors.length === 0,
|
|
504
|
-
errors,
|
|
505
|
-
warnings
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Get plugin configuration
|
|
511
|
-
* @returns {Object} Plugin configuration
|
|
512
|
-
* @override
|
|
513
|
-
*/
|
|
514
|
-
getConfig() {
|
|
515
|
-
const baseConfig = super.getConfig();
|
|
516
|
-
return {
|
|
517
|
-
...baseConfig,
|
|
518
|
-
connectionPool: !!this.connectionPool,
|
|
519
|
-
readWriteSplit: !!this.readWriteSplit,
|
|
520
|
-
shardRouting: !!this.shardRouting,
|
|
521
|
-
distributedLock: !!this.distributedLockClient,
|
|
522
|
-
configCenter: !!this.configCenter
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
* Get plugin status
|
|
528
|
-
* @returns {Object} Plugin status information
|
|
529
|
-
* @override
|
|
530
|
-
*/
|
|
531
|
-
getStatus() {
|
|
532
|
-
const baseStatus = super.getStatus();
|
|
533
|
-
return {
|
|
534
|
-
...baseStatus,
|
|
535
|
-
connectionPool: !!this.connectionPool,
|
|
536
|
-
readWriteSplit: !!this.readWriteSplit,
|
|
537
|
-
replicaCount: this.replicaConnections.length,
|
|
538
|
-
shardRouting: !!this.shardRouting,
|
|
539
|
-
distributedLock: !!this.distributedLockClient,
|
|
540
|
-
configCenter: !!this.configCenter
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
}
|