@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
216 lines (214 loc) • 9 kB
JavaScript
/**
* Test script for cache integration with actual data
* Creates test data and verifies caching behavior
*/
import { IntelligentQueryEngine } from './IntelligentQueryEngine.js';
import { OptimizelyAdapter } from './adapters/OptimizelyAdapter.js';
import { getLogger } from '../../logging/Logger.js';
import Database from 'better-sqlite3';
const logger = getLogger();
async function setupTestData(db) {
console.info('Setting up test data...');
// Create tables
db.exec(`
CREATE TABLE IF NOT EXISTS flags (
id TEXT PRIMARY KEY,
key TEXT NOT NULL,
name TEXT,
description TEXT,
enabled INTEGER DEFAULT 1,
archived INTEGER DEFAULT 0,
project_id TEXT,
environments TEXT,
created TEXT,
last_modified TEXT
);
CREATE TABLE IF NOT EXISTS experiments (
id TEXT PRIMARY KEY,
key TEXT NOT NULL,
name TEXT,
description TEXT,
status TEXT,
project_id TEXT,
campaign_id TEXT,
created TEXT,
last_modified TEXT
);
CREATE TABLE IF NOT EXISTS audiences (
id TEXT PRIMARY KEY,
key TEXT,
name TEXT NOT NULL,
description TEXT,
conditions TEXT,
project_id TEXT,
archived INTEGER DEFAULT 0,
created TEXT,
last_modified TEXT
);
`);
// Insert test flags
const insertFlag = db.prepare(`
INSERT INTO flags (id, key, name, description, enabled, project_id, environments, created, last_modified)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
for (let i = 1; i <= 20; i++) {
insertFlag.run(`flag_${i}`, `test_flag_${i}`, `Test Flag ${i}`, `Description for test flag ${i}`, i % 3 !== 0 ? 1 : 0, // Every 3rd flag is disabled
'test_project', JSON.stringify({ production: { enabled: true }, staging: { enabled: false } }), new Date().toISOString(), new Date().toISOString());
}
// Insert test experiments
const insertExp = db.prepare(`
INSERT INTO experiments (id, key, name, description, status, project_id, created, last_modified)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`);
const statuses = ['running', 'paused', 'completed'];
for (let i = 1; i <= 15; i++) {
insertExp.run(`exp_${i}`, `test_experiment_${i}`, `Test Experiment ${i}`, `Description for experiment ${i}`, statuses[i % 3], 'test_project', new Date().toISOString(), new Date().toISOString());
}
// Insert test audiences
const insertAud = db.prepare(`
INSERT INTO audiences (id, name, description, conditions, project_id, created, last_modified)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
for (let i = 1; i <= 10; i++) {
insertAud.run(`aud_${i}`, `Test Audience ${i}`, `Description for audience ${i}`, JSON.stringify({ type: 'custom_attribute', name: `attr_${i}`, value: `value_${i}` }), 'test_project', new Date().toISOString(), new Date().toISOString());
}
console.info('Test data created successfully');
}
async function runCacheTest() {
console.info('Starting cache integration test with data');
try {
// Initialize in-memory database
const db = new Database(':memory:');
// Setup test data
await setupTestData(db);
// Create engine with cache enabled
const engine = new IntelligentQueryEngine({
cache: {
enabled: true,
warmupOnStart: false,
statsInterval: 5000, // 5 seconds for testing
defaultTTL: 30000, // 30 seconds for testing
}
});
// Register Optimizely adapter
const adapter = new OptimizelyAdapter({ database: db });
engine.registerAdapter(adapter);
// Test queries
const testQueries = [
{
name: 'List enabled flags',
query: {
find: 'flags',
select: ['key', 'name', 'enabled'],
where: [{ field: 'enabled', operator: '=', value: 1 }],
limit: 10,
}
},
{
name: 'Count experiments by status',
query: {
find: 'experiments',
select: ['status'],
groupBy: ['status'],
aggregations: [{ field: 'id', function: 'COUNT', alias: 'count' }],
}
},
{
name: 'Get audience details',
query: {
find: 'audiences',
select: ['id', 'name', 'conditions'],
limit: 5,
}
},
{
name: 'Complex flag query',
query: {
find: 'flags',
select: ['key', 'name', 'description', 'environments'],
where: [
{ field: 'enabled', operator: '=', value: 1 },
{ field: 'archived', operator: '=', value: 0 }
],
orderBy: [{ field: 'name', direction: 'ASC' }],
limit: 20,
}
}
];
console.info('=== Running Cache Performance Tests ===\n');
const results = [];
// Run each query multiple times
for (const test of testQueries) {
console.info(`\nTesting: ${test.name}`);
console.info('─'.repeat(50));
const timings = [];
const cacheHits = [];
// Run 5 times to see cache behavior
for (let run = 1; run <= 5; run++) {
const start = Date.now();
const result = await engine.query(test.query);
const elapsed = Date.now() - start;
timings.push(elapsed);
cacheHits.push(result.metadata.cached || false);
console.info(` Run ${run}: ${elapsed}ms ${result.metadata.cached ? 'CACHED' : 'NOT CACHED'} - ${result.data.length} rows`);
}
// Calculate statistics
const avgTime = timings.reduce((a, b) => a + b, 0) / timings.length;
const cacheHitRate = cacheHits.filter(h => h).length / cacheHits.length * 100;
const speedup = timings[0] > 0 ? ((timings[0] - timings[timings.length - 1]) / timings[0] * 100).toFixed(1) : 0;
console.info(`\n 📈 Stats:`);
console.info(` Average time: ${avgTime.toFixed(1)}ms`);
console.info(` Cache hit rate: ${cacheHitRate.toFixed(0)}%`);
console.info(` Speed improvement: ${speedup}%`);
results.push({
query: test.name,
avgTime,
cacheHitRate,
speedup
});
}
// Test cache invalidation
console.info('\n\n=== Testing Cache Invalidation ===');
console.info('─'.repeat(50));
const beforeInvalidation = await engine.query(testQueries[0].query);
console.info(`Before invalidation: ${beforeInvalidation.metadata.cached ? 'CACHED' : 'NOT CACHED'}`);
const invalidated = await engine.invalidateCache('flags');
console.info(`Invalidated ${invalidated} cache entries for flags`);
const afterInvalidation = await engine.query(testQueries[0].query);
console.info(`After invalidation: ${afterInvalidation.metadata.cached ? 'CACHED' : 'NOT CACHED'}`);
// Get final statistics
console.info('\n\n=== Cache Statistics ===');
console.info('─'.repeat(50));
const cacheMetrics = engine.getCacheMetrics();
console.info(`Hit Rate: ${(cacheMetrics.hitRate * 100).toFixed(1)}%`);
console.info(`Total Entries: ${cacheMetrics.entries}`);
console.info(`Cache Size: ${(cacheMetrics.sizeBytes / 1024).toFixed(1)} KB`);
console.info(`\nRecommended TTLs:`);
Object.entries(cacheMetrics.recommendedTTLs).forEach(([scenario, ttl]) => {
console.info(` ${scenario}: ${ttl / 1000}s`);
});
// Summary
console.info('\n\n=== Performance Summary ===');
console.info('─'.repeat(50));
results.forEach(r => {
console.info(`${r.query}:`);
console.info(` ⚡ Avg: ${r.avgTime.toFixed(1)}ms | Cache: ${r.cacheHitRate}% | Speedup: ${r.speedup}%`);
});
// Wait a bit to see stats reporting
console.info('\n\nWaiting 6 seconds to see periodic stats reporting...');
await new Promise(resolve => setTimeout(resolve, 6000));
// Shutdown
await engine.shutdown();
console.info('\nCache integration test completed successfully!');
}
catch (error) {
console.error('Test failed: ' + String(error));
throw error;
}
}
// Run the test
runCacheTest().catch(error => {
console.error('Fatal error: ' + String(error));
process.exit(1);
});
//# sourceMappingURL=test-cache-with-data.js.map