snow-flow 2.0.2 → 2.0.3
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/{.claude/mcp-config.json → .mcp.json} +13 -12
- package/.releaserc.json +47 -0
- package/README.md +6 -0
- package/package.json +1 -1
- package/.claude/claude-settings.json +0 -15
- package/.claude/commands/analysis/README.md +0 -9
- package/.claude/commands/automation/README.md +0 -9
- package/.claude/commands/github/README.md +0 -11
- package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
- package/.claude/commands/hooks/README.md +0 -11
- package/.claude/commands/monitoring/README.md +0 -9
- package/.claude/commands/optimization/README.md +0 -9
- package/.claude/commands/training/README.md +0 -9
- package/.claude/commands/workflows/README.md +0 -9
- package/.claude/config.json +0 -36
- package/.claude/helpers/github-setup.sh +0 -28
- package/.claude/helpers/quick-start.sh +0 -19
- package/.claude/helpers/setup-mcp.sh +0 -18
- package/.claude/settings.json +0 -114
- package/.claude/settings.local.json +0 -33
- package/.claude-flow/metrics/agent-metrics.json +0 -1
- package/.claude-flow/metrics/performance.json +0 -9
- package/.claude-flow/metrics/system-metrics.json +0 -15986
- package/.claude-flow/metrics/task-metrics.json +0 -10
- package/.roo/README.md +0 -402
- package/.roo/mcp-list.txt +0 -257
- package/.roo/mcp.json +0 -32
- package/.roo/workflows/basic-tdd.json +0 -32
- package/.roomodes +0 -201
- package/CLAUDE.md +0 -393
- package/bin/snow-flow.js +0 -3
- package/dist/cli.js.bak +0 -2052
- package/dist/config/snow-flow-config.d.ts +0 -1492
- package/dist/config/snow-flow-config.js +0 -938
- package/scripts/create-env.js +0 -91
- package/scripts/postinstall.js +0 -30
- package/scripts/register-mcp-servers.js +0 -210
- package/scripts/reset-mcp-servers.js +0 -246
- package/scripts/setup-mcp.js +0 -106
- package/scripts/update-version.js +0 -31
- package/src/agents/README.md +0 -192
- package/src/agents/base-agent.ts +0 -251
- package/src/agents/coordinator.ts +0 -971
- package/src/agents/index.ts +0 -18
- package/src/agents/queen-403-handler.ts +0 -230
- package/src/agents/queen-agent.ts +0 -1399
- package/src/agents/script-writer-agent.ts +0 -769
- package/src/agents/security-agent.ts +0 -726
- package/src/agents/widget-creator-agent.ts +0 -568
- package/src/api/error-handling.ts +0 -1758
- package/src/api/natural-language-mapper.ts +0 -630
- package/src/api/performance-optimizer.ts +0 -891
- package/src/api/transaction-manager.ts +0 -754
- package/src/cli/deploy-artifact.ts +0 -304
- package/src/cli/snow-flow-cli-integration.ts +0 -434
- package/src/cli.ts +0 -4455
- package/src/cli.ts.bak +0 -5616
- package/src/compliance/advanced-compliance-system.ts +0 -1268
- package/src/compliance/index.ts +0 -19
- package/src/config/snow-flow-config.ts +0 -1019
- package/src/documentation/index.ts +0 -16
- package/src/documentation/self-documenting-system.ts +0 -1421
- package/src/dynamic-version.ts +0 -44
- package/src/healing/index.ts +0 -20
- package/src/healing/self-healing-system.ts +0 -1435
- package/src/health/README.md +0 -161
- package/src/health/system-health.ts +0 -995
- package/src/index.ts +0 -60
- package/src/intelligence/acl-analyzer.ts +0 -377
- package/src/intelligence/auto-resolution-engine.ts +0 -643
- package/src/intelligence/gap-analysis-engine.ts +0 -488
- package/src/intelligence/manual-instructions-generator.ts +0 -744
- package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
- package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
- package/src/intelligence/performance-recommendations-engine.ts +0 -1223
- package/src/intelligence/requirements-analyzer.ts +0 -1148
- package/src/intelligence/task-analyzer.ts +0 -628
- package/src/managers/scope-manager.ts +0 -555
- package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
- package/src/mcp/base-mcp-server.ts +0 -660
- package/src/mcp/http-transport-wrapper.ts +0 -426
- package/src/mcp/service-discovery-client.ts +0 -312
- package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
- package/src/mcp/servicenow-automation-mcp.ts +0 -838
- package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
- package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
- package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
- package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
- package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
- package/src/mcp/servicenow-integration-mcp.ts +0 -819
- package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
- package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
- package/src/mcp/servicenow-mcp-server.ts +0 -728
- package/src/mcp/servicenow-memory-mcp.ts +0 -474
- package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
- package/src/mcp/servicenow-operations-mcp.ts +0 -3384
- package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
- package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
- package/src/mcp/servicenow-progressive-indexer.ts +0 -370
- package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
- package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
- package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
- package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
- package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
- package/src/mcp/servicenow-update-set-mcp.ts +0 -811
- package/src/mcp/shared/agent-context-provider.ts +0 -365
- package/src/mcp/shared/base-mcp-server.ts +0 -2463
- package/src/mcp/shared/mcp-memory-manager.ts +0 -540
- package/src/mcp/shared/mcp-resource-manager.ts +0 -367
- package/src/mcp/snow-flow-mcp.ts +0 -911
- package/src/mcp/start-all-mcp-servers.ts +0 -102
- package/src/mcp/start-servicenow-mcp.ts +0 -67
- package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
- package/src/monitoring/performance-tracker.ts +0 -777
- package/src/optimization/cost-optimization-engine.ts +0 -1125
- package/src/optimization/index.ts +0 -10
- package/src/queen/README.md +0 -403
- package/src/queen/agent-factory.ts +0 -574
- package/src/queen/index.ts +0 -94
- package/src/queen/mcp-execution-bridge.ts +0 -681
- package/src/queen/neural-learning.ts +0 -319
- package/src/queen/parallel-agent-engine.ts +0 -848
- package/src/queen/queen-memory-system.ts +0 -490
- package/src/queen/queen-memory.ts +0 -456
- package/src/queen/servicenow-queen.ts +0 -1029
- package/src/queen/types.ts +0 -87
- package/src/rollback/smart-rollback-system.ts +0 -866
- package/src/schemas/deployment.schema.json +0 -58
- package/src/schemas/flow.schema.json +0 -79
- package/src/schemas/widget.schema.json +0 -72
- package/src/snow-flow-system.ts +0 -541
- package/src/sparc/sparc-help.ts +0 -49
- package/src/sparc/team-sparc.ts +0 -88
- package/src/strategies/global-scope-strategy.ts +0 -736
- package/src/templates/base/application.template.json +0 -45
- package/src/templates/base/business_rule.template.json +0 -33
- package/src/templates/base/script_include.template.json +0 -18
- package/src/templates/base/table.template.json +0 -64
- package/src/templates/base/widget.template.json +0 -25
- package/src/templates/patterns/composite.incident-management.template.json +0 -140
- package/src/templates/patterns/widget.dashboard.template.json +0 -238
- package/src/templates/patterns/widget.datatable.template.json +0 -292
- package/src/testing/integration-test-suite.ts +0 -1276
- package/src/types/index.ts +0 -183
- package/src/types/neo4j-driver.d.ts +0 -23
- package/src/types/servicenow.types.ts +0 -307
- package/src/types/snow-flow.types.ts +0 -186
- package/src/types/todo.types.ts +0 -70
- package/src/utils/action-type-cache.ts +0 -286
- package/src/utils/agent-detector.ts +0 -573
- package/src/utils/artifact-tracker.ts +0 -379
- package/src/utils/dependency-detector.ts +0 -233
- package/src/utils/deployment-metadata-handler.ts +0 -518
- package/src/utils/error-recovery.ts +0 -680
- package/src/utils/logger.ts +0 -60
- package/src/utils/mcp-auth-middleware.ts +0 -262
- package/src/utils/mcp-config-manager.ts +0 -270
- package/src/utils/mcp-server-manager.ts +0 -446
- package/src/utils/mcp-tool-registry.ts +0 -298
- package/src/utils/migrate-snow-flow.ts +0 -98
- package/src/utils/oauth-html-templates.ts +0 -188
- package/src/utils/scope-utils.ts +0 -443
- package/src/utils/servicenow-client.ts +0 -3321
- package/src/utils/servicenow-id-generator.ts +0 -181
- package/src/utils/snow-memory-manager.ts +0 -605
- package/src/utils/snow-oauth.ts +0 -797
- package/src/utils/template-engine.ts +0 -463
- package/src/utils/theme-manager.ts +0 -295
- package/src/utils/unified-auth-store.ts +0 -222
- package/src/utils/update-set-importer.ts +0 -422
- package/src/utils/update-set-xml-packager.ts +0 -371
- package/src/utils/widget-template-generator.ts +0 -1744
- package/src/version.ts +0 -1950
|
@@ -1,891 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Performance Optimization and Caching Strategy
|
|
3
|
-
* Advanced caching and performance optimization for ServiceNow API calls
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ServiceNowClient } from '../utils/servicenow-client.js';
|
|
7
|
-
import { Logger } from '../utils/logger.js';
|
|
8
|
-
import fs from 'fs';
|
|
9
|
-
import path from 'path';
|
|
10
|
-
import os from 'os';
|
|
11
|
-
|
|
12
|
-
export interface CacheEntry<T> {
|
|
13
|
-
key: string;
|
|
14
|
-
value: T;
|
|
15
|
-
timestamp: Date;
|
|
16
|
-
ttl: number;
|
|
17
|
-
access_count: number;
|
|
18
|
-
last_accessed: Date;
|
|
19
|
-
tags: string[];
|
|
20
|
-
size: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface CacheConfig {
|
|
24
|
-
max_size: number;
|
|
25
|
-
default_ttl: number;
|
|
26
|
-
cleanup_interval: number;
|
|
27
|
-
persistence_enabled: boolean;
|
|
28
|
-
compression_enabled: boolean;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface PerformanceMetrics {
|
|
32
|
-
cache_hit_rate: number;
|
|
33
|
-
cache_miss_rate: number;
|
|
34
|
-
average_response_time: number;
|
|
35
|
-
api_call_count: number;
|
|
36
|
-
cache_size: number;
|
|
37
|
-
memory_usage: number;
|
|
38
|
-
bandwidth_saved: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface OptimizationHint {
|
|
42
|
-
type: 'batch' | 'cache' | 'compress' | 'parallel' | 'lazy';
|
|
43
|
-
description: string;
|
|
44
|
-
estimated_improvement: number;
|
|
45
|
-
implementation_complexity: 'low' | 'medium' | 'high';
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface BatchRequest {
|
|
49
|
-
id: string;
|
|
50
|
-
requests: APIRequest[];
|
|
51
|
-
priority: 'high' | 'medium' | 'low';
|
|
52
|
-
timeout: number;
|
|
53
|
-
retry_count: number;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface APIRequest {
|
|
57
|
-
id: string;
|
|
58
|
-
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
59
|
-
url: string;
|
|
60
|
-
data?: any;
|
|
61
|
-
headers?: Record<string, string>;
|
|
62
|
-
cache_key?: string;
|
|
63
|
-
cacheable: boolean;
|
|
64
|
-
priority: number;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface APIResponse<T> {
|
|
68
|
-
success: boolean;
|
|
69
|
-
data?: T;
|
|
70
|
-
error?: string;
|
|
71
|
-
cached: boolean;
|
|
72
|
-
response_time: number;
|
|
73
|
-
cache_hit: boolean;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export class PerformanceOptimizer {
|
|
77
|
-
private client: ServiceNowClient;
|
|
78
|
-
private logger: Logger;
|
|
79
|
-
private cache: Map<string, CacheEntry<any>> = new Map();
|
|
80
|
-
private config: CacheConfig;
|
|
81
|
-
private metrics: PerformanceMetrics;
|
|
82
|
-
private cleanupTimer?: NodeJS.Timeout;
|
|
83
|
-
private batchQueue: Map<string, BatchRequest> = new Map();
|
|
84
|
-
private rateLimiter: Map<string, number> = new Map();
|
|
85
|
-
private connectionPool: Map<string, any> = new Map();
|
|
86
|
-
|
|
87
|
-
constructor(client: ServiceNowClient, config?: Partial<CacheConfig>) {
|
|
88
|
-
this.client = client;
|
|
89
|
-
this.logger = new Logger('PerformanceOptimizer');
|
|
90
|
-
|
|
91
|
-
this.config = {
|
|
92
|
-
max_size: 1000,
|
|
93
|
-
default_ttl: 300000, // 5 minutes
|
|
94
|
-
cleanup_interval: 60000, // 1 minute
|
|
95
|
-
persistence_enabled: true,
|
|
96
|
-
compression_enabled: true,
|
|
97
|
-
...config
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
this.metrics = {
|
|
101
|
-
cache_hit_rate: 0,
|
|
102
|
-
cache_miss_rate: 0,
|
|
103
|
-
average_response_time: 0,
|
|
104
|
-
api_call_count: 0,
|
|
105
|
-
cache_size: 0,
|
|
106
|
-
memory_usage: 0,
|
|
107
|
-
bandwidth_saved: 0
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
this.startCleanupTimer();
|
|
111
|
-
this.loadPersistedCache();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Optimized API call with caching and performance monitoring
|
|
116
|
-
*/
|
|
117
|
-
async optimizedAPICall<T>(request: APIRequest): Promise<APIResponse<T>> {
|
|
118
|
-
const startTime = Date.now();
|
|
119
|
-
const cacheKey = request.cache_key || this.generateCacheKey(request);
|
|
120
|
-
|
|
121
|
-
// Check cache first
|
|
122
|
-
if (request.cacheable) {
|
|
123
|
-
const cached = this.getFromCache<T>(cacheKey);
|
|
124
|
-
if (cached) {
|
|
125
|
-
const responseTime = Date.now() - startTime;
|
|
126
|
-
this.updateMetrics(true, responseTime);
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
success: true,
|
|
130
|
-
data: cached,
|
|
131
|
-
cached: true,
|
|
132
|
-
response_time: responseTime,
|
|
133
|
-
cache_hit: true
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Apply rate limiting
|
|
139
|
-
if (this.isRateLimited(request.url)) {
|
|
140
|
-
await this.waitForRateLimit(request.url);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
// Execute API call
|
|
145
|
-
const response = await this.executeAPICall<T>(request);
|
|
146
|
-
const responseTime = Date.now() - startTime;
|
|
147
|
-
|
|
148
|
-
// Cache successful responses
|
|
149
|
-
if (request.cacheable && response.success && response.data) {
|
|
150
|
-
this.setInCache(cacheKey, response.data, {
|
|
151
|
-
ttl: this.getTTLForRequest(request),
|
|
152
|
-
tags: this.getTagsForRequest(request)
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
this.updateMetrics(false, responseTime);
|
|
157
|
-
|
|
158
|
-
return {
|
|
159
|
-
...response,
|
|
160
|
-
cached: false,
|
|
161
|
-
response_time: responseTime,
|
|
162
|
-
cache_hit: false
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
} catch (error) {
|
|
166
|
-
const responseTime = Date.now() - startTime;
|
|
167
|
-
this.updateMetrics(false, responseTime);
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
success: false,
|
|
171
|
-
error: error instanceof Error ? error.message : String(error),
|
|
172
|
-
cached: false,
|
|
173
|
-
response_time: responseTime,
|
|
174
|
-
cache_hit: false
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Batch multiple API requests for better performance
|
|
181
|
-
*/
|
|
182
|
-
async batchAPIRequests<T>(requests: APIRequest[]): Promise<APIResponse<T>[]> {
|
|
183
|
-
const batchId = `batch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
184
|
-
const batchRequest: BatchRequest = {
|
|
185
|
-
id: batchId,
|
|
186
|
-
requests: requests.sort((a, b) => b.priority - a.priority),
|
|
187
|
-
priority: 'medium',
|
|
188
|
-
timeout: 30000,
|
|
189
|
-
retry_count: 0
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
this.batchQueue.set(batchId, batchRequest);
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
// Group requests by type for optimization
|
|
196
|
-
const groupedRequests = this.groupRequestsByType(requests);
|
|
197
|
-
const results: APIResponse<T>[] = [];
|
|
198
|
-
|
|
199
|
-
// Execute groups in parallel
|
|
200
|
-
const groupPromises = Object.entries(groupedRequests).map(async ([type, groupRequests]) => {
|
|
201
|
-
return await this.executeBatchGroup<T>(groupRequests, type);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const groupResults = await Promise.all(groupPromises);
|
|
205
|
-
|
|
206
|
-
// Flatten results
|
|
207
|
-
for (const groupResult of groupResults) {
|
|
208
|
-
results.push(...groupResult);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return results;
|
|
212
|
-
|
|
213
|
-
} finally {
|
|
214
|
-
this.batchQueue.delete(batchId);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Preload commonly accessed data
|
|
220
|
-
*/
|
|
221
|
-
async preloadData(preloadConfig: {
|
|
222
|
-
action_types: boolean;
|
|
223
|
-
trigger_types: boolean;
|
|
224
|
-
flow_templates: boolean;
|
|
225
|
-
user_preferences: boolean;
|
|
226
|
-
}): Promise<void> {
|
|
227
|
-
const preloadTasks: Promise<void>[] = [];
|
|
228
|
-
|
|
229
|
-
if (preloadConfig.action_types) {
|
|
230
|
-
preloadTasks.push(this.preloadActionTypes());
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (preloadConfig.trigger_types) {
|
|
234
|
-
preloadTasks.push(this.preloadTriggerTypes());
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (preloadConfig.flow_templates) {
|
|
238
|
-
preloadTasks.push(this.preloadFlowTemplates());
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (preloadConfig.user_preferences) {
|
|
242
|
-
preloadTasks.push(this.preloadUserPreferences());
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
await Promise.all(preloadTasks);
|
|
246
|
-
this.logger.info('Data preloading completed');
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Analyze performance and provide optimization suggestions
|
|
251
|
-
*/
|
|
252
|
-
analyzePerformance(): {
|
|
253
|
-
metrics: PerformanceMetrics;
|
|
254
|
-
bottlenecks: string[];
|
|
255
|
-
optimization_hints: OptimizationHint[];
|
|
256
|
-
} {
|
|
257
|
-
const bottlenecks: string[] = [];
|
|
258
|
-
const optimizationHints: OptimizationHint[] = [];
|
|
259
|
-
|
|
260
|
-
// Analyze cache hit rate
|
|
261
|
-
if (this.metrics.cache_hit_rate < 0.5) {
|
|
262
|
-
bottlenecks.push('Low cache hit rate');
|
|
263
|
-
optimizationHints.push({
|
|
264
|
-
type: 'cache',
|
|
265
|
-
description: 'Increase cache TTL for frequently accessed data',
|
|
266
|
-
estimated_improvement: 0.3,
|
|
267
|
-
implementation_complexity: 'low'
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Analyze response times
|
|
272
|
-
if (this.metrics.average_response_time > 2000) {
|
|
273
|
-
bottlenecks.push('High response times');
|
|
274
|
-
optimizationHints.push({
|
|
275
|
-
type: 'parallel',
|
|
276
|
-
description: 'Implement parallel processing for independent requests',
|
|
277
|
-
estimated_improvement: 0.5,
|
|
278
|
-
implementation_complexity: 'medium'
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Analyze cache size
|
|
283
|
-
if (this.cache.size > this.config.max_size * 0.8) {
|
|
284
|
-
bottlenecks.push('Cache nearing capacity');
|
|
285
|
-
optimizationHints.push({
|
|
286
|
-
type: 'compress',
|
|
287
|
-
description: 'Enable compression for cached data',
|
|
288
|
-
estimated_improvement: 0.4,
|
|
289
|
-
implementation_complexity: 'medium'
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Analyze API call patterns
|
|
294
|
-
const batchableRequests = this.identifyBatchableRequests();
|
|
295
|
-
if (batchableRequests.length > 0) {
|
|
296
|
-
optimizationHints.push({
|
|
297
|
-
type: 'batch',
|
|
298
|
-
description: `Batch ${batchableRequests.length} similar requests`,
|
|
299
|
-
estimated_improvement: 0.6,
|
|
300
|
-
implementation_complexity: 'high'
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return {
|
|
305
|
-
metrics: this.metrics,
|
|
306
|
-
bottlenecks,
|
|
307
|
-
optimization_hints: optimizationHints
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Implement adaptive caching based on usage patterns
|
|
313
|
-
*/
|
|
314
|
-
optimizeCaching(): void {
|
|
315
|
-
const cacheAnalysis = this.analyzeCacheUsage();
|
|
316
|
-
|
|
317
|
-
// Adjust TTL based on access patterns
|
|
318
|
-
for (const [key, entry] of this.cache) {
|
|
319
|
-
const accessFrequency = entry.access_count / (Date.now() - entry.timestamp.getTime());
|
|
320
|
-
|
|
321
|
-
if (accessFrequency > 0.01) { // Frequently accessed
|
|
322
|
-
entry.ttl = this.config.default_ttl * 2;
|
|
323
|
-
} else if (accessFrequency < 0.001) { // Rarely accessed
|
|
324
|
-
entry.ttl = this.config.default_ttl * 0.5;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Implement cache warming for predicted requests
|
|
329
|
-
this.warmCache(cacheAnalysis.predicted_requests);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Get from cache with LRU eviction
|
|
334
|
-
*/
|
|
335
|
-
private getFromCache<T>(key: string): T | null {
|
|
336
|
-
const entry = this.cache.get(key);
|
|
337
|
-
if (!entry) {
|
|
338
|
-
return null;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Check if expired
|
|
342
|
-
if (Date.now() - entry.timestamp.getTime() > entry.ttl) {
|
|
343
|
-
this.cache.delete(key);
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Update access statistics
|
|
348
|
-
entry.access_count++;
|
|
349
|
-
entry.last_accessed = new Date();
|
|
350
|
-
|
|
351
|
-
return entry.value;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Set in cache with size management
|
|
356
|
-
*/
|
|
357
|
-
private setInCache<T>(key: string, value: T, options: {
|
|
358
|
-
ttl?: number;
|
|
359
|
-
tags?: string[];
|
|
360
|
-
} = {}): void {
|
|
361
|
-
// Check if cache is full
|
|
362
|
-
if (this.cache.size >= this.config.max_size) {
|
|
363
|
-
this.evictLeastRecent();
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const entry: CacheEntry<T> = {
|
|
367
|
-
key,
|
|
368
|
-
value,
|
|
369
|
-
timestamp: new Date(),
|
|
370
|
-
ttl: options.ttl || this.config.default_ttl,
|
|
371
|
-
access_count: 1,
|
|
372
|
-
last_accessed: new Date(),
|
|
373
|
-
tags: options.tags || [],
|
|
374
|
-
size: this.estimateSize(value)
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
this.cache.set(key, entry);
|
|
378
|
-
this.updateCacheMetrics();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Execute API call with connection pooling
|
|
383
|
-
*/
|
|
384
|
-
private async executeAPICall<T>(request: APIRequest): Promise<APIResponse<T>> {
|
|
385
|
-
const connection = this.getPooledConnection(request.url);
|
|
386
|
-
const startTime = Date.now();
|
|
387
|
-
|
|
388
|
-
try {
|
|
389
|
-
let response;
|
|
390
|
-
|
|
391
|
-
switch (request.method) {
|
|
392
|
-
case 'GET':
|
|
393
|
-
response = await this.client.getRecords(this.extractTable(request.url), request.data);
|
|
394
|
-
break;
|
|
395
|
-
case 'POST':
|
|
396
|
-
response = await this.client.createRecord(this.extractTable(request.url), request.data);
|
|
397
|
-
break;
|
|
398
|
-
case 'PUT':
|
|
399
|
-
case 'PATCH':
|
|
400
|
-
response = await this.client.updateRecord(this.extractTable(request.url), request.data.sys_id, request.data);
|
|
401
|
-
break;
|
|
402
|
-
case 'DELETE':
|
|
403
|
-
response = await this.client.deleteRecord(this.extractTable(request.url), request.data.sys_id);
|
|
404
|
-
break;
|
|
405
|
-
default:
|
|
406
|
-
throw new Error(`Unsupported method: ${request.method}`);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
return {
|
|
410
|
-
success: response.success,
|
|
411
|
-
data: response.data,
|
|
412
|
-
error: response.error,
|
|
413
|
-
cached: false,
|
|
414
|
-
response_time: Date.now() - startTime,
|
|
415
|
-
cache_hit: false
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
} finally {
|
|
419
|
-
this.returnPooledConnection(request.url, connection);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Group requests by type for batch processing
|
|
425
|
-
*/
|
|
426
|
-
private groupRequestsByType(requests: APIRequest[]): Record<string, APIRequest[]> {
|
|
427
|
-
const groups: Record<string, APIRequest[]> = {};
|
|
428
|
-
|
|
429
|
-
for (const request of requests) {
|
|
430
|
-
const type = `${request.method}_${this.extractTable(request.url)}`;
|
|
431
|
-
if (!groups[type]) {
|
|
432
|
-
groups[type] = [];
|
|
433
|
-
}
|
|
434
|
-
groups[type].push(request);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return groups;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Execute batch group with parallel processing
|
|
442
|
-
*/
|
|
443
|
-
private async executeBatchGroup<T>(requests: APIRequest[], type: string): Promise<APIResponse<T>[]> {
|
|
444
|
-
const batchSize = this.getBatchSizeForType(type);
|
|
445
|
-
const results: APIResponse<T>[] = [];
|
|
446
|
-
|
|
447
|
-
// Process requests in batches
|
|
448
|
-
for (let i = 0; i < requests.length; i += batchSize) {
|
|
449
|
-
const batch = requests.slice(i, i + batchSize);
|
|
450
|
-
const batchPromises = batch.map(request => this.optimizedAPICall<T>(request));
|
|
451
|
-
|
|
452
|
-
const batchResults = await Promise.all(batchPromises);
|
|
453
|
-
results.push(...batchResults);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
return results;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Preload action types
|
|
461
|
-
*/
|
|
462
|
-
private async preloadActionTypes(): Promise<void> {
|
|
463
|
-
const request: APIRequest = {
|
|
464
|
-
id: 'preload_action_types',
|
|
465
|
-
method: 'GET',
|
|
466
|
-
url: '/api/now/table/sys_hub_action_type_base',
|
|
467
|
-
cacheable: true,
|
|
468
|
-
priority: 1
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
await this.optimizedAPICall(request);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Preload trigger types
|
|
476
|
-
*/
|
|
477
|
-
private async preloadTriggerTypes(): Promise<void> {
|
|
478
|
-
const request: APIRequest = {
|
|
479
|
-
id: 'preload_trigger_types',
|
|
480
|
-
method: 'GET',
|
|
481
|
-
url: '/api/now/table/sys_hub_trigger_type',
|
|
482
|
-
cacheable: true,
|
|
483
|
-
priority: 1
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
await this.optimizedAPICall(request);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Preload flow templates
|
|
491
|
-
*/
|
|
492
|
-
private async preloadFlowTemplates(): Promise<void> {
|
|
493
|
-
const request: APIRequest = {
|
|
494
|
-
id: 'preload_flow_templates',
|
|
495
|
-
method: 'GET',
|
|
496
|
-
url: '/api/now/table/sys_hub_flow_template',
|
|
497
|
-
cacheable: true,
|
|
498
|
-
priority: 1
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
await this.optimizedAPICall(request);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Preload user preferences
|
|
506
|
-
*/
|
|
507
|
-
private async preloadUserPreferences(): Promise<void> {
|
|
508
|
-
const request: APIRequest = {
|
|
509
|
-
id: 'preload_user_preferences',
|
|
510
|
-
method: 'GET',
|
|
511
|
-
url: '/api/now/table/sys_user_preference',
|
|
512
|
-
cacheable: true,
|
|
513
|
-
priority: 1
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
await this.optimizedAPICall(request);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Analyze cache usage patterns
|
|
521
|
-
*/
|
|
522
|
-
private analyzeCacheUsage(): {
|
|
523
|
-
most_accessed: string[];
|
|
524
|
-
least_accessed: string[];
|
|
525
|
-
predicted_requests: string[];
|
|
526
|
-
} {
|
|
527
|
-
const sortedEntries = Array.from(this.cache.entries())
|
|
528
|
-
.sort((a, b) => b[1].access_count - a[1].access_count);
|
|
529
|
-
|
|
530
|
-
const mostAccessed = sortedEntries.slice(0, 10).map(([key]) => key);
|
|
531
|
-
const leastAccessed = sortedEntries.slice(-10).map(([key]) => key);
|
|
532
|
-
|
|
533
|
-
// Predict likely requests based on patterns
|
|
534
|
-
const predictedRequests = this.predictLikelyRequests(mostAccessed);
|
|
535
|
-
|
|
536
|
-
return {
|
|
537
|
-
most_accessed: mostAccessed,
|
|
538
|
-
least_accessed: leastAccessed,
|
|
539
|
-
predicted_requests: predictedRequests
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Warm cache with predicted requests
|
|
545
|
-
*/
|
|
546
|
-
private async warmCache(predictedRequests: string[]): Promise<void> {
|
|
547
|
-
const warmingTasks = predictedRequests.map(async (cacheKey) => {
|
|
548
|
-
if (!this.cache.has(cacheKey)) {
|
|
549
|
-
const request = this.reconstructRequestFromCacheKey(cacheKey);
|
|
550
|
-
if (request) {
|
|
551
|
-
await this.optimizedAPICall(request);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
await Promise.all(warmingTasks);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Evict least recently used entries
|
|
561
|
-
*/
|
|
562
|
-
private evictLeastRecent(): void {
|
|
563
|
-
const entries = Array.from(this.cache.entries())
|
|
564
|
-
.sort((a, b) => a[1].last_accessed.getTime() - b[1].last_accessed.getTime());
|
|
565
|
-
|
|
566
|
-
const entriesToEvict = entries.slice(0, Math.ceil(this.config.max_size * 0.1));
|
|
567
|
-
|
|
568
|
-
for (const [key] of entriesToEvict) {
|
|
569
|
-
this.cache.delete(key);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/**
|
|
574
|
-
* Update performance metrics
|
|
575
|
-
*/
|
|
576
|
-
private updateMetrics(cacheHit: boolean, responseTime: number): void {
|
|
577
|
-
this.metrics.api_call_count++;
|
|
578
|
-
|
|
579
|
-
if (cacheHit) {
|
|
580
|
-
this.metrics.cache_hit_rate = (this.metrics.cache_hit_rate * (this.metrics.api_call_count - 1) + 1) / this.metrics.api_call_count;
|
|
581
|
-
} else {
|
|
582
|
-
this.metrics.cache_miss_rate = (this.metrics.cache_miss_rate * (this.metrics.api_call_count - 1) + 1) / this.metrics.api_call_count;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
this.metrics.average_response_time = (this.metrics.average_response_time * (this.metrics.api_call_count - 1) + responseTime) / this.metrics.api_call_count;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Update cache metrics
|
|
590
|
-
*/
|
|
591
|
-
private updateCacheMetrics(): void {
|
|
592
|
-
this.metrics.cache_size = this.cache.size;
|
|
593
|
-
this.metrics.memory_usage = Array.from(this.cache.values())
|
|
594
|
-
.reduce((total, entry) => total + entry.size, 0);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Generate cache key for request
|
|
599
|
-
*/
|
|
600
|
-
private generateCacheKey(request: APIRequest): string {
|
|
601
|
-
const keyParts = [
|
|
602
|
-
request.method,
|
|
603
|
-
request.url,
|
|
604
|
-
JSON.stringify(request.data),
|
|
605
|
-
JSON.stringify(request.headers)
|
|
606
|
-
];
|
|
607
|
-
|
|
608
|
-
return Buffer.from(keyParts.join('|')).toString('base64');
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Get TTL for specific request type
|
|
613
|
-
*/
|
|
614
|
-
private getTTLForRequest(request: APIRequest): number {
|
|
615
|
-
const url = request.url.toLowerCase();
|
|
616
|
-
|
|
617
|
-
if (url.includes('action_type') || url.includes('trigger_type')) {
|
|
618
|
-
return 3600000; // 1 hour for metadata
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
if (url.includes('flow_template')) {
|
|
622
|
-
return 1800000; // 30 minutes for templates
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
if (url.includes('user_preference')) {
|
|
626
|
-
return 600000; // 10 minutes for preferences
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
return this.config.default_ttl;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Get tags for request
|
|
634
|
-
*/
|
|
635
|
-
private getTagsForRequest(request: APIRequest): string[] {
|
|
636
|
-
const tags: string[] = [];
|
|
637
|
-
const url = request.url.toLowerCase();
|
|
638
|
-
|
|
639
|
-
if (url.includes('action_type')) tags.push('action_type');
|
|
640
|
-
if (url.includes('trigger_type')) tags.push('trigger_type');
|
|
641
|
-
if (url.includes('flow')) tags.push('flow');
|
|
642
|
-
if (url.includes('user')) tags.push('user');
|
|
643
|
-
|
|
644
|
-
return tags;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Estimate size of cached value
|
|
649
|
-
*/
|
|
650
|
-
private estimateSize(value: any): number {
|
|
651
|
-
return JSON.stringify(value).length * 2; // Rough estimate
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* Extract table name from URL
|
|
656
|
-
*/
|
|
657
|
-
private extractTable(url: string): string {
|
|
658
|
-
const match = url.match(/\/table\/([^\/\?]+)/);
|
|
659
|
-
return match ? match[1] : 'unknown';
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
/**
|
|
663
|
-
* Get batch size for request type
|
|
664
|
-
*/
|
|
665
|
-
private getBatchSizeForType(type: string): number {
|
|
666
|
-
if (type.includes('GET')) return 10;
|
|
667
|
-
if (type.includes('POST')) return 5;
|
|
668
|
-
if (type.includes('PUT') || type.includes('PATCH')) return 3;
|
|
669
|
-
if (type.includes('DELETE')) return 3;
|
|
670
|
-
return 5;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
/**
|
|
674
|
-
* Check if request is rate limited
|
|
675
|
-
*/
|
|
676
|
-
private isRateLimited(url: string): boolean {
|
|
677
|
-
const domain = this.extractDomain(url);
|
|
678
|
-
const lastRequest = this.rateLimiter.get(domain);
|
|
679
|
-
|
|
680
|
-
if (!lastRequest) return false;
|
|
681
|
-
|
|
682
|
-
const timeSinceLastRequest = Date.now() - lastRequest;
|
|
683
|
-
return timeSinceLastRequest < 100; // 100ms rate limit
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* Wait for rate limit to clear
|
|
688
|
-
*/
|
|
689
|
-
private async waitForRateLimit(url: string): Promise<void> {
|
|
690
|
-
const domain = this.extractDomain(url);
|
|
691
|
-
const lastRequest = this.rateLimiter.get(domain);
|
|
692
|
-
|
|
693
|
-
if (lastRequest) {
|
|
694
|
-
const waitTime = 100 - (Date.now() - lastRequest);
|
|
695
|
-
if (waitTime > 0) {
|
|
696
|
-
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
this.rateLimiter.set(domain, Date.now());
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Extract domain from URL
|
|
705
|
-
*/
|
|
706
|
-
private extractDomain(url: string): string {
|
|
707
|
-
try {
|
|
708
|
-
return new URL(url).hostname;
|
|
709
|
-
} catch {
|
|
710
|
-
return 'default';
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
/**
|
|
715
|
-
* Get pooled connection
|
|
716
|
-
*/
|
|
717
|
-
private getPooledConnection(url: string): any {
|
|
718
|
-
const domain = this.extractDomain(url);
|
|
719
|
-
return this.connectionPool.get(domain) || {};
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
/**
|
|
723
|
-
* Return pooled connection
|
|
724
|
-
*/
|
|
725
|
-
private returnPooledConnection(url: string, connection: any): void {
|
|
726
|
-
const domain = this.extractDomain(url);
|
|
727
|
-
this.connectionPool.set(domain, connection);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
/**
|
|
731
|
-
* Identify batchable requests
|
|
732
|
-
*/
|
|
733
|
-
private identifyBatchableRequests(): string[] {
|
|
734
|
-
// Implementation would analyze request patterns
|
|
735
|
-
return [];
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
/**
|
|
739
|
-
* Predict likely requests based on patterns
|
|
740
|
-
*/
|
|
741
|
-
private predictLikelyRequests(mostAccessed: string[]): string[] {
|
|
742
|
-
// Implementation would use ML or pattern analysis
|
|
743
|
-
return mostAccessed.slice(0, 5);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
/**
|
|
747
|
-
* Reconstruct request from cache key
|
|
748
|
-
*/
|
|
749
|
-
private reconstructRequestFromCacheKey(cacheKey: string): APIRequest | null {
|
|
750
|
-
try {
|
|
751
|
-
const decoded = Buffer.from(cacheKey, 'base64').toString();
|
|
752
|
-
const [method, url, data, headers] = decoded.split('|');
|
|
753
|
-
|
|
754
|
-
return {
|
|
755
|
-
id: 'reconstructed',
|
|
756
|
-
method: method as any,
|
|
757
|
-
url,
|
|
758
|
-
data: JSON.parse(data),
|
|
759
|
-
headers: JSON.parse(headers),
|
|
760
|
-
cacheable: true,
|
|
761
|
-
priority: 1
|
|
762
|
-
};
|
|
763
|
-
} catch {
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* Start cleanup timer
|
|
770
|
-
*/
|
|
771
|
-
private startCleanupTimer(): void {
|
|
772
|
-
this.cleanupTimer = setInterval(() => {
|
|
773
|
-
this.cleanupExpiredEntries();
|
|
774
|
-
}, this.config.cleanup_interval);
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
/**
|
|
778
|
-
* Cleanup expired entries
|
|
779
|
-
*/
|
|
780
|
-
private cleanupExpiredEntries(): void {
|
|
781
|
-
const now = Date.now();
|
|
782
|
-
const expiredKeys: string[] = [];
|
|
783
|
-
|
|
784
|
-
for (const [key, entry] of this.cache) {
|
|
785
|
-
if (now - entry.timestamp.getTime() > entry.ttl) {
|
|
786
|
-
expiredKeys.push(key);
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
for (const key of expiredKeys) {
|
|
791
|
-
this.cache.delete(key);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
if (expiredKeys.length > 0) {
|
|
795
|
-
this.logger.debug(`Cleaned up ${expiredKeys.length} expired cache entries`);
|
|
796
|
-
this.updateCacheMetrics();
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* Load persisted cache
|
|
802
|
-
*/
|
|
803
|
-
private loadPersistedCache(): void {
|
|
804
|
-
if (!this.config.persistence_enabled) return;
|
|
805
|
-
|
|
806
|
-
try {
|
|
807
|
-
const cacheFile = path.join(process.env.SNOW_FLOW_HOME || path.join(os.homedir(), '.snow-flow'), 'cache', 'performance_cache.json');
|
|
808
|
-
|
|
809
|
-
if (fs.existsSync(cacheFile)) {
|
|
810
|
-
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf-8'));
|
|
811
|
-
|
|
812
|
-
for (const [key, entry] of Object.entries(cacheData)) {
|
|
813
|
-
this.cache.set(key, {
|
|
814
|
-
...entry as CacheEntry<any>,
|
|
815
|
-
timestamp: new Date((entry as any).timestamp),
|
|
816
|
-
last_accessed: new Date((entry as any).last_accessed)
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
this.logger.info(`Loaded ${this.cache.size} entries from persisted cache`);
|
|
821
|
-
}
|
|
822
|
-
} catch (error) {
|
|
823
|
-
this.logger.warn('Failed to load persisted cache:', error);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
/**
|
|
828
|
-
* Save cache to disk
|
|
829
|
-
*/
|
|
830
|
-
saveCacheToDisk(): void {
|
|
831
|
-
if (!this.config.persistence_enabled) return;
|
|
832
|
-
|
|
833
|
-
try {
|
|
834
|
-
const cacheDir = path.join(process.env.SNOW_FLOW_HOME || path.join(os.homedir(), '.snow-flow'), 'cache');
|
|
835
|
-
if (!fs.existsSync(cacheDir)) {
|
|
836
|
-
fs.mkdirSync(cacheDir, { recursive: true });
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
const cacheFile = path.join(cacheDir, 'performance_cache.json');
|
|
840
|
-
const cacheData = Object.fromEntries(this.cache.entries());
|
|
841
|
-
|
|
842
|
-
fs.writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2));
|
|
843
|
-
this.logger.info(`Saved ${this.cache.size} entries to persisted cache`);
|
|
844
|
-
} catch (error) {
|
|
845
|
-
this.logger.warn('Failed to save cache to disk:', error);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
/**
|
|
850
|
-
* Clear cache
|
|
851
|
-
*/
|
|
852
|
-
clearCache(tags?: string[]): void {
|
|
853
|
-
if (!tags || tags.length === 0) {
|
|
854
|
-
this.cache.clear();
|
|
855
|
-
this.logger.info('Cleared all cache entries');
|
|
856
|
-
} else {
|
|
857
|
-
const keysToDelete: string[] = [];
|
|
858
|
-
|
|
859
|
-
for (const [key, entry] of this.cache) {
|
|
860
|
-
if (entry.tags.some(tag => tags.includes(tag))) {
|
|
861
|
-
keysToDelete.push(key);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
for (const key of keysToDelete) {
|
|
866
|
-
this.cache.delete(key);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
this.logger.info(`Cleared ${keysToDelete.length} cache entries with tags: ${tags.join(', ')}`);
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
this.updateCacheMetrics();
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
* Destroy optimizer and cleanup
|
|
877
|
-
*/
|
|
878
|
-
destroy(): void {
|
|
879
|
-
if (this.cleanupTimer) {
|
|
880
|
-
clearInterval(this.cleanupTimer);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
this.saveCacheToDisk();
|
|
884
|
-
this.cache.clear();
|
|
885
|
-
this.batchQueue.clear();
|
|
886
|
-
this.rateLimiter.clear();
|
|
887
|
-
this.connectionPool.clear();
|
|
888
|
-
|
|
889
|
-
this.logger.info('Performance optimizer destroyed');
|
|
890
|
-
}
|
|
891
|
-
}
|