Skip to content

Reset PK sequences after mounting cached fixtures (#51)#58

Merged
ngan merged 1 commit into
mainfrom
np-pg-sequence-fix
May 6, 2026
Merged

Reset PK sequences after mounting cached fixtures (#51)#58
ngan merged 1 commit into
mainfrom
np-pg-sequence-fix

Conversation

@ngan
Copy link
Copy Markdown
Collaborator

@ngan ngan commented May 6, 2026

Closes #51

Summary

ActiveRecordCoder#mount replays INSERTs that include explicit primary key values. Postgres sequences don't observe these inserts, so a later Model.create calls nextval and collides with an id we just inserted. Intermittent PG::UniqueViolation in test runs that mount the cache onto a database whose sequence is at its initial value (e.g. parallel test workers with their own DB copies).

Fix

Reset the sequence per connection after the batch executes:

  • Prefer connection.reset_column_sequences! (Rails main / 8.2+) — batches the reset in one round-trip per connection
  • Fall back to per-table connection.reset_pk_sequence! (Rails 8.0/8.1)
  • Skip silently on adapters that expose neither (MySQL, SQLite — their PK generators advance from explicit-id INSERTs and don't have this bug)

Repro spec

spec/integration/pk_sequence_repro_spec.rb simulates the parallel-worker scenario by wiping the table and resetting the PK generator after the auto-mount, then re-mounting and asserting that a fresh Model.create succeeds.

Without the fix this fails on Postgres with PG::UniqueViolation: duplicate key value violates unique constraint "users_pkey", Key (id)=(1) already exists. Passes naturally on MySQL and SQLite.

Why batched + fallback

The batched method (rails/rails#55928) was added to address per-table sequence reset being slow on large schemas. Using it when available means fixture_kit users on Rails 8.2+ get the perf win automatically. The per-table fallback covers our currently-supported 8.0 and 8.1.

Stack

Last in the stack — sits on #57 (which adds the PG matrix that exercises this fix in CI).

Test plan

  • All three adapters green locally (166/0)
  • CI: PG matrix entry should be the test that goes from red (without this fix) to green (with it)

🤖 Generated with Claude Code

@ngan ngan changed the base branch from np-pg-mysql-ci-matrix to main May 6, 2026 20:11
ActiveRecordCoder#mount replays INSERTs that include explicit primary
key values. Postgres sequences don't observe these inserts, so a later
Model.create can call nextval and collide with an id we just inserted —
intermittent PG::UniqueViolation in test runs that mount the cache onto
a database whose sequence is at its initial value (e.g. parallel test
workers with their own DB copies).

Reset the sequence per connection after the batch executes:

- Prefer connection.reset_column_sequences! when available (Rails main
  / 8.2+) — batches the reset in one round-trip per connection
- Fall back to per-table connection.reset_pk_sequence! (Rails 8.0/8.1)
- Skip silently on adapters that expose neither (MySQL, SQLite)

Adds spec/integration/pk_sequence_repro_spec.rb that simulates the
parallel-worker scenario by wiping the table and resetting the PK
generator after the auto-mount, then re-mounting and asserting that a
fresh Model.create succeeds. Without the fix this fails on Postgres
with PG::UniqueViolation; passes naturally on MySQL/SQLite.

Closes #51

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ngan ngan marked this pull request as ready for review May 6, 2026 20:18
@ngan ngan force-pushed the np-pg-sequence-fix branch from 7a5adac to fb02b5b Compare May 6, 2026 20:18
@ngan ngan merged commit 5ae5557 into main May 6, 2026
10 checks passed
@ngan ngan deleted the np-pg-sequence-fix branch May 6, 2026 20:20
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.

Intermittent PG::UniqueViolation in tests when FixtureKit cache uses explicit PKs (PostgreSQL sequences not advanced)

1 participant