Zugehörige Ticket-Aktualisierungen konsistent halten

CloudflareBeginner
Jetzt üben

Einführung

Ein Ticket darf erst geschlossen werden, wenn die zugehörige Lösungsnotiz gespeichert wurde. Sie verwenden einen vorbereiteten D1-Batch, damit beide Schreibvorgänge gemeinsam ausgeführt werden. Anschließend übertragen Sie ein Lesezeichen der Sessions API zwischen den Anfragen, sodass spätere Lesevorgänge bereits bestätigte Änderungen sehen können.

In diesem Lab unterscheiden Sie zwischen atomarem Rollback und sequenzieller Konsistenz innerhalb einer Sitzung. Sie verwenden eine unabhängige Datenbank und einen Worker. Lesereplikate müssen nicht aktiviert werden, und ein Replikationskonflikt muss nicht nachgestellt werden.

Verwenden Sie Ihr eigenes Lernkonto und eine frische VM. Die Einrichtung installiert zunächst Node.js 22.22.0. Danach führt sie npm install für Wrangler 4.131.1 als projektspezifische Version sowie für alle Abhängigkeiten der Bewertung unter /home/labex/project/ticket-database aus. Die direkten Abhängigkeitsversionen sind festgelegt; bei der Installation wird eine eigene Lockdatei erstellt. Während der Einrichtung erfolgt weder eine Cloud-Anmeldung noch eine bewertete Arbeit an der Datenbank. Installieren Sie auf einem persönlichen Rechner dieselbe Wrangler-Version mit npm install --save-dev wrangler@4.131.1 in Ihrem Projekt.

Dieses Lab verwendet kleine synthetische Datensätze innerhalb der kostenlosen D1-Kontingente. Die bisherige Nutzung Ihres Kontos wird auf diese Kontingente angerechnet. Eine gekaufte Domain ist nicht erforderlich. Behalten Sie diese VM, bis sowohl die Ressourcenlöschung als auch die Abmeldung überprüft wurden.

Diese VM autorisieren und das Konto auswählen

In diesem Schritt verbinden Sie dieses frische Terminal mit Ihrem eigenen Lernkonto. Eine Anmeldung im Dashboard autorisiert die VM allein nicht. Die D1-Berechtigung erlaubt das Erstellen, Ändern und Löschen von Datenbanken. Die Workers-Berechtigung ermöglicht Deployments, und die KV-Berechtigung unterstützt die Auflistung von Ressourcen bei der Wrangler-Bereinigung. Prüfen Sie die tatsächliche Zustimmungsseite einschließlich Background Access, bevor Sie die Autorisierung bestätigen.

Öffnen Sie das vorbereitete Projekt und prüfen Sie die festgelegte CLI-Version:

cd /home/labex/project/ticket-database
npx wrangler --version

Erwartet wird 4.131.1. Starten Sie die Geräteautorisierung. --device zeigt einen Browsercode an, und --browser=false überlässt Ihnen die Entscheidung, ob Sie den Browser öffnen:

npx wrangler login --device --browser=false --scopes account:read user:read d1:write workers_scripts:write workers_kv:write

Öffnen Sie die angezeigte URL im Browser, geben Sie den aktuellen Code ein, bestätigen Sie Ihr Lernkonto und die Berechtigungen und autorisieren Sie den Zugriff. Warten Sie, bis das Terminal den Erfolg bestätigt. Fügen Sie niemals Passwörter oder Tokens in Projektdateien ein.

npx wrangler whoami --json

Prüfen Sie loggedIn: true. Lesen Sie anschließend name und id des Kontos aus, auch wenn nur ein Konto aufgelistet wird. Kopieren Sie die ID des gewünschten Kontos in die folgende Konfiguration. Die folgende Shell-Variable verwendet 6 zufällige Bytes, also 12 hexadezimale Zeichen, um Kollisionen mit anderen Lernenden zu vermeiden. Ein Here-Dokument schreibt den JSON-Inhalt zwischen den Zeilen JSON; $RUN wird darin ersetzt.

Der umgekehrte Schrägstrich vor $schema erhält diesen JSON-Schlüssel unverändert; $RUN wird weiterhin durch den eindeutigen Namen dieses Durchlaufs ersetzt.

