CodamAIDocs
Themafertig

Ein Request, eine Transaktion

Alles in einem Request gelingt oder nichts. Hier steht, wann committet und wann zurückgerollt wird, und dass es zwischen zwei Requests keine Klammer gibt.

Ausprägungen
Erfolg → Commit vor der AntwortFehler irgendwo → RollbackKonflikt beim Commit → 409zwei Requests → zwei TransaktionenHooks in der Transaktion, Seiteneffekte nicht

Worum es geht

Eine Transaktion ist eine Klammer um Änderungen in der Datenbank: Entweder werden alle Änderungen darin dauerhaft, oder keine. Das Dauerhaft-Machen heißt Commit, das Verwerfen heißt Rollback.

In CDMS ist diese Klammer genau eine Anfrage. Alles, was eine Anfrage schreibt, gehört zusammen: das Objekt selbst, alle verschachtelten Kinder, alle mitgelöschten Objekte und alles, was Hooks über CDMS schreiben.

Der Zeitstrahl einer Anfrage

sequenceDiagram
    participant C as Client
    participant D as CDMS
    participant H as Hook
    participant DB as Datenbank
    C->>D: PUT /company/update/c4…
    D->>DB: erste Datenbankaktion öffnet die Transaktion
    D->>H: Before-Hooks
    D->>DB: ändern, Kinder schreiben
    D->>H: After-Hooks
    D->>DB: flush: SQL wird ausgeführt, noch nicht festgeschrieben
    D->>DB: zurücklesen für die Antwort
    D->>DB: COMMIT
    D-->>C: 200 mit dem Objekt

Zwei Zeitpunkte muss man auseinanderhalten:

  • flush: CDMS schickt die gesammelten SQL-Befehle an die Datenbank. Die Datenbank prüft dabei ihre Regeln, zum Beispiel eindeutige Werte. Andere Anfragen sehen die Änderung noch nicht.
  • Commit: Die Datenbank macht die Änderung dauerhaft und für alle sichtbar. Das passiert direkt, bevor CDMS die Antwort schreibt.

Kommt beim Client eine Erfolgsantwort an, ist die Änderung also schon gespeichert. Eine Anfrage direkt danach sieht sie.

Erfolg, Fehler, Konflikt

Wie eine Anfrage endet

Wann: Alle Schritte gelingen.

  1. 1
    CDMS
    verarbeitet die Anfrage: prüfen, schreiben, Hooks, zurücklesen
  2. 2
    CDMS→Database
    Commit, unmittelbar bevor der Antwortkörper geschrieben wird
  3. 3
    CDMS→Client
    2xx

Ergebnis: Die Änderung ist dauerhaft.

Wann: Irgendein Schritt scheitert: Rolle fehlt, Validierung, Hook, Datenbankregel.

  1. 1
    CDMS
    ein Schritt wirft einen Fehler
  2. 2
    CDMS→Database
    markiert die ganze Anfrage als gescheitert und rollt alle offenen Transaktionen zurück
  3. 3
    CDMS→Client
    Fehlerantwort, z. B. 400, 403, 404, 422

Ergebnis: Nichts von dieser Anfrage ist gespeichert, auch nicht die Teile, die vor dem Fehler schon geschrieben waren.

Wann: Alle Schritte gelingen, aber eine andere Anfrage hat dasselbe Datei-Modell gleichzeitig geändert. Nur Datei-Modelle erkennen gleichzeitige Änderungen.

  1. 1
    CDMS→Database
    Commit scheitert an der gleichzeitigen Änderung
  2. 2
    CDMS→Client
    409, die Anfrage wird zurückgerollt

Ergebnis: Weil der Commit vor der Antwort liegt, erfährt der Client davon. Siehe Gleichzeitige Änderungen.

Entscheidungstabelle

Was von einer Anfrage übrig bleibt
Alle Schritte erfolgreich?Commit erfolgreich?Ergebnis
jaja2xx, alles gespeichert
janein409 bei gleichzeitiger Änderung eines Datei-Modells, sonst ein Serverfehler; nichts gespeichert
nein–Fehlerantwort; nichts gespeichert

Zwei Fälle haben eigene Seiten:

Was alles in der Klammer liegt

Wasin derselben Transaktion?
das Objekt der Anfrageja
verschachtelt angelegte, geänderte oder gelöschte Kinderja
abgekoppelte Objekte (Verweis geleert)ja
Schreibzugriffe eines Hooks über CDMS auf Modelle derselben Ebeneja
das Zurücklesen für die Antwortja, im Modus STRICT
Dateiinhalte im Dateispeichernein, aber sie werden erst nach dem Commit wirksam und bei einem Fehler verworfen
E-Mails, HTTP-Aufrufe, Nachrichten, die ein Hook verschicktnein

Zwei Anfragen, zwei Transaktionen

  1. 1
    Client→CDMS
    POST /customer/create → 200, der Kunde ist gespeichert
  2. 2
    Client→CDMS
    POST /order/create mit dem neuen Kunden → 422
  3. 3
    CDMS
    rollt nur die zweite Anfrage zurück
    Ergebnis: Der Kunde bleibt, obwohl sein Auftrag fehlt.

Eine Klammer über mehrere Anfragen gibt es nicht. Wenn zwei Objekte nur gemeinsam entstehen dürfen, schreibe sie in einer Anfrage, verschachtelt über die Beziehung. Siehe Die vier Fälle beim verschachtelten Schreiben.

Fallen

Wie es weitergeht

Quellen im Code und in der Wissensdatenbank
  • commons-persistence – DatabaseRequestContext (getEntityManager, markRollbackOnly, commitThreadTransactions, closeEntityManager)
  • CDMS/cdms-rest-api – RequestTransactionCommitter (beforeBodyWrite, postHandle, settle), RequestCommitConfig (extendHandlerExceptionResolvers), RequestFailureMarker (resolveException), CdmsExceptionMapper (markRollbackOnly)
  • CDMS/cdms-system-layer – AbstractSystemLayer (createObject, updateObject, patchObject, deleteObject: flush, rollback)
  • CDMS/cdms-persistence-database – docs/adr/ADR-009-request-scoped-transaction-bracket.md
  • documentation/30-daten-und-persistenz/02-transaktionen.md
Suchen