fix: support idempotent actions over HTTP
CI / test (pull_request) Canceled after 1m25s
PR合并自动部署 / release-check (pull_request) Successful in 1m44s
PR合并自动部署 / deploy (pull_request) Failing after 10s

This commit is contained in:
2026-08-09 00:20:48 +08:00
parent 7c9e0303b9
commit 8aad781581
3 changed files with 54 additions and 3 deletions
+28 -2
View File
@@ -17,6 +17,32 @@ function csrfToken() {
return match ? decodeURIComponent(match[1]) : "";
}
function createIdempotencyKey() {
const cryptoApi = globalThis.crypto;
if (typeof cryptoApi?.randomUUID === "function") {
return cryptoApi.randomUUID();
}
const bytes = new Uint8Array(16);
if (typeof cryptoApi?.getRandomValues === "function") {
cryptoApi.getRandomValues(bytes);
} else {
for (let index = 0; index < bytes.length; index += 1) {
bytes[index] = Math.floor(Math.random() * 256);
}
}
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = [...bytes].map((value) => value.toString(16).padStart(2, "0"));
return [
hex.slice(0, 4).join(""),
hex.slice(4, 6).join(""),
hex.slice(6, 8).join(""),
hex.slice(8, 10).join(""),
hex.slice(10).join(""),
].join("-");
}
async function api(path, options = {}) {
const headers = { Accept: "application/json", ...(options.headers || {}) };
if (options.body && typeof options.body !== "string") {
@@ -165,7 +191,7 @@ function renderStoryNode(run) {
try {
const next = await api(`math-life/runs/${run.run_id}/choice/`, {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
headers: { "Idempotency-Key": createIdempotencyKey() },
body: { choice_index: choice.index },
});
renderStoryNode(next);
@@ -341,7 +367,7 @@ function renderAttempt(attempt) {
try {
const result = await api(`contests/attempts/${attempt.attempt_id}/submit/`, {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
headers: { "Idempotency-Key": createIdempotencyKey() },
body: { answers },
});
renderAttempt(result);