Käsitteet
Idempotenssi
Lähetä POST-kutsun mukana Idempotency-Key, niin katkenneen yhteyden jälkeiseen uudelleenyritykseen vastataan ensimmäisellä vastauksella eikä ketään ilmoiteta kahdesti.
Miksi
Yhteys voi katketa sen jälkeen, kun AttendBeacon on ilmoittanut jonkun, mutta ennen kuin koodisi on saanut siitä tiedon. Uudelleen lähetettynä sama POST myöntäisi toisen lipun. Idempotency-Key-avaimen kanssa niin ei käy: toinen pyyntö saa ensimmäisen vastauksen.
Miten
Luo jokaiselle pyynnölle oma avain (UUID on ihanteellinen) ja lähetä se POST-kutsun mukana. Säilytä se pyynnön kanssa, kunnes saat vastauksen, ja lähetä sama avain jokaisessa uudelleenyrityksessä.
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))
}
}Mitä säilytetään ja kuinka kauan
Avaimen ensimmäinen vastaus (sen tila, Location ja runko) säilytetään 24 tuntia, ja se annetaan uudelleen jokaiselle pyynnölle, jolla on sama avain, metodi, polku ja runko. Toistetussa vastauksessa on Idempotent-Replayed: true.
| Tilanne | Vastaus |
|---|---|
| Uudelleenyritys pyynnölle, johon on vastattu | Ensimmäinen vastaus, jossa Idempotent-Replayed: true |
| Uudelleenyritys, kun ensimmäistä käsitellään vielä | 409 idempotencyKeyInUse, jossa Retry-After: 1 |
| Sama avain eri metodilla, polulla tai rungolla | 422 idempotencyKeyReused: käytä uudelle pyynnölle uutta avainta |
| Yli 255 merkin tai välilyöntejä sisältävä avain | 400 invalidIdempotencyKey |
| Ensimmäinen pyyntö epäonnistui AttendBeaconin päässä (5xx) | Mitään ei säilytetä, joten uudelleenyritys käsitellään alusta |
Avain kuuluu sen lähettäneelle API-avaimelle: kaksi integraatiota ei voi törmätä. Säilytetyissä vastauksissa voi olla henkilön nimi; kun henkilö poistaa tietonsa, häntä koskevat vastaukset poistetaan myös.
Mitkä kutsut
Jokainen POST ottaa vastaan Idempotency-Key-avaimen: ilmoittautuminen, lippujen myöntäminen, peruminen, sisäänkirjaus sekä tapahtumien, ohjelmaosuuksien, alennuskoodien ja webhookien luominen. PATCH, PUT ja DELETE ovat luonnostaan turvallisia toistaa; PATCH ottaa sen sijaan If-Match-otsakkeen, jotta välissä tehtyä muutosta ei kirjoiteta yli (Virheet, preconditionFailed).