RUN=labex-c04-d05-$(openssl rand -hex 6)
cat > wrangler.jsonc <<JSON
{
  "\$schema": "./node_modules/wrangler/config-schema.json",
  "name": "$RUN",
  "account_id": "YOUR_ACCOUNT_ID",
  "main": "src/index.js",
  "compatibility_date": "2026-09-15",
  "workers_dev": true,
  "preview_urls": false
}
JSON

Ersetzen Sie YOUR_ACCOUNT_ID, bevor Sie den Block ausführen. Lassen Sie dieses Terminal geöffnet, damit RUN verfügbar bleibt. name bezeichnet diesen Durchlauf; account_id legt das Konto für Cloud-Vorgänge fest. Die Datei ist gewöhnlicher JSON-Code und damit auch gültiger JSONC-Code. Durch das Schreiben der Datei wird kein Worker bereitgestellt.

Tickets und Lösungsnotizen vorbereiten

In diesem Schritt bereiten Sie zwei miteinander verknüpfte Tabellen vor. Beim Schließen eines Tickets soll auch die zugehörige Lösungsnotiz gespeichert werden. Wenn nur einer der beiden Schreibvorgänge erfolgreich ist, sehen Mitarbeitende möglicherweise ein geschlossenes Ticket ohne Erklärung. Die Einrichtung stellt das Schema und den HTTP-Router bereit. Sie implementieren die zusammengehörigen SQL-Operationen.

Erstellen Sie eine temporäre Cloud-Datenbank. --binding DB gibt dem Anwendungscode einen kurzen Namen, --update-config speichert den tatsächlichen Namen und die UUID in wrangler.jsonc, und --use-remote=false hält die Entwicklung lokal:

npx wrangler d1 create "$RUN-db" --binding DB --update-config --use-remote=false

Lesen Sie den erstellten Namen und die ID aus und prüfen Sie anschließend die gespeicherte Bindung:

cat wrangler.jsonc

Der Eintrag DB muss die Datenbank dieses Durchlaufs bezeichnen. Eine Bindung ist eine konfigurierte Verbindung zwischen dem Code und einer Ressource. Ihre UUID identifiziert die Cloud-Datenbank, während --local eine separate SQLite-Datenbank auf dieser VM verwendet. Geben Sie bei SQL-Befehlen immer entweder --local oder --remote an.

cat schema.sql
npx wrangler d1 execute DB --local --file schema.sql
npx wrangler d1 execute DB --remote --file schema.sql

Ticket 1 ist offen und besitzt keine Lösung. Ticket 2 ist geschlossen und besitzt das Lösungsereignis 1. Diese bereits verwendete Ereignis-ID erzeugt einen kontrollierten Fehler: Das Einfügen eines weiteren Ereignisses mit der ID 1 muss den Primärschlüssel verletzen.

Schreibvorgänge atomar und Lesevorgänge sequenziell halten

In diesem Schritt lösen Sie zwei voneinander getrennte Konsistenzprobleme. Atomarität bedeutet, dass entweder beide zusammengehörigen Schreibvorgänge erfolgreich sind oder keiner von beiden. D1 batch() führt vorbereitete Anweisungen als Transaktion aus: Ein Fehler setzt den gesamten Batch zurück. Zwei separat mit await erwartete Schreibvorgänge bieten diese Garantie nicht.

Eine Sitzung verfolgt den Datenbankzustand, den eine Folge von Abfragen beobachtet hat. Der bereitgestellte Router ruft env.DB.withSession(...) auf und beginnt mit first-primary, wenn der Client kein Lesezeichen besitzt. Er sendet getBookmark() im Header x-d1-bookmark zurück. Eine spätere Anfrage kann dieses Lesezeichen mitsenden, um ab mindestens diesem Datenbankzustand fortzufahren. Das ist sequenzielle Konsistenz, keine Alles-oder-nichts-Transaktion über mehrere HTTP-Anfragen hinweg.

Implementieren Sie beide Funktionen mit der vom Router übergebenen Sitzung:

