fix(protokoll): IDs ohne Zweierschritte vergeben (#032)
Spalten-Default (BIGSERIAL) und Trigger protokoll_verketten zogen je eine Nummer aus der Sequenz, jede Zeile verbrauchte zwei IDs. Die Nummer aus dem Default darf der Trigger aber nicht einfach uebernehmen, denn sie wird vor der Advisory-Sperre gezogen: Eine parallele Transaktion mit groesserer ID koennte zuerst verketten, und die Kette liesse sich in ID-Reihenfolge nicht mehr pruefen. Deshalb zieht nur noch der Trigger unter der Sperre; der Default ist ein Platzhalter 0 (Prisma: @default(0)), damit create ohne ID funktioniert. Die Sequenz bleibt der Spalte zugeordnet. Bestehende Zeilen werden nicht umnummeriert, weil die ID in die Hash-Eingabe eingeht. Tests: drei Eintraege nacheinander ergeben n, n+1, n+2; eine mitgegebene ID wird ueberschrieben; 20 parallele Eintraege belegen genau 20 aufeinanderfolgende IDs bei intakter Kette. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -236,8 +236,30 @@ describe("Protokoll", () => {
|
||||
expect(pruefung?.ergebnis).toBe(zweiter.id);
|
||||
});
|
||||
|
||||
it("vergibt IDs ohne Zweierschritte (#032)", async () => {
|
||||
// Frueher zogen Spalten-Default und Trigger je eine Nummer aus der Sequenz.
|
||||
const [a, b, c] = [await eintragen("eins"), await eintragen("zwei"), await eintragen("drei")];
|
||||
expect(b.id).toBe(a.id + 1n);
|
||||
expect(c.id).toBe(a.id + 2n);
|
||||
const [pruefung] = await prisma.$queryRaw<
|
||||
{ ergebnis: bigint | null }[]
|
||||
>`SELECT protokoll_kette_pruefen() AS ergebnis`;
|
||||
expect(pruefung?.ergebnis).toBeNull();
|
||||
});
|
||||
|
||||
it("ueberschreibt eine mitgegebene ID unter der Sperre (#032)", async () => {
|
||||
const erster = await eintragen("eins");
|
||||
const zweiter = await prisma.protokoll.create({
|
||||
data: { id: 999n, akteurName: "Test", aktion: "zwei", ergebnis: "ERFOLG" },
|
||||
});
|
||||
expect(zweiter.id).toBe(erster.id + 1n);
|
||||
expect(zweiter.vorgaengerHash).toBe(erster.hash);
|
||||
});
|
||||
|
||||
it("bleibt bei gleichzeitigem Schreiben eine lueckenlose Kette", async () => {
|
||||
await Promise.all(Array.from({ length: 20 }, (_, i) => eintragen(`parallel-${i}`)));
|
||||
const zeilen = await Promise.all(Array.from({ length: 20 }, (_, i) => eintragen(`parallel-${i}`)));
|
||||
const ids = zeilen.map((z) => z.id).sort((x, y) => (x < y ? -1 : 1));
|
||||
expect(ids.at(-1)! - ids[0]!).toBe(19n);
|
||||
const [pruefung] = await prisma.$queryRaw<
|
||||
{ ergebnis: bigint | null }[]
|
||||
>`SELECT protokoll_kette_pruefen() AS ergebnis`;
|
||||
|
||||
Reference in New Issue
Block a user