Skip to content

Ship transaction-free bundles by default - #4

Merged
lemuelroberto merged 4 commits into
emfga:mainfrom
lemuelroberto:feat/no-transaction-bundles
Sep 30, 2026
Merged

lemuelroberto merged 4 commits into
emfga:mainfrom
lemuelroberto:feat/no-transaction-bundles

Conversation

@lemuelroberto

Copy link
Copy Markdown
Member

Why

The all-in bundle carried one BEGIN;/COMMIT; pair per script — 40
including the vendored cel4postgres. Embedded in a migration tool
(Kysely, Flyway, Liquibase…), which runs each migration inside its own
transaction, the first COMMIT; ended that transaction and the rest
ran in autocommit: a failure halfway left half an engine installed.
pgtle-wrap.sh already grepped the lines out for CREATE EXTENSION.

What changes

  • Vendors cel4postgres 0.0.2 (Ship transaction-free bundles by default cel4postgres#6), whose plain
    bundle has no transaction control. The file is the published release
    asset; sha256 b6de8556… matches its SHA256SUMS.
  • sql/ carries no transaction control. Plain artifacts run inside the
    caller's transaction; each gets a -tx twin with exactly one
    BEGIN; and one COMMIT; around the whole file.
  • build-release.sh refuses a BEGIN;/COMMIT; line in sql/ or the
    vendored bundle.
  • New scripts/smoke-artifacts.sh, run by CI and the release: each
    plain artifact installs between BEGIN and ROLLBACK and must leave
    no fga/cel schema (a stray COMMIT; fails it), then with
    --single-transaction; each -tx artifact installs with a bare
    psql -f; engine-only files over the vendored cel. Replaces
    release-engine-initdb.sh.
  • Per-file install loops (docker/000_install.sh, CI reinstall) use
    --single-transaction, so each file stays atomic — it matters on the
    bench's persistent volume. bench/loader.go already gets that from
    the simple protocol's implicit transaction (comment updated).
  • pgtle-wrap.sh wraps plain files unchanged and refuses -tx input.
  • docs/INSTALL.md / README: both shapes, psql -1, and an "Inside a
    migration tool" section. CLAUDE.md's sql/ contract updated in its
    own commit. Version 0.0.2.

Verified locally

  • docker compose up -d --wait installs through the new initdb loop.
  • go vet ./..., go build ./..., TestLoadAndCheck (bench loader),
    TestEngineVersion + TestCheckCorpus (149 subtests pass; skips are
    the named skip list). Full suite left to CI per CLAUDE.md.
  • smoke-artifacts.sh: all four artifacts ok. With a top-level
    COMMIT; injected into the plain bundle it fails with "committed on
    its own"; a BEGIN; added to sql/ makes build-release.sh refuse.
  • shellcheck scripts/*.sh docker/*.sh: clean.

cel4postgres 0.0.2 ships its plain bundle without transaction control,
so the vendored file can sit inside a transaction the caller owns --
the property fga4postgres's own bundles are about to need. The file
is the published release asset, byte for byte: its sha256 matches the
release's SHA256SUMS.
Every sql/ script opened and committed its own transaction, so the
all-in bundle carried one BEGIN;/COMMIT; pair per script -- forty
with the vendored cel4postgres. Embedding it in a migration tool,
which runs each migration inside a transaction it owns, therefore
failed in the worst way: the first COMMIT; ended the migration's
transaction and the rest ran in autocommit, so a failure halfway left
half an engine behind. pg_tle had the same problem, which is why
pgtle-wrap.sh grepped those lines out.

The sources now carry no transaction control and the plain artifacts
are what the sources say. The caller picks the boundary: psql -1, a
migration's transaction, or CREATE EXTENSION. Each artifact gets a -tx
twin with exactly one BEGIN; and one COMMIT; around the whole file,
for a bare psql -f that should still be all or nothing.

The per-file install loops (initdb, the bench's persistent volume, the
CI reinstall) now pass --single-transaction so each file stays atomic
as before, and the bench loader already gets that from the simple
protocol's implicit transaction. build-release.sh refuses a BEGIN; or
COMMIT; line in sql/ or the vendored bundle. scripts/smoke-artifacts.sh,
run by CI and by the release, installs each plain artifact between
BEGIN and ROLLBACK and asserts nothing survives, which a stray COMMIT;
would break; it replaces release-engine-initdb.sh.
The artifact set changed shape: plain files lost their transaction
control and -tx twins were added. A consumer pinning 0.0.1 must not
receive files that behave differently under the same name.
The sql/ naming section justified plain concatenation by every script
opening its own BEGIN;/COMMIT;. That is no longer true, and a
contributor following it would reintroduce exactly the lines that stop
a bundle being embedded in a caller's transaction. State the new
contract and what enforces it, and point the by-hand install and the
vendoring decision at cel4postgres 0.0.2.
@lemuelroberto
lemuelroberto merged commit 9b0f746 into emfga:main Sep 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant