Überspringen zum Hauptinhalt

Warum wiederholte Kaufversuche doppelte Berechtigungen erzeugen und wie man sie testet

Original Persistium Kaufbuchdiagramm zeigt eine Absicht, einen dauerhaften Datensatz und eine Wiedergabe-sichere Berechtigungsentscheidung.

Wie man Kaufabsicht, unbekannte Commit-Ergebnisse, Wiederholungen und Berechtigungs-Einzigartigkeit modelliert, damit ein Kauf sicher wiederholt werden kann, ohne zweimal zu gewähren.

Ein Retry ist keine zweite Kaufentscheidung

Kaufabläufe scheitern im Zwischenraum zwischen einem externen Zahlungsereignis und einem Zuschuss im Spiel. Eine Quittung kann zweimal eintreffen. Eine Netzwerkanfrage kann nach dem Festlegen des Servers, aber bevor der Client die Antwort erhalten hat, ablaufen. Ein Prozess kann nach dem Reservieren einer Transaktion abstürzen, aber vor der Gewährung einer Währung. Beim Neustart kann die sicherste Aktion darin bestehen, unterbrochene Arbeiten erneut zu versuchen. Wenn das System jeden Wiederholungsversuch als Erlaubnis behandelt, sind doppelte Berechtigungen eine normale Folge der Wiederherstellung.

Die sinnvolle Unterscheidung ist Absicht gegen Gewährung. Absicht ist die Anforderung, ein bestimmtes Produkt unter einer bestimmten Transaktionsidentität zu erhalten. Grant ist das dauerhafte Spielergebnis: Rechteinhaberschaft, ein Währungsdelta, ein Inventarartikel oder eine Abonnementperiode. Die gleiche Absicht kann mehrmals geliefert, abgefragt, wiederholt oder erneut zugestellt werden. Es sollte immer noch zu einer Finanzhilfeentscheidung führen.

Dies ist ein technisches Muster, keine plattformspezifische Garantie. Verschiedene Geschäfte, Zahlungsanbieter und Spiel-Backends zeigen unterschiedliches Quittungs-, Bestätigungs- und Rückerstattungsverhalten. Gehen Sie nicht davon aus, dass eine Quittung einen Zuschuss beweist oder dass eine Bestätigung beweist, dass der Spieler einen Gegenstand gesehen hat. Bauen Sie den serverseitigen Datensatz auf, damit das Spiel angeben kann, was es weiß, und erholen Sie sich sicher, wenn ein externes Ergebnis unvollständig ist oder sich verzögert.

Geben Sie jeder Kaufabsicht einen stabilen Schlüssel

Ein Idempotenz-Schlüssel bindet wiederholte Zustellversuche an eine Entscheidung. Er kann von einer vertrauenswürdigen Plattform-Transaktionskennung abgeleitet werden, wenn diese verfügbar und verifiziert ist, oder er kann von einem Server ausgegeben werden, bevor ein Kauf beginnt und später mit vertrauenswürdigen Quittungsinformationen verknüpft wird. Der Schlüssel muss über Versuchsreihen hinweg stabil sein.

Speichern Sie genügend Kontext mit dem Schlüssel zur Ablehnung von Inkongruenzen: Spieler- oder Kontoumfang, Produktidentität, erwartete Menge oder Berechtigungsform, Quellkanal, empfangene Zeit, Verifizierungsstatus und ein Zustand wie z. B. ausstehendes, festgelegtes, abgelehntes oder Bedarfsprüfung. Halten Sie sensibles Empfangsmaterial aus gewöhnlichen Protokollen fern. Wenn Rohanbieter-Nutzlasten für einen verifizierten Wiederherstellungsfluss eine kurze Aufbewahrung benötigen, schützen Sie sie separat und machen Sie ihren Zugriff überlegt.

