Scale unique answer tracking

This commit is contained in:
hz
2026-07-13 02:11:54 -05:00
parent 700da4e415
commit f2c59388eb
23 changed files with 1064 additions and 131 deletions
+76
View File
@@ -0,0 +1,76 @@
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);
}