77 lines
2.3 KiB
JavaScript
77 lines
2.3 KiB
JavaScript
import http from "k6/http";
|
|
import { check, sleep } from "k6";
|
|
import { SharedArray } from "k6/data";
|
|
|
|
const baseUrl = __ENV.BASE_URL || "https://s3q.ranaze.com";
|
|
const tokenPath = __ENV.AUTH_TOKENS_PATH || "./tokens.json";
|
|
const tokens = new SharedArray("test-user tokens", () => JSON.parse(open(tokenPath)));
|
|
|
|
if (tokens.length < 5000) {
|
|
throw new Error("The load test requires at least 5,000 distinct USER tokens.");
|
|
}
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
answer_tracking: {
|
|
executor: "ramping-vus",
|
|
startVUs: 0,
|
|
stages: [
|
|
{ duration: "2m", target: 5000 },
|
|
{ duration: "5m", target: 5000 },
|
|
{ duration: "1m", target: 0 },
|
|
],
|
|
gracefulRampDown: "30s",
|
|
},
|
|
},
|
|
thresholds: {
|
|
http_req_failed: ["rate<0.01"],
|
|
"http_req_duration{operation:search}": ["p(95)<1000"],
|
|
"http_req_duration{operation:answer}": ["p(95)<500"],
|
|
},
|
|
};
|
|
|
|
export default function () {
|
|
const token = tokens[(__VU - 1) % tokens.length];
|
|
const headers = {
|
|
Authorization: `Bearer ${token}`,
|
|
"Content-Type": "application/json",
|
|
};
|
|
|
|
const search = http.post(
|
|
`${baseUrl}/api/questions/search`,
|
|
JSON.stringify({ limit: 80 }),
|
|
{ headers, tags: { operation: "search" } },
|
|
);
|
|
if (!check(search, { "search succeeded": (response) => response.status === 200 })) {
|
|
sleep(1);
|
|
return;
|
|
}
|
|
|
|
const questions = search.json();
|
|
if (!questions || questions.length === 0) {
|
|
sleep(1);
|
|
return;
|
|
}
|
|
|
|
const question = questions[Math.floor(Math.random() * questions.length)];
|
|
if (Math.random() < 0.1) {
|
|
const skipped = http.post(
|
|
`${baseUrl}/api/questions/${encodeURIComponent(question.externalId)}/skip`,
|
|
null,
|
|
{ headers, tags: { operation: "answer" } },
|
|
);
|
|
check(skipped, { "skip recorded": (response) => response.status === 200 });
|
|
sleep(Math.random() * 2 + 1);
|
|
return;
|
|
}
|
|
|
|
const choice = question.choices[Math.floor(Math.random() * question.choices.length)];
|
|
const answer = http.post(
|
|
`${baseUrl}/api/questions/attempts/first`,
|
|
JSON.stringify({ questionExternalId: question.externalId, choiceId: choice.id }),
|
|
{ headers, tags: { operation: "answer" } },
|
|
);
|
|
check(answer, { "answer recorded": (response) => response.status === 200 });
|
|
sleep(Math.random() * 2 + 1);
|
|
}
|