Begreper
Idempotens
Send en Idempotency-Key med en POST, så får et nytt forsøk etter en tapt forbindelse det første svaret i stedet for å melde på noen to ganger.
Hvorfor
En forbindelse kan bli brutt etter at AttendBeacon har meldt på noen, men før koden din fikk vite det. Sendt på nytt ville den samme POST-en utstedt en ny billett. Med en Idempotency-Key skjer ikke det: den andre forespørselen får svaret på den første.
Slik gjør du det
Lag din egen nøkkel for hver forespørsel (en UUID er ideelt) og send den med POST-en. Ta vare på den sammen med forespørselen til du har fått et svar, og send den samme nøkkelen med hvert nytt forsøk.
curl -X POST "https://attendbeacon.com/api/v1/events/b3ac0000-0000-4000-8000-000000000001/registrations" \
-H "Authorization: Bearer $ATTENDBEACON_KEY" \
-H "Idempotency-Key: 6f1c2a9e-4b7d-4c0f-8e3a-5b9d1c7e0f42" \
-H "Content-Type: application/json" \
-d '{ "ticketTypeId": "b3ac0006-0000-4000-8000-000000000001", "firstName": "Anna", "lastName": "de Vries", "email": "anna.devries@example.com" }'const idempotencyKey = crypto.randomUUID(); // once per registration, kept for its retries
async function register(person) {
for (let attempt = 1; ; attempt++) {
try {
const response = await fetch(`${base}/events/${eventId}/registrations`, {
method: "POST",
headers: { Authorization: `Bearer ${key}`, "Idempotency-Key": idempotencyKey, "Content-Type": "application/json" },
body: JSON.stringify(person)
});
if (response.status < 500) return response; // an answer: the first, or the first again
} catch { /* the connection dropped: try again with the same key */ }
if (attempt === 4) throw new Error("AttendBeacon did not answer.");
await new Promise((resolve) => setTimeout(resolve, 2 ** attempt * 1000));
}
}var idempotencyKey = Guid.NewGuid().ToString(); // once per registration, kept for its retries
for (var attempt = 1; ; attempt++)
{
using var request = new HttpRequestMessage(HttpMethod.Post, $"events/{eventId}/registrations") { Content = JsonContent.Create(person) };
request.Headers.Add("Idempotency-Key", idempotencyKey);
try
{
using var response = await client.SendAsync(request);
if ((int)response.StatusCode < 500) return await response.Content.ReadFromJsonAsync<JsonElement>();
}
catch (HttpRequestException) { /* try again with the same key */ }
if (attempt == 4) throw new InvalidOperationException("AttendBeacon did not answer.");
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}idempotency_key = str(uuid.uuid4()) # once per registration, kept for its retries
for attempt in range(1, 5):
try:
response = requests.post(
f"{base}/events/{event_id}/registrations",
headers={"Authorization": f"Bearer {key}", "Idempotency-Key": idempotency_key},
json=person,
timeout=30,
)
if response.status_code < 500:
break # an answer: the first, or the first again
except requests.ConnectionError:
pass # try again with the same key
time.sleep(2 ** attempt)$idempotencyKey = [guid]::NewGuid().ToString() # once per registration, kept for its retries
$headers["Idempotency-Key"] = $idempotencyKey
$body = $person | ConvertTo-Json
foreach ($attempt in 1..4) {
try {
$attendee = Invoke-RestMethod -Method Post -Uri "$base/events/$eventId/registrations" -Headers $headers -ContentType "application/json" -Body $body
break
} catch {
if ($_.Exception.Response -and [int]$_.Exception.Response.StatusCode -lt 500) { throw }
Start-Sleep -Seconds ([math]::Pow(2, $attempt))
}
}Hva som lagres, og hvor lenge
Det første svaret på en nøkkel (statusen, Location og innholdet) lagres i 24 timer og gis på nytt til enhver forespørsel med samme nøkkel, metode, sti og innhold. Et gjentatt svar har med Idempotent-Replayed: true.
| Situasjon | Svar |
|---|---|
| Et nytt forsøk på en forespørsel som er besvart | Det første svaret, med Idempotent-Replayed: true |
| Et nytt forsøk mens den første fortsatt behandles | 409 idempotencyKeyInUse, med Retry-After: 1 |
| Samme nøkkel med en annen metode, sti eller et annet innhold | 422 idempotencyKeyReused: bruk en ny nøkkel for en ny forespørsel |
| En nøkkel som er lengre enn 255 tegn, eller som har mellomrom | 400 invalidIdempotencyKey |
| Den første forespørselen mislyktes hos AttendBeacon (5xx) | Ingenting lagres, så det nye forsøket behandles på nytt |
En nøkkel tilhører API-nøkkelen som sendte den: to integrasjoner kan ikke kollidere. De lagrede svarene kan navngi en person; når den personen sletter dataene sine, slettes også svarene som navngir personen.
Hvilke kall
Hver POST tar en Idempotency-Key: påmelding, utstedelse av billetter, avbestilling, innsjekking og oppretting av arrangementer, økter, rabattkoder og webhooks. PATCH, PUT og DELETE er av natur trygge å gjenta; PATCH tar i stedet If-Match, slik at en endring gjort i mellomtiden ikke overskrives (Feil, preconditionFailed).