Konzepte
Idempotenz
Senden Sie bei einem POST einen Idempotency-Key mit. Eine Wiederholung nach einem Verbindungsabbruch erhält dann die erste Antwort, statt jemanden doppelt anzumelden.
Warum
Eine Verbindung kann abbrechen, nachdem AttendBeacon jemanden angemeldet hat, aber bevor Ihr Code davon erfahren hat. Erneut gesendet, würde derselbe POST ein zweites Ticket ausstellen. Mit einem Idempotency-Key passiert das nicht: Die zweite Anfrage bekommt die Antwort der ersten.
Wie
Erzeugen Sie für jede Anfrage einen eigenen Schlüssel (ideal ist eine UUID) und senden Sie ihn mit dem POST. Bewahren Sie ihn zusammen mit der Anfrage auf, bis Sie eine Antwort haben, und senden Sie bei jeder Wiederholung denselben Schlüssel.
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))
}
}Was gespeichert wird, und wie lange
Die erste Antwort auf einen Schlüssel (ihr Status, Location und Body) wird 24 Stunden lang aufbewahrt und jeder Anfrage mit demselben Schlüssel, derselben Methode, demselben Pfad und demselben Body erneut gegeben. Eine wiederholte Antwort trägt Idempotent-Replayed: true.
| Situation | Antwort |
|---|---|
| Wiederholung einer Anfrage, die beantwortet wurde | Die erste Antwort, mit Idempotent-Replayed: true |
| Wiederholung, während die erste noch bearbeitet wird | 409 idempotencyKeyInUse, mit Retry-After: 1 |
| Derselbe Schlüssel mit anderer Methode, anderem Pfad oder Body | 422 idempotencyKeyReused: Verwenden Sie für eine neue Anfrage einen neuen Schlüssel |
| Ein Schlüssel mit mehr als 255 Zeichen oder mit Leerzeichen | 400 invalidIdempotencyKey |
| Die erste Anfrage ist bei AttendBeacon gescheitert (5xx) | Nichts wird gespeichert, die Wiederholung wird neu bearbeitet |
Ein Idempotency-Key gehört zu dem API-Schlüssel, der ihn gesendet hat: Zwei Integrationen können sich nicht in die Quere kommen. Die gespeicherten Antworten können eine Person nennen; löscht diese Person ihre Daten, werden auch die Antworten gelöscht, die sie nennen.
Welche Aufrufe
Jeder POST nimmt einen Idempotency-Key an: Anmelden, Tickets ausstellen, Stornieren, Einchecken und das Erstellen von Veranstaltungen, Sessions, Rabattcodes und Webhooks. PATCH, PUT und DELETE lassen sich ihrer Natur nach gefahrlos wiederholen. PATCH nimmt stattdessen If-Match an, damit eine zwischenzeitliche Änderung nicht überschrieben wird (Fehler, preconditionFailed).