From 86f9929cd2af511fc5f48adf990935d394a9be8c Mon Sep 17 00:00:00 2001 From: James Maes Date: Thu, 15 Oct 2026 07:56:47 -0500 Subject: [PATCH] fix(ddl): no comment line may start with -- changeset Liquibase formatted SQL parses any line beginning with '-- changeset' as a directive, so the worm-audit:13 comment broke the changelog. Reword it and guard the rendered DDL in CanonicalAndCryptoTest. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + docs/ddl/worm-audit-postgres.sql | 4 ++-- .../com/kingsrook/qbits/wormaudit/ddl/postgres/worm-audit.sql | 4 ++-- .../com/kingsrook/qbits/wormaudit/CanonicalAndCryptoTest.java | 3 +++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc83bd..dcf0f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes are documented here, following [Keep a Changelog](https://ke ### Fixed +- `worm-audit:13` had a comment line starting with `-- changeset`, which Liquibase formatted-SQL parsing rejects as a malformed directive. The comment is reworded, and `CanonicalAndCryptoTest` now requires every `-- changeset` line to be a real directive. - Chain writer database load. Each 30-second tick re-read the whole late-detail lookback (24 h of `audit_detail`) and probed the GIN array index once per detail (18.4 s and 1.78M buffer hits per tick on a 120k-detail production database), and re-scanned every settled audit header for the unchained anti-join. Coverage now lives in `worm_audit_chain_detail` (`worm-audit:13`): one insert-only row per covered detail, written by the chain trigger in the same statement as its link and backfilled from the existing chain, so the late-detail check is a primary-key probe. Each tick also reads only ids above per-JVM sweep floors (rows settled since the last complete sweep); after a restart and once an hour a tick sweeps everything, as before. Link hash inputs, `detail_ids`, the verifier and exports are unchanged. - The chain trigger's overlap check (`EXISTS ... && ...`) ran as a cached generic plan that sequentially scanned all of `worm_audit_chain` for every inserted link (55k sequential scans, 1.2B tuples read in production, about 80 ms per link and growing). The trigger now inserts the coverage rows and lets their primary key reject a detail covered twice. - Verification counts detail coverage by aggregating the chain's own detail lists once instead of one index probe per detail, and breaks when the coverage table disagrees with the chain. diff --git a/docs/ddl/worm-audit-postgres.sql b/docs/ddl/worm-audit-postgres.sql index 58881fa..97c0ad6 100644 --- a/docs/ddl/worm-audit-postgres.sql +++ b/docs/ddl/worm-audit-postgres.sql @@ -469,8 +469,8 @@ BEGIN END; $fn$; --- The array index worm_audit_chain_detail_coverage is no longer used by this release. It stays until a later --- changeset drops it, so a previous-release writer still running during a rolling deploy keeps its indexed probe. +-- The array index worm_audit_chain_detail_coverage is no longer used by this release. It stays until +-- a later migration drops it, so a previous-release writer still running during a rolling deploy keeps its indexed probe. DROP TRIGGER IF EXISTS worm_audit_row_guard ON public.worm_audit_chain_detail; CREATE TRIGGER worm_audit_row_guard BEFORE UPDATE OR DELETE ON public.worm_audit_chain_detail diff --git a/src/main/resources/com/kingsrook/qbits/wormaudit/ddl/postgres/worm-audit.sql b/src/main/resources/com/kingsrook/qbits/wormaudit/ddl/postgres/worm-audit.sql index a1b887c..8bd3596 100644 --- a/src/main/resources/com/kingsrook/qbits/wormaudit/ddl/postgres/worm-audit.sql +++ b/src/main/resources/com/kingsrook/qbits/wormaudit/ddl/postgres/worm-audit.sql @@ -469,8 +469,8 @@ BEGIN END; $fn$; --- The array index worm_audit_chain_detail_coverage is no longer used by this release. It stays until a later --- changeset drops it, so a previous-release writer still running during a rolling deploy keeps its indexed probe. +-- The array index worm_audit_chain_detail_coverage is no longer used by this release. It stays until +-- a later migration drops it, so a previous-release writer still running during a rolling deploy keeps its indexed probe. DROP TRIGGER IF EXISTS worm_audit_row_guard ON public.worm_audit_chain_detail; CREATE TRIGGER worm_audit_row_guard BEFORE UPDATE OR DELETE ON public.worm_audit_chain_detail diff --git a/src/test/java/com/kingsrook/qbits/wormaudit/CanonicalAndCryptoTest.java b/src/test/java/com/kingsrook/qbits/wormaudit/CanonicalAndCryptoTest.java index 27f9553..4c18eac 100644 --- a/src/test/java/com/kingsrook/qbits/wormaudit/CanonicalAndCryptoTest.java +++ b/src/test/java/com/kingsrook/qbits/wormaudit/CanonicalAndCryptoTest.java @@ -167,6 +167,9 @@ class CanonicalAndCryptoTest java.nio.file.Files.readString( java.nio.file.Path.of("docs/ddl/worm-audit-postgres.sql"))); assertThat(sql).doesNotContain("${"); + // Liquibase parses every line starting with "-- changeset" as a directive, comments included. + assertThat(sql.lines().filter(line -> line.startsWith("-- changeset"))) + .allMatch(line -> line.matches("-- changeset worm-audit:[0-9]+( splitStatements:false)?")); assertThat(sql).contains("GET DIAGNOSTICS stack = PG_CONTEXT", "function worm_audit_purge(timestamp with time zone)", "SET timezone = 'UTC'"); // The documented migration contract deliberately uses physical snake_case columns. assertThat(sql).contains("OLD.audit_id", "OLD.timestamp", "NEW.name", "GRANT UPDATE (label, create_date, modify_date)"); -- 2.54.0