Files
maps-saas/apps/api/scripts/load_test_geocoding.ts
T

92 lines
3.7 KiB
TypeScript

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 || 'zP9vL5mK2nQ8xR7jT4wS1yB6hG3fV0cX';
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<void>[] = [];
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);