Das Datenmodell benötigt auch eine Eindeutigkeitsgrenze. Bei nicht verbrauchbaren Berechtigungen kann die Eindeutigkeit Konto plus Produkt-ID sein. Bei Währungen ist die Eindeutigkeit in der Regel die Ledger- oder Grant-Transaktion und nicht der aktuelle Saldo. Bei Verbrauchsgütern kann eine vertrauenswürdige Transaktionskennung auch dann eindeutig sein, wenn sich die Produkt-ID wiederholt. Definieren Sie den Schlüssel vor der Codierung der Retry-Richtlinie; andernfalls können zwei Subsysteme gegen inkompatible Identitäten deduplizieren.

Modellieren Sie das unbekannte Commit-Ergebnis

Das schwierige Ergebnis ist kein sauberer Erfolg oder ein sauberer Misserfolg. Es ist "unbekannt": der Client weiß nicht, ob der Server die Zuwendung zugesagt hat. Ein Timeout, ein Verbindungs-Reset, ein Prozessneustart oder ein Service-Ausfall kann diesen Zustand erzeugen. Das sichere Client-Verhalten besteht darin, nach dem Transaktionsstatus zu fragen oder die gleiche Absicht zu wiederholen. Das sichere Server-Verhalten besteht darin, diese Absicht nachzuschlagen und die dauerhafte Entscheidung zurückzugeben, anstatt eine weitere Mutation anzuwenden.

Machen Sie den Anzeigezustand des Kunden nicht autoritativ. Ein verschwindender Spinner, ein lokaler Quittungs-Cache oder eine optimistische Saldoänderung können die Erfahrung verbessern, aber er kann nicht entscheiden, ob das Konto eine Berechtigung besitzt. Serverautorität bedeutet, dass der Server die akzeptierte Transaktion gemäß der Vertrauensgrenze des Produkts überprüft, den dauerhaften Datensatz einmal festlegt und den aktuellen Zustand zurückgibt, wenn er erneut gefragt wird.

Das ursprüngliche Kaufsequenzdiagramm zeigt wiederholte Zustellversuche, die auf einem Ledger-Datensatz und einer Berechtigungsentscheidung konvergieren.
Retries und Quittungsrücklieferung lösen sich gegen die gleiche dauerhafte Kaufabsicht auf, anstatt neue Zuschüsse zu schaffen.

Die Sequenz sollte die Richtlinie zur teilweisen Fertigstellung sichtbar machen, z. B.: Absicht erhalten, vertrauenswürdige Kaufnachweise validieren, den dauerhaften Ledger-Datensatz erstellen oder laden, die Berechtigungs- oder Währungsmutation festlegen, den gewährten Datensatz markieren, die externe Lieferung gegebenenfalls bestätigen und dann das Ergebnis zurückgeben. Wenn der Prozess zwischen zwei Schritten stoppt, kann eine Statusabfrage eines Wiederherstellungsarbeiters oder einer Statusabfrage später aus dem dauerhaften Datensatz fortgesetzt werden. Die genaue Bestellung hängt vom externen Anbieter und der Spielarchitektur ab, die Identität der einzelnen Finanzhilfe jedoch nicht.

Schutz von Zahlungsansprüchen und Währungsinvarianten

Ein idempotency-Schlüssel verhindert die Wiederholung einer Absicht; er macht nicht automatisch jeden Nebeneffekt korrekt. Definieren Sie die Invarianten, die ein Grant bewahren muss. Ein nicht verbrauchbarer Anspruch erscheint höchstens einmal für das Konto und das Produkt. Ein Currency Grant hat einen Ledger-Eintrag mit einem Transaktionsschlüssel, einem bekannten Delta und einem resultierenden Saldo, der der Summe der gültigen Einträge entspricht.

Eine Lektüre, gefolgt von einem späteren Schreiben, kann unter gleichzeitiger Lieferung laufen. Zwei Arbeiter können sowohl "nicht besessen" beobachten als auch beide gewähren. Verwenden Sie Transaktionsspeicher, Vergleichs- und Set-Semantik, einen serialisierten Account-Mutationspfad oder ein anderes explizites Gleichzeitigkeitsprimitiv, das für den Datenspeicher geeignet ist. Die wichtige Eigenschaft ist, dass die Entscheidung und ihr Marker nicht unabhängig voneinander durch zwei Versuche gewonnen werden können.

