snow-flow 1.1.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.
- package/.env.example +49 -0
- package/.mcp.json +106 -0
- package/.mcp.json.template +106 -0
- package/LICENSE +21 -0
- package/README.md +236 -0
- package/bin/snow-flow +4 -0
- package/bin/snow-flow.js +3 -0
- package/claude-flow +79 -0
- package/claude-flow.bat +18 -0
- package/claude-flow.config.json +20 -0
- package/claude-flow.ps1 +24 -0
- package/dist/agents/app-creator.agent.d.ts +55 -0
- package/dist/agents/app-creator.agent.d.ts.map +1 -0
- package/dist/agents/app-creator.agent.js +1292 -0
- package/dist/agents/app-creator.agent.js.map +1 -0
- package/dist/agents/base-snow-agent.d.ts +63 -0
- package/dist/agents/base-snow-agent.d.ts.map +1 -0
- package/dist/agents/base-snow-agent.js +296 -0
- package/dist/agents/base-snow-agent.js.map +1 -0
- package/dist/agents/script-generator.agent.d.ts +32 -0
- package/dist/agents/script-generator.agent.d.ts.map +1 -0
- package/dist/agents/script-generator.agent.js +772 -0
- package/dist/agents/script-generator.agent.js.map +1 -0
- package/dist/agents/ui-builder.agent.d.ts +50 -0
- package/dist/agents/ui-builder.agent.d.ts.map +1 -0
- package/dist/agents/ui-builder.agent.js +1539 -0
- package/dist/agents/ui-builder.agent.js.map +1 -0
- package/dist/agents/widget-builder.agent.d.ts +32 -0
- package/dist/agents/widget-builder.agent.d.ts.map +1 -0
- package/dist/agents/widget-builder.agent.js +439 -0
- package/dist/agents/widget-builder.agent.js.map +1 -0
- package/dist/agents/workflow-designer.agent.d.ts +31 -0
- package/dist/agents/workflow-designer.agent.d.ts.map +1 -0
- package/dist/agents/workflow-designer.agent.js +583 -0
- package/dist/agents/workflow-designer.agent.js.map +1 -0
- package/dist/api/error-handling.d.ts +214 -0
- package/dist/api/error-handling.d.ts.map +1 -0
- package/dist/api/error-handling.js +594 -0
- package/dist/api/error-handling.js.map +1 -0
- package/dist/api/flow-designer-api.d.ts +167 -0
- package/dist/api/flow-designer-api.d.ts.map +1 -0
- package/dist/api/flow-designer-api.js +555 -0
- package/dist/api/flow-designer-api.js.map +1 -0
- package/dist/api/natural-language-mapper.d.ts +126 -0
- package/dist/api/natural-language-mapper.d.ts.map +1 -0
- package/dist/api/natural-language-mapper.js +498 -0
- package/dist/api/natural-language-mapper.js.map +1 -0
- package/dist/api/performance-optimizer.d.ts +240 -0
- package/dist/api/performance-optimizer.d.ts.map +1 -0
- package/dist/api/performance-optimizer.js +701 -0
- package/dist/api/performance-optimizer.js.map +1 -0
- package/dist/api/transaction-manager.d.ts +189 -0
- package/dist/api/transaction-manager.d.ts.map +1 -0
- package/dist/api/transaction-manager.js +576 -0
- package/dist/api/transaction-manager.js.map +1 -0
- package/dist/cli/deploy-artifact.d.ts +7 -0
- package/dist/cli/deploy-artifact.d.ts.map +1 -0
- package/dist/cli/deploy-artifact.js +279 -0
- package/dist/cli/deploy-artifact.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2057 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/scope-manager.d.ts +75 -0
- package/dist/managers/scope-manager.d.ts.map +1 -0
- package/dist/managers/scope-manager.js +448 -0
- package/dist/managers/scope-manager.js.map +1 -0
- package/dist/mcp/mcp-wrapper.d.ts +8 -0
- package/dist/mcp/mcp-wrapper.d.ts.map +1 -0
- package/dist/mcp/mcp-wrapper.js +77 -0
- package/dist/mcp/mcp-wrapper.js.map +1 -0
- package/dist/mcp/servicenow-automation-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-automation-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-automation-mcp.js +683 -0
- package/dist/mcp/servicenow-automation-mcp.js.map +1 -0
- package/dist/mcp/servicenow-deployment-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-deployment-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-deployment-mcp.js +972 -0
- package/dist/mcp/servicenow-deployment-mcp.js.map +1 -0
- package/dist/mcp/servicenow-flow-composer-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-flow-composer-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-flow-composer-mcp.js +1121 -0
- package/dist/mcp/servicenow-flow-composer-mcp.js.map +1 -0
- package/dist/mcp/servicenow-graph-memory-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-graph-memory-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-graph-memory-mcp.js +703 -0
- package/dist/mcp/servicenow-graph-memory-mcp.js.map +1 -0
- package/dist/mcp/servicenow-integration-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-integration-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-integration-mcp.js +689 -0
- package/dist/mcp/servicenow-integration-mcp.js.map +1 -0
- package/dist/mcp/servicenow-intelligent-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-intelligent-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-intelligent-mcp.js +1138 -0
- package/dist/mcp/servicenow-intelligent-mcp.js.map +1 -0
- package/dist/mcp/servicenow-mcp-server.d.ts +37 -0
- package/dist/mcp/servicenow-mcp-server.d.ts.map +1 -0
- package/dist/mcp/servicenow-mcp-server.js +648 -0
- package/dist/mcp/servicenow-mcp-server.js.map +1 -0
- package/dist/mcp/servicenow-operations-mcp.d.ts +15 -0
- package/dist/mcp/servicenow-operations-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-operations-mcp.js +1287 -0
- package/dist/mcp/servicenow-operations-mcp.js.map +1 -0
- package/dist/mcp/servicenow-platform-development-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-platform-development-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-platform-development-mcp.js +557 -0
- package/dist/mcp/servicenow-platform-development-mcp.js.map +1 -0
- package/dist/mcp/servicenow-progressive-indexer.d.ts +79 -0
- package/dist/mcp/servicenow-progressive-indexer.d.ts.map +1 -0
- package/dist/mcp/servicenow-progressive-indexer.js +320 -0
- package/dist/mcp/servicenow-progressive-indexer.js.map +1 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.js +888 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.js.map +1 -0
- package/dist/mcp/servicenow-security-compliance-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-security-compliance-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-security-compliance-mcp.js +812 -0
- package/dist/mcp/servicenow-security-compliance-mcp.js.map +1 -0
- package/dist/mcp/servicenow-update-set-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-update-set-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-update-set-mcp.js +599 -0
- package/dist/mcp/servicenow-update-set-mcp.js.map +1 -0
- package/dist/mcp/start-all-mcp-servers.d.ts +6 -0
- package/dist/mcp/start-all-mcp-servers.d.ts.map +1 -0
- package/dist/mcp/start-all-mcp-servers.js +65 -0
- package/dist/mcp/start-all-mcp-servers.js.map +1 -0
- package/dist/mcp/start-servicenow-mcp.d.ts +7 -0
- package/dist/mcp/start-servicenow-mcp.d.ts.map +1 -0
- package/dist/mcp/start-servicenow-mcp.js +64 -0
- package/dist/mcp/start-servicenow-mcp.js.map +1 -0
- package/dist/mcp/test-simple-mcp.d.ts +6 -0
- package/dist/mcp/test-simple-mcp.d.ts.map +1 -0
- package/dist/mcp/test-simple-mcp.js +64 -0
- package/dist/mcp/test-simple-mcp.js.map +1 -0
- package/dist/orchestrator/flow-composer.d.ts +269 -0
- package/dist/orchestrator/flow-composer.d.ts.map +1 -0
- package/dist/orchestrator/flow-composer.js +2221 -0
- package/dist/orchestrator/flow-composer.js.map +1 -0
- package/dist/orchestrator/flow-pattern-templates.d.ts +260 -0
- package/dist/orchestrator/flow-pattern-templates.d.ts.map +1 -0
- package/dist/orchestrator/flow-pattern-templates.js +906 -0
- package/dist/orchestrator/flow-pattern-templates.js.map +1 -0
- package/dist/orchestrator/flow-subflow-decision-engine.d.ts +202 -0
- package/dist/orchestrator/flow-subflow-decision-engine.d.ts.map +1 -0
- package/dist/orchestrator/flow-subflow-decision-engine.js +769 -0
- package/dist/orchestrator/flow-subflow-decision-engine.js.map +1 -0
- package/dist/orchestrator/flow-validation-engine.d.ts +145 -0
- package/dist/orchestrator/flow-validation-engine.d.ts.map +1 -0
- package/dist/orchestrator/flow-validation-engine.js +663 -0
- package/dist/orchestrator/flow-validation-engine.js.map +1 -0
- package/dist/orchestrator/snow-orchestrator.d.ts +49 -0
- package/dist/orchestrator/snow-orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/snow-orchestrator.js +235 -0
- package/dist/orchestrator/snow-orchestrator.js.map +1 -0
- package/dist/orchestrator/subflow-creation-handler.d.ts +230 -0
- package/dist/orchestrator/subflow-creation-handler.d.ts.map +1 -0
- package/dist/orchestrator/subflow-creation-handler.js +791 -0
- package/dist/orchestrator/subflow-creation-handler.js.map +1 -0
- package/dist/strategies/global-scope-strategy.d.ts +123 -0
- package/dist/strategies/global-scope-strategy.d.ts.map +1 -0
- package/dist/strategies/global-scope-strategy.js +585 -0
- package/dist/strategies/global-scope-strategy.js.map +1 -0
- package/dist/types/index.d.ts +138 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/servicenow.types.d.ts +260 -0
- package/dist/types/servicenow.types.d.ts.map +1 -0
- package/dist/types/servicenow.types.js +3 -0
- package/dist/types/servicenow.types.js.map +1 -0
- package/dist/types/snow-flow.types.d.ts +114 -0
- package/dist/types/snow-flow.types.d.ts.map +1 -0
- package/dist/types/snow-flow.types.js +3 -0
- package/dist/types/snow-flow.types.js.map +1 -0
- package/dist/utils/action-type-cache.d.ts +66 -0
- package/dist/utils/action-type-cache.d.ts.map +1 -0
- package/dist/utils/action-type-cache.js +237 -0
- package/dist/utils/action-type-cache.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +35 -0
- package/dist/utils/agent-detector.d.ts.map +1 -0
- package/dist/utils/agent-detector.js +353 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/flow-api-discovery.d.ts +151 -0
- package/dist/utils/flow-api-discovery.d.ts.map +1 -0
- package/dist/utils/flow-api-discovery.js +440 -0
- package/dist/utils/flow-api-discovery.js.map +1 -0
- package/dist/utils/flow-xml-generator.d.ts +41 -0
- package/dist/utils/flow-xml-generator.d.ts.map +1 -0
- package/dist/utils/flow-xml-generator.js +258 -0
- package/dist/utils/flow-xml-generator.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +51 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/mcp-auth-middleware.d.ts +58 -0
- package/dist/utils/mcp-auth-middleware.d.ts.map +1 -0
- package/dist/utils/mcp-auth-middleware.js +227 -0
- package/dist/utils/mcp-auth-middleware.js.map +1 -0
- package/dist/utils/mcp-config-manager.d.ts +126 -0
- package/dist/utils/mcp-config-manager.d.ts.map +1 -0
- package/dist/utils/mcp-config-manager.js +209 -0
- package/dist/utils/mcp-config-manager.js.map +1 -0
- package/dist/utils/mcp-server-manager.d.ts +91 -0
- package/dist/utils/mcp-server-manager.d.ts.map +1 -0
- package/dist/utils/mcp-server-manager.js +338 -0
- package/dist/utils/mcp-server-manager.js.map +1 -0
- package/dist/utils/scope-utils.d.ts +72 -0
- package/dist/utils/scope-utils.d.ts.map +1 -0
- package/dist/utils/scope-utils.js +386 -0
- package/dist/utils/scope-utils.js.map +1 -0
- package/dist/utils/servicenow-client.d.ts +233 -0
- package/dist/utils/servicenow-client.d.ts.map +1 -0
- package/dist/utils/servicenow-client.js +1465 -0
- package/dist/utils/servicenow-client.js.map +1 -0
- package/dist/utils/snow-oauth-old.d.ts +65 -0
- package/dist/utils/snow-oauth-old.d.ts.map +1 -0
- package/dist/utils/snow-oauth-old.js +345 -0
- package/dist/utils/snow-oauth-old.js.map +1 -0
- package/dist/utils/snow-oauth.d.ts +85 -0
- package/dist/utils/snow-oauth.d.ts.map +1 -0
- package/dist/utils/snow-oauth.js +512 -0
- package/dist/utils/snow-oauth.js.map +1 -0
- package/dist/utils/template-engine.d.ts +76 -0
- package/dist/utils/template-engine.d.ts.map +1 -0
- package/dist/utils/template-engine.js +391 -0
- package/dist/utils/template-engine.js.map +1 -0
- package/dist/version.d.ts +35 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +72 -0
- package/dist/version.js.map +1 -0
- package/mcp-wrapper.sh +12 -0
- package/package.json +77 -0
- package/reports/swarm-auto-centralized-1752649029776.json +13 -0
- package/scripts/postinstall.js +30 -0
- package/scripts/setup-mcp.js +89 -0
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Performance Optimization and Caching Strategy
|
|
4
|
+
* Advanced caching and performance optimization for ServiceNow API calls
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.PerformanceOptimizer = void 0;
|
|
11
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
class PerformanceOptimizer {
|
|
15
|
+
constructor(client, config) {
|
|
16
|
+
this.cache = new Map();
|
|
17
|
+
this.batchQueue = new Map();
|
|
18
|
+
this.rateLimiter = new Map();
|
|
19
|
+
this.connectionPool = new Map();
|
|
20
|
+
this.client = client;
|
|
21
|
+
this.logger = new logger_js_1.Logger('PerformanceOptimizer');
|
|
22
|
+
this.config = {
|
|
23
|
+
max_size: 1000,
|
|
24
|
+
default_ttl: 300000, // 5 minutes
|
|
25
|
+
cleanup_interval: 60000, // 1 minute
|
|
26
|
+
persistence_enabled: true,
|
|
27
|
+
compression_enabled: true,
|
|
28
|
+
...config
|
|
29
|
+
};
|
|
30
|
+
this.metrics = {
|
|
31
|
+
cache_hit_rate: 0,
|
|
32
|
+
cache_miss_rate: 0,
|
|
33
|
+
average_response_time: 0,
|
|
34
|
+
api_call_count: 0,
|
|
35
|
+
cache_size: 0,
|
|
36
|
+
memory_usage: 0,
|
|
37
|
+
bandwidth_saved: 0
|
|
38
|
+
};
|
|
39
|
+
this.startCleanupTimer();
|
|
40
|
+
this.loadPersistedCache();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Optimized API call with caching and performance monitoring
|
|
44
|
+
*/
|
|
45
|
+
async optimizedAPICall(request) {
|
|
46
|
+
const startTime = Date.now();
|
|
47
|
+
const cacheKey = request.cache_key || this.generateCacheKey(request);
|
|
48
|
+
// Check cache first
|
|
49
|
+
if (request.cacheable) {
|
|
50
|
+
const cached = this.getFromCache(cacheKey);
|
|
51
|
+
if (cached) {
|
|
52
|
+
const responseTime = Date.now() - startTime;
|
|
53
|
+
this.updateMetrics(true, responseTime);
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
data: cached,
|
|
57
|
+
cached: true,
|
|
58
|
+
response_time: responseTime,
|
|
59
|
+
cache_hit: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Apply rate limiting
|
|
64
|
+
if (this.isRateLimited(request.url)) {
|
|
65
|
+
await this.waitForRateLimit(request.url);
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
// Execute API call
|
|
69
|
+
const response = await this.executeAPICall(request);
|
|
70
|
+
const responseTime = Date.now() - startTime;
|
|
71
|
+
// Cache successful responses
|
|
72
|
+
if (request.cacheable && response.success && response.data) {
|
|
73
|
+
this.setInCache(cacheKey, response.data, {
|
|
74
|
+
ttl: this.getTTLForRequest(request),
|
|
75
|
+
tags: this.getTagsForRequest(request)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
this.updateMetrics(false, responseTime);
|
|
79
|
+
return {
|
|
80
|
+
...response,
|
|
81
|
+
cached: false,
|
|
82
|
+
response_time: responseTime,
|
|
83
|
+
cache_hit: false
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const responseTime = Date.now() - startTime;
|
|
88
|
+
this.updateMetrics(false, responseTime);
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: error instanceof Error ? error.message : String(error),
|
|
92
|
+
cached: false,
|
|
93
|
+
response_time: responseTime,
|
|
94
|
+
cache_hit: false
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Batch multiple API requests for better performance
|
|
100
|
+
*/
|
|
101
|
+
async batchAPIRequests(requests) {
|
|
102
|
+
const batchId = this.generateBatchId();
|
|
103
|
+
const batchRequest = {
|
|
104
|
+
id: batchId,
|
|
105
|
+
requests: requests.sort((a, b) => b.priority - a.priority),
|
|
106
|
+
priority: 'medium',
|
|
107
|
+
timeout: 30000,
|
|
108
|
+
retry_count: 0
|
|
109
|
+
};
|
|
110
|
+
this.batchQueue.set(batchId, batchRequest);
|
|
111
|
+
try {
|
|
112
|
+
// Group requests by type for optimization
|
|
113
|
+
const groupedRequests = this.groupRequestsByType(requests);
|
|
114
|
+
const results = [];
|
|
115
|
+
// Execute groups in parallel
|
|
116
|
+
const groupPromises = Object.entries(groupedRequests).map(async ([type, groupRequests]) => {
|
|
117
|
+
return await this.executeBatchGroup(groupRequests, type);
|
|
118
|
+
});
|
|
119
|
+
const groupResults = await Promise.all(groupPromises);
|
|
120
|
+
// Flatten results
|
|
121
|
+
for (const groupResult of groupResults) {
|
|
122
|
+
results.push(...groupResult);
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
this.batchQueue.delete(batchId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Preload commonly accessed data
|
|
132
|
+
*/
|
|
133
|
+
async preloadData(preloadConfig) {
|
|
134
|
+
const preloadTasks = [];
|
|
135
|
+
if (preloadConfig.action_types) {
|
|
136
|
+
preloadTasks.push(this.preloadActionTypes());
|
|
137
|
+
}
|
|
138
|
+
if (preloadConfig.trigger_types) {
|
|
139
|
+
preloadTasks.push(this.preloadTriggerTypes());
|
|
140
|
+
}
|
|
141
|
+
if (preloadConfig.flow_templates) {
|
|
142
|
+
preloadTasks.push(this.preloadFlowTemplates());
|
|
143
|
+
}
|
|
144
|
+
if (preloadConfig.user_preferences) {
|
|
145
|
+
preloadTasks.push(this.preloadUserPreferences());
|
|
146
|
+
}
|
|
147
|
+
await Promise.all(preloadTasks);
|
|
148
|
+
this.logger.info('Data preloading completed');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Analyze performance and provide optimization suggestions
|
|
152
|
+
*/
|
|
153
|
+
analyzePerformance() {
|
|
154
|
+
const bottlenecks = [];
|
|
155
|
+
const optimizationHints = [];
|
|
156
|
+
// Analyze cache hit rate
|
|
157
|
+
if (this.metrics.cache_hit_rate < 0.5) {
|
|
158
|
+
bottlenecks.push('Low cache hit rate');
|
|
159
|
+
optimizationHints.push({
|
|
160
|
+
type: 'cache',
|
|
161
|
+
description: 'Increase cache TTL for frequently accessed data',
|
|
162
|
+
estimated_improvement: 0.3,
|
|
163
|
+
implementation_complexity: 'low'
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Analyze response times
|
|
167
|
+
if (this.metrics.average_response_time > 2000) {
|
|
168
|
+
bottlenecks.push('High response times');
|
|
169
|
+
optimizationHints.push({
|
|
170
|
+
type: 'parallel',
|
|
171
|
+
description: 'Implement parallel processing for independent requests',
|
|
172
|
+
estimated_improvement: 0.5,
|
|
173
|
+
implementation_complexity: 'medium'
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// Analyze cache size
|
|
177
|
+
if (this.cache.size > this.config.max_size * 0.8) {
|
|
178
|
+
bottlenecks.push('Cache nearing capacity');
|
|
179
|
+
optimizationHints.push({
|
|
180
|
+
type: 'compress',
|
|
181
|
+
description: 'Enable compression for cached data',
|
|
182
|
+
estimated_improvement: 0.4,
|
|
183
|
+
implementation_complexity: 'medium'
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Analyze API call patterns
|
|
187
|
+
const batchableRequests = this.identifyBatchableRequests();
|
|
188
|
+
if (batchableRequests.length > 0) {
|
|
189
|
+
optimizationHints.push({
|
|
190
|
+
type: 'batch',
|
|
191
|
+
description: `Batch ${batchableRequests.length} similar requests`,
|
|
192
|
+
estimated_improvement: 0.6,
|
|
193
|
+
implementation_complexity: 'high'
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
metrics: this.metrics,
|
|
198
|
+
bottlenecks,
|
|
199
|
+
optimization_hints: optimizationHints
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Implement adaptive caching based on usage patterns
|
|
204
|
+
*/
|
|
205
|
+
optimizeCaching() {
|
|
206
|
+
const cacheAnalysis = this.analyzeCacheUsage();
|
|
207
|
+
// Adjust TTL based on access patterns
|
|
208
|
+
for (const [key, entry] of this.cache) {
|
|
209
|
+
const accessFrequency = entry.access_count / (Date.now() - entry.timestamp.getTime());
|
|
210
|
+
if (accessFrequency > 0.01) { // Frequently accessed
|
|
211
|
+
entry.ttl = this.config.default_ttl * 2;
|
|
212
|
+
}
|
|
213
|
+
else if (accessFrequency < 0.001) { // Rarely accessed
|
|
214
|
+
entry.ttl = this.config.default_ttl * 0.5;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Implement cache warming for predicted requests
|
|
218
|
+
this.warmCache(cacheAnalysis.predicted_requests);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get from cache with LRU eviction
|
|
222
|
+
*/
|
|
223
|
+
getFromCache(key) {
|
|
224
|
+
const entry = this.cache.get(key);
|
|
225
|
+
if (!entry) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
// Check if expired
|
|
229
|
+
if (Date.now() - entry.timestamp.getTime() > entry.ttl) {
|
|
230
|
+
this.cache.delete(key);
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
// Update access statistics
|
|
234
|
+
entry.access_count++;
|
|
235
|
+
entry.last_accessed = new Date();
|
|
236
|
+
return entry.value;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Set in cache with size management
|
|
240
|
+
*/
|
|
241
|
+
setInCache(key, value, options = {}) {
|
|
242
|
+
// Check if cache is full
|
|
243
|
+
if (this.cache.size >= this.config.max_size) {
|
|
244
|
+
this.evictLeastRecent();
|
|
245
|
+
}
|
|
246
|
+
const entry = {
|
|
247
|
+
key,
|
|
248
|
+
value,
|
|
249
|
+
timestamp: new Date(),
|
|
250
|
+
ttl: options.ttl || this.config.default_ttl,
|
|
251
|
+
access_count: 1,
|
|
252
|
+
last_accessed: new Date(),
|
|
253
|
+
tags: options.tags || [],
|
|
254
|
+
size: this.estimateSize(value)
|
|
255
|
+
};
|
|
256
|
+
this.cache.set(key, entry);
|
|
257
|
+
this.updateCacheMetrics();
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Execute API call with connection pooling
|
|
261
|
+
*/
|
|
262
|
+
async executeAPICall(request) {
|
|
263
|
+
const connection = this.getPooledConnection(request.url);
|
|
264
|
+
try {
|
|
265
|
+
let response;
|
|
266
|
+
switch (request.method) {
|
|
267
|
+
case 'GET':
|
|
268
|
+
response = await this.client.getRecords(this.extractTable(request.url), request.data);
|
|
269
|
+
break;
|
|
270
|
+
case 'POST':
|
|
271
|
+
response = await this.client.createRecord(this.extractTable(request.url), request.data);
|
|
272
|
+
break;
|
|
273
|
+
case 'PUT':
|
|
274
|
+
case 'PATCH':
|
|
275
|
+
response = await this.client.updateRecord(this.extractTable(request.url), request.data.sys_id, request.data);
|
|
276
|
+
break;
|
|
277
|
+
case 'DELETE':
|
|
278
|
+
response = await this.client.deleteRecord(this.extractTable(request.url), request.data.sys_id);
|
|
279
|
+
break;
|
|
280
|
+
default:
|
|
281
|
+
throw new Error(`Unsupported method: ${request.method}`);
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
success: response.success,
|
|
285
|
+
data: response.data,
|
|
286
|
+
error: response.error
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
this.returnPooledConnection(request.url, connection);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Group requests by type for batch processing
|
|
295
|
+
*/
|
|
296
|
+
groupRequestsByType(requests) {
|
|
297
|
+
const groups = {};
|
|
298
|
+
for (const request of requests) {
|
|
299
|
+
const type = `${request.method}_${this.extractTable(request.url)}`;
|
|
300
|
+
if (!groups[type]) {
|
|
301
|
+
groups[type] = [];
|
|
302
|
+
}
|
|
303
|
+
groups[type].push(request);
|
|
304
|
+
}
|
|
305
|
+
return groups;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Execute batch group with parallel processing
|
|
309
|
+
*/
|
|
310
|
+
async executeBatchGroup(requests, type) {
|
|
311
|
+
const batchSize = this.getBatchSizeForType(type);
|
|
312
|
+
const results = [];
|
|
313
|
+
// Process requests in batches
|
|
314
|
+
for (let i = 0; i < requests.length; i += batchSize) {
|
|
315
|
+
const batch = requests.slice(i, i + batchSize);
|
|
316
|
+
const batchPromises = batch.map(request => this.optimizedAPICall(request));
|
|
317
|
+
const batchResults = await Promise.all(batchPromises);
|
|
318
|
+
results.push(...batchResults);
|
|
319
|
+
}
|
|
320
|
+
return results;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Preload action types
|
|
324
|
+
*/
|
|
325
|
+
async preloadActionTypes() {
|
|
326
|
+
const request = {
|
|
327
|
+
id: 'preload_action_types',
|
|
328
|
+
method: 'GET',
|
|
329
|
+
url: '/api/now/table/sys_hub_action_type_base',
|
|
330
|
+
cacheable: true,
|
|
331
|
+
priority: 1
|
|
332
|
+
};
|
|
333
|
+
await this.optimizedAPICall(request);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Preload trigger types
|
|
337
|
+
*/
|
|
338
|
+
async preloadTriggerTypes() {
|
|
339
|
+
const request = {
|
|
340
|
+
id: 'preload_trigger_types',
|
|
341
|
+
method: 'GET',
|
|
342
|
+
url: '/api/now/table/sys_hub_trigger_type',
|
|
343
|
+
cacheable: true,
|
|
344
|
+
priority: 1
|
|
345
|
+
};
|
|
346
|
+
await this.optimizedAPICall(request);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Preload flow templates
|
|
350
|
+
*/
|
|
351
|
+
async preloadFlowTemplates() {
|
|
352
|
+
const request = {
|
|
353
|
+
id: 'preload_flow_templates',
|
|
354
|
+
method: 'GET',
|
|
355
|
+
url: '/api/now/table/sys_hub_flow_template',
|
|
356
|
+
cacheable: true,
|
|
357
|
+
priority: 1
|
|
358
|
+
};
|
|
359
|
+
await this.optimizedAPICall(request);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Preload user preferences
|
|
363
|
+
*/
|
|
364
|
+
async preloadUserPreferences() {
|
|
365
|
+
const request = {
|
|
366
|
+
id: 'preload_user_preferences',
|
|
367
|
+
method: 'GET',
|
|
368
|
+
url: '/api/now/table/sys_user_preference',
|
|
369
|
+
cacheable: true,
|
|
370
|
+
priority: 1
|
|
371
|
+
};
|
|
372
|
+
await this.optimizedAPICall(request);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Analyze cache usage patterns
|
|
376
|
+
*/
|
|
377
|
+
analyzeCacheUsage() {
|
|
378
|
+
const sortedEntries = Array.from(this.cache.entries())
|
|
379
|
+
.sort((a, b) => b[1].access_count - a[1].access_count);
|
|
380
|
+
const mostAccessed = sortedEntries.slice(0, 10).map(([key]) => key);
|
|
381
|
+
const leastAccessed = sortedEntries.slice(-10).map(([key]) => key);
|
|
382
|
+
// Predict likely requests based on patterns
|
|
383
|
+
const predictedRequests = this.predictLikelyRequests(mostAccessed);
|
|
384
|
+
return {
|
|
385
|
+
most_accessed: mostAccessed,
|
|
386
|
+
least_accessed: leastAccessed,
|
|
387
|
+
predicted_requests: predictedRequests
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Warm cache with predicted requests
|
|
392
|
+
*/
|
|
393
|
+
async warmCache(predictedRequests) {
|
|
394
|
+
const warmingTasks = predictedRequests.map(async (cacheKey) => {
|
|
395
|
+
if (!this.cache.has(cacheKey)) {
|
|
396
|
+
const request = this.reconstructRequestFromCacheKey(cacheKey);
|
|
397
|
+
if (request) {
|
|
398
|
+
await this.optimizedAPICall(request);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
await Promise.all(warmingTasks);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Evict least recently used entries
|
|
406
|
+
*/
|
|
407
|
+
evictLeastRecent() {
|
|
408
|
+
const entries = Array.from(this.cache.entries())
|
|
409
|
+
.sort((a, b) => a[1].last_accessed.getTime() - b[1].last_accessed.getTime());
|
|
410
|
+
const entriesToEvict = entries.slice(0, Math.ceil(this.config.max_size * 0.1));
|
|
411
|
+
for (const [key] of entriesToEvict) {
|
|
412
|
+
this.cache.delete(key);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Update performance metrics
|
|
417
|
+
*/
|
|
418
|
+
updateMetrics(cacheHit, responseTime) {
|
|
419
|
+
this.metrics.api_call_count++;
|
|
420
|
+
if (cacheHit) {
|
|
421
|
+
this.metrics.cache_hit_rate = (this.metrics.cache_hit_rate * (this.metrics.api_call_count - 1) + 1) / this.metrics.api_call_count;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
this.metrics.cache_miss_rate = (this.metrics.cache_miss_rate * (this.metrics.api_call_count - 1) + 1) / this.metrics.api_call_count;
|
|
425
|
+
}
|
|
426
|
+
this.metrics.average_response_time = (this.metrics.average_response_time * (this.metrics.api_call_count - 1) + responseTime) / this.metrics.api_call_count;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Update cache metrics
|
|
430
|
+
*/
|
|
431
|
+
updateCacheMetrics() {
|
|
432
|
+
this.metrics.cache_size = this.cache.size;
|
|
433
|
+
this.metrics.memory_usage = Array.from(this.cache.values())
|
|
434
|
+
.reduce((total, entry) => total + entry.size, 0);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Generate cache key for request
|
|
438
|
+
*/
|
|
439
|
+
generateCacheKey(request) {
|
|
440
|
+
const keyParts = [
|
|
441
|
+
request.method,
|
|
442
|
+
request.url,
|
|
443
|
+
JSON.stringify(request.data),
|
|
444
|
+
JSON.stringify(request.headers)
|
|
445
|
+
];
|
|
446
|
+
return Buffer.from(keyParts.join('|')).toString('base64');
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Get TTL for specific request type
|
|
450
|
+
*/
|
|
451
|
+
getTTLForRequest(request) {
|
|
452
|
+
const url = request.url.toLowerCase();
|
|
453
|
+
if (url.includes('action_type') || url.includes('trigger_type')) {
|
|
454
|
+
return 3600000; // 1 hour for metadata
|
|
455
|
+
}
|
|
456
|
+
if (url.includes('flow_template')) {
|
|
457
|
+
return 1800000; // 30 minutes for templates
|
|
458
|
+
}
|
|
459
|
+
if (url.includes('user_preference')) {
|
|
460
|
+
return 600000; // 10 minutes for preferences
|
|
461
|
+
}
|
|
462
|
+
return this.config.default_ttl;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Get tags for request
|
|
466
|
+
*/
|
|
467
|
+
getTagsForRequest(request) {
|
|
468
|
+
const tags = [];
|
|
469
|
+
const url = request.url.toLowerCase();
|
|
470
|
+
if (url.includes('action_type'))
|
|
471
|
+
tags.push('action_type');
|
|
472
|
+
if (url.includes('trigger_type'))
|
|
473
|
+
tags.push('trigger_type');
|
|
474
|
+
if (url.includes('flow'))
|
|
475
|
+
tags.push('flow');
|
|
476
|
+
if (url.includes('user'))
|
|
477
|
+
tags.push('user');
|
|
478
|
+
return tags;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Estimate size of cached value
|
|
482
|
+
*/
|
|
483
|
+
estimateSize(value) {
|
|
484
|
+
return JSON.stringify(value).length * 2; // Rough estimate
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Extract table name from URL
|
|
488
|
+
*/
|
|
489
|
+
extractTable(url) {
|
|
490
|
+
const match = url.match(/\/table\/([^\/\?]+)/);
|
|
491
|
+
return match ? match[1] : 'unknown';
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Get batch size for request type
|
|
495
|
+
*/
|
|
496
|
+
getBatchSizeForType(type) {
|
|
497
|
+
if (type.includes('GET'))
|
|
498
|
+
return 10;
|
|
499
|
+
if (type.includes('POST'))
|
|
500
|
+
return 5;
|
|
501
|
+
if (type.includes('PUT') || type.includes('PATCH'))
|
|
502
|
+
return 3;
|
|
503
|
+
if (type.includes('DELETE'))
|
|
504
|
+
return 3;
|
|
505
|
+
return 5;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Check if request is rate limited
|
|
509
|
+
*/
|
|
510
|
+
isRateLimited(url) {
|
|
511
|
+
const domain = this.extractDomain(url);
|
|
512
|
+
const lastRequest = this.rateLimiter.get(domain);
|
|
513
|
+
if (!lastRequest)
|
|
514
|
+
return false;
|
|
515
|
+
const timeSinceLastRequest = Date.now() - lastRequest;
|
|
516
|
+
return timeSinceLastRequest < 100; // 100ms rate limit
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Wait for rate limit to clear
|
|
520
|
+
*/
|
|
521
|
+
async waitForRateLimit(url) {
|
|
522
|
+
const domain = this.extractDomain(url);
|
|
523
|
+
const lastRequest = this.rateLimiter.get(domain);
|
|
524
|
+
if (lastRequest) {
|
|
525
|
+
const waitTime = 100 - (Date.now() - lastRequest);
|
|
526
|
+
if (waitTime > 0) {
|
|
527
|
+
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
this.rateLimiter.set(domain, Date.now());
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Extract domain from URL
|
|
534
|
+
*/
|
|
535
|
+
extractDomain(url) {
|
|
536
|
+
try {
|
|
537
|
+
return new URL(url).hostname;
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
return 'default';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Get pooled connection
|
|
545
|
+
*/
|
|
546
|
+
getPooledConnection(url) {
|
|
547
|
+
const domain = this.extractDomain(url);
|
|
548
|
+
return this.connectionPool.get(domain) || {};
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Return pooled connection
|
|
552
|
+
*/
|
|
553
|
+
returnPooledConnection(url, connection) {
|
|
554
|
+
const domain = this.extractDomain(url);
|
|
555
|
+
this.connectionPool.set(domain, connection);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Identify batchable requests
|
|
559
|
+
*/
|
|
560
|
+
identifyBatchableRequests() {
|
|
561
|
+
// Implementation would analyze request patterns
|
|
562
|
+
return [];
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Predict likely requests based on patterns
|
|
566
|
+
*/
|
|
567
|
+
predictLikelyRequests(mostAccessed) {
|
|
568
|
+
// Implementation would use ML or pattern analysis
|
|
569
|
+
return mostAccessed.slice(0, 5);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Reconstruct request from cache key
|
|
573
|
+
*/
|
|
574
|
+
reconstructRequestFromCacheKey(cacheKey) {
|
|
575
|
+
try {
|
|
576
|
+
const decoded = Buffer.from(cacheKey, 'base64').toString();
|
|
577
|
+
const [method, url, data, headers] = decoded.split('|');
|
|
578
|
+
return {
|
|
579
|
+
id: 'reconstructed',
|
|
580
|
+
method: method,
|
|
581
|
+
url,
|
|
582
|
+
data: JSON.parse(data),
|
|
583
|
+
headers: JSON.parse(headers),
|
|
584
|
+
cacheable: true,
|
|
585
|
+
priority: 1
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Start cleanup timer
|
|
594
|
+
*/
|
|
595
|
+
startCleanupTimer() {
|
|
596
|
+
this.cleanupTimer = setInterval(() => {
|
|
597
|
+
this.cleanupExpiredEntries();
|
|
598
|
+
}, this.config.cleanup_interval);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Cleanup expired entries
|
|
602
|
+
*/
|
|
603
|
+
cleanupExpiredEntries() {
|
|
604
|
+
const now = Date.now();
|
|
605
|
+
const expiredKeys = [];
|
|
606
|
+
for (const [key, entry] of this.cache) {
|
|
607
|
+
if (now - entry.timestamp.getTime() > entry.ttl) {
|
|
608
|
+
expiredKeys.push(key);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
for (const key of expiredKeys) {
|
|
612
|
+
this.cache.delete(key);
|
|
613
|
+
}
|
|
614
|
+
if (expiredKeys.length > 0) {
|
|
615
|
+
this.logger.debug(`Cleaned up ${expiredKeys.length} expired cache entries`);
|
|
616
|
+
this.updateCacheMetrics();
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Load persisted cache
|
|
621
|
+
*/
|
|
622
|
+
loadPersistedCache() {
|
|
623
|
+
if (!this.config.persistence_enabled)
|
|
624
|
+
return;
|
|
625
|
+
try {
|
|
626
|
+
const cacheFile = path_1.default.join(process.cwd(), '.snow-flow', 'cache', 'performance_cache.json');
|
|
627
|
+
if (fs_1.default.existsSync(cacheFile)) {
|
|
628
|
+
const cacheData = JSON.parse(fs_1.default.readFileSync(cacheFile, 'utf-8'));
|
|
629
|
+
for (const [key, entry] of Object.entries(cacheData)) {
|
|
630
|
+
this.cache.set(key, {
|
|
631
|
+
...entry,
|
|
632
|
+
timestamp: new Date(entry.timestamp),
|
|
633
|
+
last_accessed: new Date(entry.last_accessed)
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
this.logger.info(`Loaded ${this.cache.size} entries from persisted cache`);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
this.logger.warn('Failed to load persisted cache:', error);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Save cache to disk
|
|
645
|
+
*/
|
|
646
|
+
saveCacheToDisk() {
|
|
647
|
+
if (!this.config.persistence_enabled)
|
|
648
|
+
return;
|
|
649
|
+
try {
|
|
650
|
+
const cacheDir = path_1.default.join(process.cwd(), '.snow-flow', 'cache');
|
|
651
|
+
if (!fs_1.default.existsSync(cacheDir)) {
|
|
652
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
653
|
+
}
|
|
654
|
+
const cacheFile = path_1.default.join(cacheDir, 'performance_cache.json');
|
|
655
|
+
const cacheData = Object.fromEntries(this.cache.entries());
|
|
656
|
+
fs_1.default.writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2));
|
|
657
|
+
this.logger.info(`Saved ${this.cache.size} entries to persisted cache`);
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
this.logger.warn('Failed to save cache to disk:', error);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Clear cache
|
|
665
|
+
*/
|
|
666
|
+
clearCache(tags) {
|
|
667
|
+
if (!tags || tags.length === 0) {
|
|
668
|
+
this.cache.clear();
|
|
669
|
+
this.logger.info('Cleared all cache entries');
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
const keysToDelete = [];
|
|
673
|
+
for (const [key, entry] of this.cache) {
|
|
674
|
+
if (entry.tags.some(tag => tags.includes(tag))) {
|
|
675
|
+
keysToDelete.push(key);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
for (const key of keysToDelete) {
|
|
679
|
+
this.cache.delete(key);
|
|
680
|
+
}
|
|
681
|
+
this.logger.info(`Cleared ${keysToDelete.length} cache entries with tags: ${tags.join(', ')}`);
|
|
682
|
+
}
|
|
683
|
+
this.updateCacheMetrics();
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Destroy optimizer and cleanup
|
|
687
|
+
*/
|
|
688
|
+
destroy() {
|
|
689
|
+
if (this.cleanupTimer) {
|
|
690
|
+
clearInterval(this.cleanupTimer);
|
|
691
|
+
}
|
|
692
|
+
this.saveCacheToDisk();
|
|
693
|
+
this.cache.clear();
|
|
694
|
+
this.batchQueue.clear();
|
|
695
|
+
this.rateLimiter.clear();
|
|
696
|
+
this.connectionPool.clear();
|
|
697
|
+
this.logger.info('Performance optimizer destroyed');
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
exports.PerformanceOptimizer = PerformanceOptimizer;
|
|
701
|
+
//# sourceMappingURL=performance-optimizer.js.map
|