takes 11m out of search

pull/27/head
accius 4 days ago
parent 14fa020b1b
commit 5704639efb

@ -36,12 +36,10 @@ const CACHE_MAX_SIZE = 100;
let circuitBreakerOpen = false; let circuitBreakerOpen = false;
let consecutiveFailures = 0; let consecutiveFailures = 0;
let lastFailureTime = 0; let lastFailureTime = 0;
const FAILURE_THRESHOLD = 5; let lastLogTime = 0;
const CIRCUIT_RESET_TIME = 60 * 1000; // 1 minute const FAILURE_THRESHOLD = 3; // Open after 3 failures
const CIRCUIT_RESET_TIME = 2 * 60 * 1000; // 2 minutes before retry
// Rate limiting - track last log time to avoid log spam const LOG_INTERVAL = 30000; // Only log every 30 seconds
let lastErrorLogTime = 0;
const ERROR_LOG_INTERVAL = 10000; // Only log errors every 10 seconds
function getCacheKey(params) { function getCacheKey(params) {
// Round coordinates to 1 decimal place for better cache hits // Round coordinates to 1 decimal place for better cache hits
@ -67,6 +65,15 @@ function setCache(key, data) {
predictionCache.set(key, { data, timestamp: Date.now() }); predictionCache.set(key, { data, timestamp: Date.now() });
} }
function shouldLog() {
const now = Date.now();
if (now - lastLogTime > LOG_INTERVAL) {
lastLogTime = now;
return true;
}
return false;
}
function checkCircuitBreaker() { function checkCircuitBreaker() {
if (!circuitBreakerOpen) return false; if (!circuitBreakerOpen) return false;
@ -74,7 +81,9 @@ function checkCircuitBreaker() {
if (Date.now() - lastFailureTime > CIRCUIT_RESET_TIME) { if (Date.now() - lastFailureTime > CIRCUIT_RESET_TIME) {
circuitBreakerOpen = false; circuitBreakerOpen = false;
consecutiveFailures = 0; consecutiveFailures = 0;
if (shouldLog()) {
console.log('[Circuit Breaker] Reset - allowing requests'); console.log('[Circuit Breaker] Reset - allowing requests');
}
return false; return false;
} }
return true; return true;
@ -84,12 +93,10 @@ function recordFailure() {
consecutiveFailures++; consecutiveFailures++;
lastFailureTime = Date.now(); lastFailureTime = Date.now();
if (consecutiveFailures >= FAILURE_THRESHOLD) { if (consecutiveFailures >= FAILURE_THRESHOLD && !circuitBreakerOpen) {
circuitBreakerOpen = true; circuitBreakerOpen = true;
// Only log this once if (shouldLog()) {
if (Date.now() - lastErrorLogTime > ERROR_LOG_INTERVAL) { console.log(`[Circuit Breaker] OPEN after ${consecutiveFailures} failures - pausing for ${CIRCUIT_RESET_TIME/1000}s`);
console.log(`[Circuit Breaker] OPEN - ${consecutiveFailures} consecutive failures, pausing for ${CIRCUIT_RESET_TIME/1000}s`);
lastErrorLogTime = Date.now();
} }
} }
} }
@ -119,8 +126,8 @@ const HF_BANDS = {
'17m': 18.1, '17m': 18.1,
'15m': 21.1, '15m': 21.1,
'12m': 24.9, '12m': 24.9,
'11m': 27.0, // CB band (26.965-27.405 MHz)
'10m': 28.1 '10m': 28.1
// Note: 11m (27 MHz) excluded - too close to P.533 upper limit, use built-in calculation
// Note: 6m (50 MHz) excluded - outside P.533 HF range (2-30 MHz) // Note: 6m (50 MHz) excluded - outside P.533 HF range (2-30 MHz)
}; };
@ -240,7 +247,6 @@ function parseOutputFile(outputPath) {
snr: snr, snr: snr,
reliability: bcr reliability: bcr
}); });
// Removed per-frequency logging to reduce spam
} }
} }
} }
@ -252,17 +258,9 @@ function parseOutputFile(outputPath) {
results.muf = parseFloat(mufMatch[1]); results.muf = parseFloat(mufMatch[1]);
} }
// Only log success occasionally
if (results.frequencies.length > 0 && Date.now() - lastErrorLogTime > ERROR_LOG_INTERVAL) {
console.log(`[Parse] Found ${results.frequencies.length} frequency results, MUF=${results.muf || 'N/A'}`);
}
return results; return results;
} catch (err) { } catch (err) {
// Only log errors occasionally // File doesn't exist - this is expected when ITURHFProp fails
if (Date.now() - lastErrorLogTime > ERROR_LOG_INTERVAL) {
console.error('[Parse Error]', err.message);
lastErrorLogTime = Date.now();
}
return { error: err.message, frequencies: [] }; return { error: err.message, frequencies: [] };
} }
} }
@ -271,16 +269,16 @@ function parseOutputFile(outputPath) {
* Run ITURHFProp prediction * Run ITURHFProp prediction
*/ */
async function runPrediction(params) { async function runPrediction(params) {
// Check circuit breaker first // Check circuit breaker first - return immediately if open
if (checkCircuitBreaker()) { if (checkCircuitBreaker()) {
return { error: 'Circuit breaker open - service temporarily unavailable', frequencies: [] }; return { error: 'Circuit breaker open', frequencies: [], circuitBreakerOpen: true };
} }
// Check cache // Check cache
const cacheKey = getCacheKey(params); const cacheKey = getCacheKey(params);
const cached = getFromCache(cacheKey); const cached = getFromCache(cacheKey);
if (cached) { if (cached) {
return cached; return { ...cached, fromCache: true };
} }
const id = crypto.randomBytes(8).toString('hex'); const id = crypto.randomBytes(8).toString('hex');
@ -292,44 +290,32 @@ async function runPrediction(params) {
fs.mkdirSync(TEMP_DIR, { recursive: true }); fs.mkdirSync(TEMP_DIR, { recursive: true });
} }
let execStdout = '';
let execStderr = '';
try { try {
// Generate input file // Generate input file
const inputContent = generateInputFile(params); const inputContent = generateInputFile(params);
fs.writeFileSync(inputPath, inputContent); fs.writeFileSync(inputPath, inputContent);
// Only log occasionally to avoid spam
const shouldLog = Date.now() - lastErrorLogTime > ERROR_LOG_INTERVAL;
if (shouldLog) {
console.log(`[ITURHFProp] Running prediction ${id}: TX(${params.txLat.toFixed(1)},${params.txLon.toFixed(1)}) -> RX(${params.rxLat.toFixed(1)},${params.rxLon.toFixed(1)})`);
}
// Run ITURHFProp // Run ITURHFProp
const startTime = Date.now(); const startTime = Date.now();
const cmd = `${ITURHFPROP_PATH} ${inputPath} ${outputPath}`; const cmd = `${ITURHFPROP_PATH} ${inputPath} ${outputPath}`;
let execStdout = '';
try { try {
execStdout = execSync(cmd, { execStdout = execSync(cmd, {
timeout: 30000, // 30 second timeout timeout: 30000,
encoding: 'utf8', encoding: 'utf8',
env: { ...process.env, LD_LIBRARY_PATH: '/opt/iturhfprop:' + (process.env.LD_LIBRARY_PATH || '') } env: { ...process.env, LD_LIBRARY_PATH: '/opt/iturhfprop:' + (process.env.LD_LIBRARY_PATH || '') }
}); });
} catch (execError) { } catch (execError) {
execStderr = execError.stderr?.toString() || ''; recordFailure();
execStdout = execError.stdout?.toString() || '';
// Only log errors periodically to avoid spam // Only log occasionally
if (Date.now() - lastErrorLogTime > ERROR_LOG_INTERVAL) { if (shouldLog()) {
console.error(`[ITURHFProp] Error (exit ${execError.status}): ${execStdout.substring(0, 100)}`); console.error(`[ITURHFProp] Failed (exit ${execError.status}), failures: ${consecutiveFailures}, circuit: ${circuitBreakerOpen ? 'OPEN' : 'closed'}`);
lastErrorLogTime = Date.now();
} }
recordFailure(); // Cache the error to prevent repeated attempts
const errorResult = { error: `Exit code ${execError.status}`, frequencies: [] };
// Return empty result but cache it to avoid repeated failures
const errorResult = { error: `Exit code ${execError.status}`, frequencies: [], cached: false };
setCache(cacheKey, errorResult); setCache(cacheKey, errorResult);
return errorResult; return errorResult;
} }
@ -362,6 +348,10 @@ async function runPrediction(params) {
// Cache successful result // Cache successful result
setCache(cacheKey, results); setCache(cacheKey, results);
if (shouldLog()) {
console.log(`[ITURHFProp] Success: ${results.frequencies.length} freqs, MUF=${results.muf || 'N/A'}`);
}
return results; return results;
} finally { } finally {

Loading…
Cancel
Save

Powered by TurnKey Linux.