Bei Spielen mit einer In-Memory-Laufzeit ist zwischen dauerhaftem Erfolg und Präsentation zu unterscheiden. Der Server kann den sichtbaren Saldo eines Spielers aktualisieren, nachdem der dauerhafte Ledger-Eintrag übergeben wurde, aber das sichtbare Update ist nicht der Beweis.

Testabstürze, Neustarts und bewusste Wiederlieferung

Beginnen Sie mit einem deterministischen Szenario. Erstellen Sie ein Konto, ein Produkt, einen bekannten Startsaldo oder Berechtigungssatz und einen stabilen Transaktionsschlüssel. Führen Sie den Flow aus und injizieren Sie dann nach jeder benannten Grenze einen Fehler: nach Empfangsannahme, nach Ledgererstellung, nach Berechtigungsmutation, nach Statusmarkierung, nach externer Bestätigung und nach Vorbereitung der Antwort. Starten Sie den betreffenden Worker oder Prozess neu, versuchen Sie denselben Schlüssel erneut und behaupten Sie den endgültigen dauerhaften Zustand.

Das erwartete Ergebnis sollte spezifisch sein. Ein Wiederholungsversuch kann mit dem ursprünglichen Ergebnis „bereits gewährt zurückgeben, eine ausstehende Operation wieder aufnehmen, eine nicht übereinstimmende Nutzlast ablehnen oder einen Datensatz für die Überprüfung aufbewahren. Er sollte kein zweites Inventarelement hinzufügen, ein zweites Währungsdelta anwenden oder den unbekannten Zustand mit einem erfundenen Erfolg verbergen. Erfassen Sie die Klassifizierung im Testergebnis, damit ein späterer Refaktor ein absichtliches Halten nicht in ein zufälliges Duplikat verwandeln kann.

Verwenden Sie die Quittungswiederlieferung im selben Szenario. Liefern Sie die genaue vertrauenswürdige Transaktion zweimal, dann liefern Sie sie nach einem Neustart, dann liefern Sie sie zusammen mit einem doppelten Client-Wiederholversuch. Das resultierende Hauptbuch und der Kontostatus sollten mit dem Fall der Einzellieferung identisch sein. Wenn das Produkt wiederholte Käufe erlaubt, führen Sie die gleiche Sequenz mit zwei wirklich unterschiedlichen Transaktionsidentitäten aus, um zu beweisen, dass das System nicht durch die Produkt-ID allein überdedupliziert wird.

Halten Sie die Grenzen ehrlich

Das Testen kann nur die Interaktionen beweisen, die Sie ausführen. Eine simulierte Provider-Antwort kann Ihre Zustandsmaschine validieren, aber es ist kein Beweis dafür, dass sich jeder Produktionsanbieter-Vorsprung genau gleich verhält. Ein ausführbarer Test gegen eine Sandbox kann Vertrauen für diese Integration schaffen, hat aber immer noch andere Betriebsbedingungen als ein Live-Shop. Aufzeichnen, ob ein Szenario eine Simulation, einen lokalen Adapter, eine Sandbox oder eine verifizierte Provider-Umgebung verwendet.

Die Vertrauensgrenze sollte auch klar sein. Ein Client sollte keinen willkürlichen Betrag, keine Produkt-ID oder ein "verifiziertes" Flag einreichen und einen Zuschuss erhalten. Eingaben werden nicht vertrauenswürdig, bis der Server sie gegen die entsprechende Konfiguration und den Kaufnachweis validiert. Wenn die Validierung nicht abgeschlossen werden kann, halten Sie die Absicht an oder lehnen Sie sie mit einer wiederherstellbaren Kategorie ab. Lassen Sie eine Wiederholungswarteschlange nicht zu einem Bypass um die Überprüfung werden.

