From 10eefc48c7ac4f1fa0de3406b4df68098f646285 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 17 Apr 2026 21:54:34 +0200 Subject: [PATCH] test(db): verify V42 partial unique index for QUEUED training runs per person Co-Authored-By: Claude Sonnet 4.6 --- .../repository/MigrationIntegrationTest.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/backend/src/test/java/org/raddatz/familienarchiv/repository/MigrationIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/repository/MigrationIntegrationTest.java index 78ff9861..da1ab7f4 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/repository/MigrationIntegrationTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/repository/MigrationIntegrationTest.java @@ -217,8 +217,71 @@ class MigrationIntegrationTest { assertThat(stored).isEqualTo("sage"); } + // ─── V42: idx_training_runs_queued_per_person partial unique index ──────── + + @Test + @Transactional(propagation = Propagation.NOT_SUPPORTED) + void v42_partialUniqueIndex_preventsTwoQueuedRunsForSamePerson() { + UUID personId = createPerson("V42Test", "SamePerson"); + jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'QUEUED', 10, 2, 'sender_x', ?) + """, personId); + + assertThatThrownBy(() -> + jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'QUEUED', 5, 1, 'sender_x', ?) + """, personId) + ).isInstanceOf(DataIntegrityViolationException.class); + + jdbc.update("DELETE FROM ocr_training_runs WHERE person_id = ?", personId); + jdbc.update("DELETE FROM persons WHERE id = ?", personId); + } + + @Test + void v42_partialUniqueIndex_allowsQueuedRunsForDifferentPersons() { + UUID person1 = createPerson("V42Test", "PersonA"); + UUID person2 = createPerson("V42Test", "PersonB"); + + int rows1 = jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'QUEUED', 10, 2, 'sender_a', ?) + """, person1); + int rows2 = jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'QUEUED', 5, 1, 'sender_b', ?) + """, person2); + + assertThat(rows1).isEqualTo(1); + assertThat(rows2).isEqualTo(1); + } + + @Test + void v42_partialUniqueIndex_allowsMultipleDoneRunsForSamePerson() { + UUID personId = createPerson("V42Test", "DonePerson"); + + int rows1 = jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'DONE', 10, 2, 'sender_x', ?) + """, personId); + int rows2 = jdbc.update(""" + INSERT INTO ocr_training_runs (id, status, block_count, document_count, model_name, person_id) + VALUES (gen_random_uuid(), 'DONE', 15, 3, 'sender_x', ?) + """, personId); + + assertThat(rows1).isEqualTo(1); + assertThat(rows2).isEqualTo(1); + } + // ─── helpers ───────────────────────────────────────────────────────────── + private UUID createPerson(String firstName, String lastName) { + UUID id = UUID.randomUUID(); + jdbc.update("INSERT INTO persons (id, first_name, last_name) VALUES (?, ?, ?)", id, firstName, lastName); + return id; + } + private UUID createTag(String name) { UUID id = UUID.randomUUID(); jdbc.update("INSERT INTO tag (id, name) VALUES (?, ?)", id, name);