Skip to content

Rehearses the parallel-column exit - #124

Merged
johnnyt merged 1 commit into
mainfrom
ece-6ler-parallel-exit-rehearsal
Sep 30, 2026
Merged

johnnyt merged 1 commit into
mainfrom
ece-6ler-parallel-exit-rehearsal

Conversation

@johnnyt

@johnnyt johnnyt commented Sep 30, 2026

Copy link
Copy Markdown
Member

Rehearses the migrate-from-cloak guide's parallel-column exit end to end, and adds steps 0 and 1 to the in-place walk.

What changes

  • test/encryptor/ecto/runbook_parallel_walk_test.exs (new): one describe block per "Parallel step" 0 to 8 of the guide, against the runbook's integrations table and its three <field>_encrypted pairs, each test asserting what that section says the host sees:
    • step 0: the parallel plan's census reads the new column and shows no legacy row before the pass; the guide's old-column query is byte-equal to the in-place plan's format census and shows the legacy format alone;
    • step 1: an unprovisioned workspace fails at its own row on every column with {:raised, Encryptor.Ecto.EncryptError}, and the same dry run is clean once it is provisioned;
    • step 2: every new column is NULL, and the step 3 schema reads such a row;
    • step 3: the dual write on insert and on update, and a write past the changeset leaving a stale pair that neither the pass nor verification sees;
    • step 4: the mix encryptor.ecto.migrate --mode dry-run output, whole, with nothing written; the release task's shape, both vaults started inside Ecto.Migrator.with_repo/2;
    • step 5: the --mode write output, whole, old columns byte for byte, the plan's integrity query before and after; a halted pass and its resume;
    • step 6: mix encryptor.ecto.verify --sample all exits 1 before the pass and prints the whole green block after it, with no legacy_load event;
    • step 7: the cut-over read equals the old column, the kept dual write keeps the old column current, and a declaration whose "column" is not the one the pass wrote under raises DecryptError on a verified row;
    • step 8: after the old columns are dropped, the old field names read every row through source: plus column:, and without column: the read is refused.
  • test/encryptor/ecto/runbook_test.exs: new "step 0" and "step 1" describe blocks (the pre-pass format census; the unprovisioned workspace's failure at its own row, then clean once provisioned). Additions only: no existing test is removed or reworded.
  • docs/guides/migrate-from-cloak.md, "Parallel step 3": the Expected and If-it-differs lines corrected (see Provenance).

The walk reuses the fixtures the parallel plan test added (ParallelIntegration, CutOverIntegration, ParallelMigration and the fixture migration with the _encrypted columns); the one test-local schema is the step 8 trap, a field renamed back onto the new column without column:. It is a sibling file rather than an extension of runbook_parallel_test.exs because that file is organised by plan-level property and this one by runbook step, as ruled by the operator, 2026-09-29.

Provenance

  • The walk found the guide's step 3 inexact, and the guide is what changed. It said "new and updated rows carry both columns" and called a new column still NULL after an update an uncovered write path; an update writes the pair of each field it changes only, so a field it leaves alone keeps a NULL pair until step 5. It also said an uncovered write path "keeps producing rows step 6 reports"; a stale pair left by a write past the changeset is already in the target state to both the pass and verify/2, so step 6 never reports it. The guide now says both, and the second step 3 test asserts both.
  • No lib/ change, no record, no changelog fragment (test harness and documentation are excluded by changelog.d/README.md).

Review

Own review against the bead: every describe maps to one "Parallel step" heading, 0 to 8; each quoted output the tests assert (the dry-run, write and verify blocks) is the task's full output compared with ==; the step 0 query is compared to Encryptor.Ecto.Migrator.Census.queries/2's rendered format query; the step 8 pinned field matches the guide's source:/column: line. Each new test carries a sabotage note naming a mutation that was applied and turned that test red on an assertion, and the source was restored byte-equal after each.

Gate

Full mix quality green on this tree, database arm included (ECTO_REQUIRE_DATABASE=1):

✓ Format: No changes needed
✓ Compile: dev + test compiled (warnings as errors)
○ Doctor: skipped (:doctor not installed)
○ Gettext: skipped (:gettext not installed)
○ Sobelow: skipped (:sobelow not installed)
✓ Doc links: 12 links checked
✓ Dependencies: No unused dependencies
✓ Credo: No issues
✓ Docs: No warnings
✓ Dialyzer: No warnings
✓ Tests: 891 of 891 passed, 95.3% coverage

✓ All quality checks passed!

Refs: ece-6ler

A new test file walks the migrate-from-cloak guide's parallel-column
exit on the runbook's integrations table, one describe block per
"Parallel step" 0 to 8, each asserting what that section says the
host sees: the census and the old-column format query, the vault
error at an unprovisioned workspace's own row, the dual write, the
dry run, write and verify output through the mix tasks, the cut-over
read and the pinned column after the drop. It reuses the fixtures the
parallel plan test added; nothing is duplicated.

The in-place walk gains step 0 and step 1 blocks and loses nothing.

Walking step 3 found the guide inexact: an update writes the pair of
the field it changes, not both columns of the row, and a stale pair
is invisible to the pass and to verification. The guide's Expected
and If-it-differs lines now say so, and the walk asserts both.

Test and guide only; no library change and no fragment.

Refs: ece-6ler
@johnnyt
johnnyt merged commit 81fcfaf into main Sep 30, 2026
1 check passed
@johnnyt
johnnyt deleted the ece-6ler-parallel-exit-rehearsal branch September 30, 2026 06:30
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