import axios from 'axios'; const API_URL = process.env.TEST_API_URL || 'http://localhost:3200/api/geocoding/search'; const API_KEY = process.env.TEST_API_KEY || process.env.MAP_API_KEY || ''; const TOTAL_REQUESTS = 5000; const CONCURRENCY = 50; // Number of parallel requests const keywords = ["مستشفى", "شارع", "مدرسة", "جامعة", "مطعم", "فندق", "مسجد", "مقهى", "صيدلية", "مول", "دوار", "عيادة", "بنك", "مخبز"]; const names = ["السلام", "التخصصي", "المدينة", "النور", "اليرموك", "العربي", "الحديث", "الوطني", "المركزي", "الواحة", "الاموي", "المواساة"]; function generateRandomQuery(): string { const keyword = keywords[Math.floor(Math.random() * keywords.length)]; const name = names[Math.floor(Math.random() * names.length)]; const randomSuffix = Math.random() > 0.5 ? ` ${Math.floor(Math.random() * 100)}` : ''; return `${keyword} ${name}${randomSuffix}`; } async function runLoadTest() { console.log(`🚀 Starting Load Test: ${TOTAL_REQUESTS} requests with concurrency of ${CONCURRENCY}...`); console.log(`📡 Target API: ${API_URL}\n`); let completed = 0; let successful = 0; let failed = 0; const latencies: number[] = []; const startTime = Date.now(); // Worker function to process a chunk of requests async function worker(requestsCount: number) { for (let i = 0; i < requestsCount; i++) { const query = generateRandomQuery(); const reqStart = Date.now(); try { await axios.get(API_URL, { headers: { 'x-api-key': API_KEY }, params: { q: query, country: 'syria' } // targeting syria since data exists there }); successful++; } catch (error: any) { if (failed === 0) { console.error('First failure reason:', error.response?.data || error.message); } failed++; } finally { latencies.push(Date.now() - reqStart); completed++; if (completed % 500 === 0) { console.log(`⏳ Progress: ${completed}/${TOTAL_REQUESTS} requests completed...`); } } } } // Split the total requests among the concurrent workers const requestsPerWorker = Math.floor(TOTAL_REQUESTS / CONCURRENCY); const workers: Promise[] = []; for (let i = 0; i < CONCURRENCY; i++) { // The last worker takes any remainder const count = (i === CONCURRENCY - 1) ? requestsPerWorker + (TOTAL_REQUESTS % CONCURRENCY) : requestsPerWorker; workers.push(worker(count)); } await Promise.all(workers); const totalTimeSec = (Date.now() - startTime) / 1000; const rps = TOTAL_REQUESTS / totalTimeSec; latencies.sort((a, b) => a - b); const p50 = latencies[Math.floor(latencies.length * 0.50)] || 0; const p95 = latencies[Math.floor(latencies.length * 0.95)] || 0; const p99 = latencies[Math.floor(latencies.length * 0.99)] || 0; console.log('\n======================================='); console.log('📊 LOAD TEST RESULTS'); console.log('======================================='); console.log(`Total Requests : ${TOTAL_REQUESTS}`); console.log(`Successful : ${successful} (${((successful/TOTAL_REQUESTS)*100).toFixed(1)}%)`); console.log(`Failed : ${failed} (${((failed/TOTAL_REQUESTS)*100).toFixed(1)}%)`); console.log(`Total Time : ${totalTimeSec.toFixed(2)} seconds`); console.log(`Throughput (RPS): ${rps.toFixed(2)} req/sec`); console.log('---------------------------------------'); console.log(`p50 Latency : ${p50} ms`); console.log(`p95 Latency : ${p95} ms`); console.log(`p99 Latency : ${p99} ms`); console.log('=======================================\n'); } runLoadTest().catch(console.error);