147 lines
5.1 KiB
JavaScript
147 lines
5.1 KiB
JavaScript
/**
|
|
* SCENARIO: location-update.js
|
|
* Real-time location stress test — simulasi banyak User berjalan serentak.
|
|
*
|
|
* WalkGuide mengirim lokasi setiap 5 detik saat WalkGuide aktif.
|
|
* Ini endpoint paling high-frequency di seluruh sistem.
|
|
*
|
|
* Target: p95 < 300ms, error rate < 1%
|
|
*/
|
|
import { sleep, check } from "k6";
|
|
import {
|
|
DEFAULT_THRESHOLDS,
|
|
handleSummary,
|
|
metricsHelper,
|
|
pickThresholds,
|
|
} from "../modules/metrics-helper.js";
|
|
import * as api from "../modules/api-client.js";
|
|
import { testData } from "../modules/test-data.js";
|
|
|
|
const BASE_URL = __ENV.BASE_URL || "http://202.46.28.160:8080";
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
location_stress: {
|
|
executor: "ramping-vus",
|
|
startVUs: 0,
|
|
stages: [
|
|
{ duration: "30s", target: 20 }, // ramp-up
|
|
{ duration: "90s", target: 50 }, // sustain at 50 walking users
|
|
{ duration: "60s", target: 100 }, // peak load
|
|
{ duration: "30s", target: 0 }, // ramp-down
|
|
],
|
|
gracefulRampDown: "15s",
|
|
},
|
|
},
|
|
thresholds: pickThresholds(
|
|
__ENV.BENCH_PROFILE === "local"
|
|
? {
|
|
http_req_duration: ["p(95)<35000", "p(99)<40000"],
|
|
walkguide_location_latency_ms: ["p(95)<3000", "p(99)<5000"],
|
|
}
|
|
: {
|
|
...DEFAULT_THRESHOLDS,
|
|
walkguide_location_latency_ms: ["p(95)<300", "p(99)<600"],
|
|
http_req_duration: ["p(95)<400"],
|
|
},
|
|
),
|
|
};
|
|
|
|
// ── VU shared state (tiap VU punya token sendiri) ─────────────────────────────
|
|
let vuTokens = null;
|
|
let vuBaseLat = null;
|
|
let vuBaseLng = null;
|
|
|
|
// ── Main VU function ──────────────────────────────────────────────────────────
|
|
export default function locationStress() {
|
|
// ── Inisialisasi: register + login sekali per VU ───────────────────────────
|
|
if (!vuTokens) {
|
|
const suffix = `loc_${__VU}_${Date.now()}`;
|
|
const payload = testData.userRegisterPayload(suffix);
|
|
const res = api.register(payload);
|
|
|
|
if (res.status === 200) {
|
|
const body = api.parseBody(res);
|
|
if (body && body.data) vuTokens = body.data;
|
|
}
|
|
|
|
if (!vuTokens) {
|
|
console.error(`[location] VU ${__VU} failed to get tokens`);
|
|
sleep(2);
|
|
return;
|
|
}
|
|
|
|
// Posisi awal acak di Surabaya
|
|
const coord = testData.randomSurabayaCoord(0.05);
|
|
vuBaseLat = coord.lat;
|
|
vuBaseLng = coord.lng;
|
|
|
|
// Start walkguide session
|
|
const startRes = api.startWalkguide(vuTokens.accessToken);
|
|
check(startRes, {
|
|
"walkguide-start: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
sleep(0.5);
|
|
}
|
|
|
|
// ── Poll actuator untuk JVM heap (hanya VU 1, tidak mengganggu tes lain) ────
|
|
if (__VU === 1 && __ITER % 10 === 0) {
|
|
metricsHelper.pollJvmHeap(BASE_URL);
|
|
metricsHelper.pollDbConnections(BASE_URL);
|
|
}
|
|
|
|
// ── Simulasi walking: kirim 3 location update berturut-turut (15 detik real) ─
|
|
for (let i = 0; i < 3; i++) {
|
|
const locPayload = testData.locationUpdatePayload(vuBaseLat, vuBaseLng);
|
|
|
|
const res = api.updateLocation(
|
|
vuTokens.accessToken,
|
|
locPayload.lat,
|
|
locPayload.lng,
|
|
locPayload.accuracy,
|
|
locPayload.speed,
|
|
locPayload.heading,
|
|
);
|
|
|
|
check(res, {
|
|
"location-update: status 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"location-update: latency ok": (r) => r.timings.duration < 500,
|
|
});
|
|
|
|
// Update base coordinate (simulasi pergerakan)
|
|
vuBaseLat += testData.randomFloat(-0.0003, 0.0003);
|
|
vuBaseLng += testData.randomFloat(-0.0003, 0.0003);
|
|
|
|
// 5 detik interval seperti production
|
|
sleep(5);
|
|
}
|
|
|
|
// ── Kadang Guardian juga poll lokasi (setiap 10 iteration) ──────────────────
|
|
// Ini simulasi Guardian membuka map screen
|
|
if (__ITER % 5 === 0 && vuTokens) {
|
|
// Re-login as guardian to test guardian endpoint
|
|
// Dalam real load test, Guardian VU terpisah — di sini kita skip
|
|
// karena token kita adalah ROLE_USER
|
|
}
|
|
}
|
|
|
|
// ── Setup: siapkan backend ────────────────────────────────────────────────────
|
|
export function setup() {
|
|
const res = api.ping();
|
|
if (res.status !== 200)
|
|
throw new Error(`Backend not reachable: ${res.status}`);
|
|
console.log(`✅ Location stress test starting. Backend: ${BASE_URL}`);
|
|
return { startTime: Date.now() };
|
|
}
|
|
|
|
// ── Teardown: stop semua walkguide session ────────────────────────────────────
|
|
export function teardown(data) {
|
|
console.log(
|
|
`Location stress test finished. Duration: ${(Date.now() - data.startTime) / 1000}s`,
|
|
);
|
|
// Note: individual VU stop walkguide tidak bisa dilakukan di teardown
|
|
// karena token sudah tidak tersedia. Dalam production, session timeout handles ini.
|
|
}
|
|
|
|
export { handleSummary };
|