← back to Watches
scripts/warmup-market-cache.js
154 lines
#!/usr/bin/env node
/**
* Cache Warmup Script for Market Data
* Pre-populates the server cache with real market data from Wayback Machine
* Run this periodically to ensure fast response times
*/
const http = require('http');
const https = require('https');
// Server configuration
const SERVER_HOST = 'localhost';
const SERVER_PORT = 7600;
// All watch IDs from omega-watches.json
const WATCH_IDS = [
'speedmaster-moonwatch',
'speedmaster-alaska',
'seamaster-300',
'seamaster-ploprof',
'seamaster-bond',
'constellation-piepan',
'constellation-manhattan',
'deville-tresor',
'deville-coaxial',
'railmaster-original',
'aqua-terra',
'planet-ocean',
'speedmaster-reduced',
'speedmaster-mark2',
'flightmaster'
];
// Delay between requests (ms) - be respectful to Wayback Machine
const REQUEST_DELAY = 30000; // 30 seconds
function fetchMarketData(watchId) {
return new Promise((resolve, reject) => {
const options = {
hostname: SERVER_HOST,
port: SERVER_PORT,
path: `/api/market-data/${watchId}`,
method: 'GET',
timeout: 180000 // 3 minute timeout
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const json = JSON.parse(data);
resolve({
watchId,
success: json.success,
isMock: json.isMock,
source: json.source,
price: json.marketPrice ? `$${json.marketPrice.low} - $${json.marketPrice.high}` : 'N/A'
});
} catch (e) {
reject(new Error(`Failed to parse response: ${e.message}`));
}
});
});
req.on('error', (e) => {
reject(e);
});
req.on('timeout', () => {
req.destroy();
reject(new Error('Request timeout'));
});
req.end();
});
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function warmupCache() {
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ MARKET DATA CACHE WARMUP ║');
console.log('╚════════════════════════════════════════════════════════════╝\n');
console.log(`Starting cache warmup for ${WATCH_IDS.length} watches...`);
console.log(`Request delay: ${REQUEST_DELAY / 1000} seconds\n`);
const startTime = Date.now();
const results = {
success: 0,
failed: 0,
mock: 0,
real: 0
};
for (let i = 0; i < WATCH_IDS.length; i++) {
const watchId = WATCH_IDS[i];
const progress = `[${i + 1}/${WATCH_IDS.length}]`;
console.log(`${progress} Fetching ${watchId}...`);
try {
const result = await fetchMarketData(watchId);
if (result.success) {
results.success++;
if (result.isMock) {
results.mock++;
console.log(` ⚠️ Mock data: ${result.price}`);
} else {
results.real++;
console.log(` ✅ Real data: ${result.price} (${result.source})`);
}
} else {
results.failed++;
console.log(` ❌ Failed to fetch data`);
}
} catch (error) {
results.failed++;
console.log(` ❌ Error: ${error.message}`);
}
// Wait before next request (except for last one)
if (i < WATCH_IDS.length - 1) {
console.log(` Waiting ${REQUEST_DELAY / 1000}s before next request...\n`);
await sleep(REQUEST_DELAY);
}
}
const elapsed = Math.round((Date.now() - startTime) / 1000);
console.log('\n╔════════════════════════════════════════════════════════════╗');
console.log('║ WARMUP COMPLETE ║');
console.log('╚════════════════════════════════════════════════════════════╝');
console.log(`\nResults:`);
console.log(` Total: ${WATCH_IDS.length}`);
console.log(` Success: ${results.success}`);
console.log(` Failed: ${results.failed}`);
console.log(` Real data: ${results.real}`);
console.log(` Mock data: ${results.mock}`);
console.log(` Time: ${elapsed}s`);
console.log(`\nCache is now warm! Requests will be served from cache for 1 hour.`);
}
// Run the warmup
warmupCache().catch(console.error);