cat > src/store.js <<'JS'
export async function closeTicket(session, id, eventId, note) {
  await session.batch([
    session.prepare("UPDATE tickets SET status = 'closed' WHERE id = ?").bind(id),
    session.prepare('INSERT INTO resolutions(event_id, ticket_id, note) VALUES (?, ?, ?)').bind(eventId, id, note)
  ]);
}
export async function readTicket(session, id) {
  const ticket = await session.prepare('SELECT id, subject, status FROM tickets WHERE id = ?').bind(id).first();
  if (!ticket) return null;
  const { results } = await session.prepare('SELECT event_id, note FROM resolutions WHERE ticket_id = ? ORDER BY event_id').bind(id).all();
  return { ...ticket, resolutions: results };
}
JS

Lesen Sie src/index.js, um withSession, den eingehenden Lesezeichen-Header und das zurückgegebene Lesezeichen zu finden. Alle Datenbankoperationen der Anfrage verwenden diese Sitzung. Ein Lesezeichen ist eine undurchsichtige Position. Geben Sie es unverändert zurück, anstatt es zu analysieren oder selbst zu erzeugen.

cat src/index.js
npx wrangler dev --ip 0.0.0.0 > dev.log 2>&1 &
cat dev.log

Warten Sie auf die Meldung, dass der lokale Dienst lauscht. Die lokale Simulation kann den Rollback eines Batches testen, demonstriert aber weder die tatsächliche Remote-Replikation noch ein Cloud-Lesezeichen.

Rollback vor einem erfolgreichen Abschluss beobachten

In diesem Schritt übermitteln Sie absichtlich die bereits verwendete Ereignis-ID. Die erste Anweisung des Batches versucht, Ticket 1 zu schließen, aber die zweite Anweisung schlägt fehl. Lesen Sie nach dem Fehler das Ergebnis:

curl -i http://localhost:8787/tickets/1/close -H 'Content-Type: application/json' -d '{"event_id":1,"note":"Must roll back"}'
curl -i http://localhost:8787/tickets/1

Erwartet wird zunächst 409 event_conflict. Danach muss Ticket 1 weiterhin open sein und ein leeres Array resolutions besitzen. Der Statuscode 409 allein reicht nicht aus: Die anschließende Abfrage zeigt, dass keine teilweise ausgeführte Änderung erhalten geblieben ist.

Verwenden Sie nun die noch nicht verwendete Ereignis-ID 2:

curl -i http://localhost:8787/tickets/1/close -H 'Content-Type: application/json' -d '{"event_id":2,"note":"Access restored"}'
curl -i http://localhost:8787/tickets/1

Erwartet wird HTTP 200. Ticket 1 muss closed sein und das Lösungsereignis 2 mit der Notiz Access restored enthalten. Beide Datensätze stimmen nun überein. Setzen Sie keine lokalen Daten zurück und ändern Sie die Remote-Datenbank nicht, um eine Replikationsverzögerung zu erzeugen.

Eine Remote-Sitzung mit ihrem Lesezeichen fortsetzen

In diesem Schritt führen Sie denselben Batch gegen D1 aus und übertragen ein echtes Lesezeichen zwischen den Anfragen. Die Remote-Testdaten befinden sich weiterhin im Ausgangszustand.

npx wrangler deploy

Kopieren Sie die tatsächliche Deployment-URL. Wiederholen Sie zuerst den fehlgeschlagenen Batch und bestätigen Sie den Rollback:

URL='YOUR_DEPLOYED_HTTPS_URL'
curl -i "$URL/tickets/1/close" -H 'Content-Type: application/json' -d '{"event_id":1,"note":"Must roll back"}'
curl -i "$URL/tickets/1"

Erwartet wird 409 und anschließend ein offenes Ticket ohne Lösungen. Falls das Deployment noch verteilt wird, wiederholen Sie die Abfrage bis zu einer Minute lang. Verwechseln Sie eine Plattform-Fehlerseite nicht mit dem JSON-Vertrag der Anwendung.

Führen Sie den erfolgreichen Abschluss aus:

curl -i "$URL/tickets/1/close" -H 'Content-Type: application/json' -d '{"event_id":2,"note":"Access restored"}'

