Idempotentiškumas
Kaip su Idempotency-Key saugiai kartoti POST užklausas ir nesukurti dublių.
Kam to reikia
Jei POST /library/imports užklausa nutrūko ir nežinote, ar importas buvo sukurtas, pakartojus ją galėtų atsirasti antras importas. Idempotency-Key tai išsprendžia: pakartotą užklausą su tuo pačiu raktu API atpažįsta ir grąžina tą patį rezultatą, o nauja operacija nepradedama.
Antraštė palaikoma visoms POST užklausoms. Ją rekomenduojame siųsti su POST /library/imports.
POST /api/v1/library/imports
Authorization: Bearer dk_live_...
Content-Type: application/json
Idempotency-Key: 8f3a5c2e-1b7d-4e90-a6c4-2d9b0e7f5a13Taisyklės
| Taisyklė | Reikšmė |
|---|---|
| Formatas | 8–255 simbolių iš aibės A-Za-z0-9_-:.. Priimama ir kabutėse ("abc...", IETF Structured Field forma) |
| Taikymo sritis | naudotojas: tas pats Idempotency-Key galioja visiems jo API raktams |
| Saugojimas | 24 valandos |
| Pakartojimas | grąžinamas tas pats statusas ir turinys su antrašte Idempotent-Replayed: true |
| Tas pats raktas, kita užklausa | 422 idempotency_key_reused. Lyginamas metodas, kelias ir kanoninis JSON turinys |
| Lygiagreti užklausa | 409 idempotency_in_progress su Retry-After (likusios sekundės) |
| Netinkamas raktas | 400 idempotency_key_invalid |
Vykdoma užklausa užrakinama 60 sekundžių. Jei jos vykdymas nutrūksta, kitas bandymas su tuo pačiu raktu gali ją perimti pasibaigus užraktui.
Kas išsaugoma, o kas ne
Išsaugomi tik 2xx atsakymai ir deterministinės klaidos: 400, 404, 413, 415, 422. Atsakymai 402, 403, 408, 409, 429 ir 5xx neišsaugomi, o raktas atlaisvinamas. Todėl po tokios klaidos tą pačią užklausą su tuo pačiu raktu galite saugiai kartoti, kai problema išspręsta (pavyzdžiui, papildėte kreditus po 402).
Atsakymai, kuriuose būtų paslapčių, niekada nesaugomi. v1 API tokių atsakymų negrąžina.
Kaip naudoti
- Prieš pirmą bandymą sugeneruokite naują UUID ir išsaugokite jį kartu su operacija.
- Siųskite tą patį raktą kiekvienam tos pačios operacijos bandymui.
- Naujai operacijai generuokite naują raktą. Nenaudokite pastovios reikšmės, pavyzdžiui,
"import": antra užklausa su kitu turiniu gautų 422, o su tuo pačiu turiniu per 24 val. gautų seną atsakymą.
import os
import uuid
import requests
key = str(uuid.uuid4()) # sukuriama vieną kartą ir saugoma kartu su operacija
last_error = None
for attempt in range(3):
try:
response = requests.post(
"https://api.diko.app/api/v1/library/imports",
headers={
"Authorization": f"Bearer {os.environ['DIKO_API_KEY']}",
"Idempotency-Key": key,
},
json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
timeout=30,
)
break
except (requests.ConnectionError, requests.Timeout) as error:
last_error = error # tas pats raktas: pakartojimas dublio nesukurs
else:
raise last_error # nepavyko nė vienas iš 3 bandymų
if response.headers.get("Idempotent-Replayed") == "true":
print("Tai ankstesnės užklausos rezultatas")const key = crypto.randomUUID() // sukuriama vieną kartą ir saugoma kartu su operacija
let response: Response | undefined
for (let attempt = 0; attempt < 3 && !response; attempt++) {
try {
response = await fetch("https://api.diko.app/api/v1/library/imports", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DIKO_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": key, // tas pats raktas: dublio nebus
},
body: JSON.stringify({ url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }),
signal: AbortSignal.timeout(30_000),
})
} catch {
// tinklo klaida arba pasibaigė skirtasis laikas: kartojame su tuo pačiu raktu
}
}
if (!response) throw new Error("Per 3 bandymus atsakymo negauta")
if (response.headers.get("Idempotent-Replayed") === "true") console.log("Tai ankstesnės užklausos rezultatas")