Für diese Testdisziplin gilt der Datenschutz. Fixtures sollten synthetische Transaktionsdaten verwenden. Logs sollten auf eine sichere Testkennung verweisen, nicht auf einen rohen Quittungs- oder Kontonamen. Ein Produktionsvorfall kann eingeschränkte Beweise erfordern, aber die Routine-Testsuite sollte niemals zu einem zweiten Zahlungsdatenspeicher werden.

Praktische Checkliste

  • Trennen Sie eine stabile Kaufabsicht von der späteren Spielseite.
  • Verwenden Sie einen Idempotenzschlüssel für Timeouts, Retries, Neustarts und Quittungszustellung.
  • Binden Sie den Schlüssel an das Konto, das Produkt- oder Berechtigungsformular und den vertrauenswürdigen Quellkontext.
  • Definieren Sie dauerhafte Zustände wie anhängig, engagiert, abgelehnt und Bedarfsprüfung.
  • Erzwingen Sie die Eindeutigkeit von Berechtigungen und Währungsbuch-Invarianten innerhalb derselben Parallelitätsgrenze wie die Gewährung.
  • Injizieren Sie Fehler nach jedem Zustandsübergang, starten Sie dann neu und wiederholen Sie die gleiche Absicht.
  • Testen Sie doppelte Lieferung und legitime Wiederholungskäufe separat.
  • Melden Sie unbekannte Ergebnisse ehrlich; Verwandeln Sie kein Timeout in einen erfundenen Erfolg.
  • Halten Sie quittungsähnliche Armaturen und Testprotokolle synthetisch und redigiert.

Häufig gestellte Fragen

Ist eine eindeutige Quittungs-ID genug für Idempotenz?

Es kann eine nützliche Komponente sein, wenn der Server überprüfen kann, ob die Quittungsidentität vertrauenswürdig ist und sie korrekt ausführt. Es ist immer noch wichtig, die resultierende Finanzhilfeentscheidung, die Dismatch-Richtlinie und den Wiederherstellungszustand zu speichern. Ein System kann den gleichen Bezeichner wiederholt erhalten, ihn verspätet erhalten oder ihn mit einer Nutzlast erhalten, die nicht mit dem gespeicherten Produktkontext übereinstimmt. Die dauerhafte Aufzeichnung macht diese Fälle inspizierbar.

Sollte ein Kunde nach einem Timeout automatisch erneut versuchen?

Normalerweise sollte es die Statusauflösung mit der gleichen Absichtsidentität wiederholen, mit begrenztem Backoff und klarem Benutzerfeedback. Ob es externe Kaufbeweise erneut einreichen sollte, hängt vom Anbieter und Verifizierungsdesign ab. Das unsichere Verhalten besteht darin, stillschweigend eine neue Kaufanfrage zu erstellen oder einen lokalen Zuschuss zu beantragen, weil die ursprüngliche Antwort verloren ging.

Wie unterscheiden sich Verbrauchsgüter von dauerhaften Ansprüchen?

Dauerhafte Ansprüche werden in der Regel nach Konten und Produkten dedupliziert. Verbrauchsmaterialien können es ermöglichen, das gleiche Produkt viele Male zu kaufen, so dass die Eindeutigkeitsgrenze eine Transaktionsidentität oder eine Ledgersequenz anstelle einer Produkt-ID enthalten muss.

Was behauptet Persistium hier?

Persistium befindet sich in der Entwicklung. In dieser Notiz werden allgemein anwendbare Integritäts- und Testdesignmuster erläutert; es wird kein öffentliches Kaufprodukt, keine Plattformzertifizierung, keine Kundenvorfallhistorie oder ein gehosteter Dienst beansprucht. Seine Kontinuitätsrichtung ist an der gleichen Art von Beleg und replaysicherer Wiederherstellungsdisziplin interessiert.

Verbundenes SystemEntdecken Sie Persistium