Erwartet werden das geschlossene Ticket und seine Notiz. Kopieren Sie den nicht leeren Header x-d1-bookmark aus der Antwort ohne zusätzliche Leerzeichen in die folgende Variable:

BOOKMARK='YOUR_RESPONSE_BOOKMARK'
curl -i "$URL/tickets/1" -H "x-d1-bookmark: $BOOKMARK"

Die Folgeabfrage muss das geschlossene Ticket und das Lösungsereignis 2 sehen. Ein Lesezeichen begrenzt, wie alt ein Lesevorgang sein darf; es ist kein Authentifizierungstoken. Dieser Ablauf funktioniert, ohne einen veralteten Lesevorgang zu benötigen oder die Lesereplikation zu aktivieren. Sie überprüfen den Sitzungsvertrag und behaupten nicht, dass ein Replikationskonflikt aufgetreten ist.

Öffnen Sie im Dashboard genau den bereitgestellten Worker und bestätigen Sie, dass seine DB-Bindung auf die Datenbank dieses Durchlaufs zeigt. Schließen Sie die funktionale Überprüfung vor der Bereinigung ab.

Worker-Bindung an D1

Dieses Beispiel zeigt die Bindung DB des Workers an seine D1-Datenbank. Das generierte Ressourcenpräfix kennzeichnet diesen Beispieldurchlauf; deine Namen werden abweichen. Der Screenshot bestätigt nur die Bindung. Die obigen HTTP-Prüfungen belegen das atomare Zurückrollen, die erfolgreiche Aktualisierung und das Fortsetzen mit dem Lesezeichen.

Temporäre Ressourcen löschen

In diesem Schritt entfernen Sie nur die Ressourcen dieses Labs, solange die VM noch autorisiert ist. Schließen Sie zuerst alle funktionalen Prüfungen ab. Behalten Sie die Konfiguration, bis die Löschung überprüft wurde.

npx wrangler delete

Bestätigen Sie, dass nur der Worker-Name aus der Konfiguration dieses Durchlaufs gelöscht wird.

npx wrangler d1 delete DB

Prüfen Sie die Eingabeaufforderung und bestätigen Sie, dass nur die Datenbank dieses Durchlaufs betroffen ist. Listen Sie anschließend die Datenbanken auf:

npx wrangler d1 list --json

Der aufgezeichnete Datenbankname und die UUID müssen in einer erfolgreichen Antwort fehlen. Andere Ressourcen dürfen weiterhin vorhanden sein. Ein Authentifizierungs- oder Netzwerkfehler ist nicht eindeutig: Stellen Sie den Zugriff wieder her und wiederholen Sie die Abfrage, bevor Sie fortfahren. Führen Sie die Überprüfung dieses Schritts durch, solange Sie noch angemeldet sind.

Beenden Sie auch den lokalen Entwicklungsprozess. Listen Sie die Jobs auf und beenden Sie nur den von Ihnen gestarteten wrangler dev-Job. Ersetzen Sie %1, falls dessen Jobnummer abweicht:

jobs
kill %1

Die Autorisierung dieser VM beenden

In diesem Schritt beenden Sie die Autorisierung erst, nachdem die unabhängige Prüfung der Löschung erfolgreich war. logout entfernt die auf dieser VM gespeicherte Wrangler-Autorisierung. Das bloße Schließen einer VM führt nicht zur Bereinigung der Cloud-Ressourcen.

npx wrangler logout
npx wrangler whoami --json

Erwartet wird loggedIn: false. Diese nicht authentifizierte Abfrage kann mit einem Fehlercode beendet werden. Das ist nur dann erwartungsgemäß, wenn die strukturierte Antwort ausdrücklich angibt, dass Sie abgemeldet sind. Schließen Sie die Überprüfung ab und beenden Sie anschließend die Laborumgebung.

Zusammenfassung

Sie haben geübt, zusammengehörige Ticket-Aktualisierungen konsistent zu halten. Sie haben überprüfbare Datenbankergebnisse kontrolliert, das ausgewählte Konto und den lokalen Zustand ausdrücklich berücksichtigt und die temporären Ressourcen vor der Abmeldung entfernt.