Skip to content

fix: declare unique_constraint for audit pkey in *_and_log / log_changes (OPS-4567)#28

Closed
palantir-valiot[bot] wants to merge 1 commit into
mainfrom
palantir/OPS-4567-missing-unique-constraint
Closed

fix: declare unique_constraint for audit pkey in *_and_log / log_changes (OPS-4567)#28
palantir-valiot[bot] wants to merge 1 commit into
mainfrom
palantir/OPS-4567-missing-unique-constraint

Conversation

@palantir-valiot

Copy link
Copy Markdown

Summary

Root cause: upsert_and_log (and the other *_and_log / log_changes paths) call repo.insert(%Changelog{...}) without declaring unique_constraint/3 for the audit table's pkey. When the sequence for audit_log/audit_logs is rewound or a concurrent upsert produces an id collision, Postgres raises on the unique pkey and Ecto surfaces it as Ecto.ConstraintError (see audit_logs_pkey in the stack). The existing error-handling in log_changes already swallows {:error, reason} returns (logs and returns {:ok, reason}), so turning the violation into a changeset error makes the main mutation succeed instead of blowing up the request.

Fix: changelog_changeset/1 now attaches unique_constraint(:id, name: ...) for the common pkey names customers actually use (audit_log_pkey, audit_logs_pkey, ${table}_pkey). Also upgraded benchee/credo within ranges (deps freshness per workflow).

Files changed:

  • lib/ecto_trail/ecto_trail.ex — add @default_audit_table, changelog_changeset now builds candidates from Application.get_env(:ecto_trail, :table_name, ...) and calls add_unique_constraints_for_pkey/2.
  • test/unit/ecto_trail_test.exs — added "constraint error handling for audit_log pkey (OPS-4567)" integration test exercising upsert_and_log under forced pkey collision (sequence rewind).
  • test/unit/ecto_trail_constraint_unit_test.exs — new pure (no-DB) unit test asserting the constraint declarations are present on the internal builder.
  • mix.exs — 1.0.4.
  • CHANGELOG.md — concise entry + deps freshness note.
  • mix.lock — benchee 1.5.1, credo 1.7.19 (and transitive).

Why

Linear: OPS-4567 — "jobs-lamosa-gto-prod: Root cause is missing unique_constraint handling". Triage: NOTIFY+FIX, severity high, category code_bug, first-party package. Matches the exact stack in the issue (ecto_trail 1.0.3 lib/ecto_trail/ecto_trail.ex:435: EctoTrail.log_changes/5repo.insert inside upsert_and_log).

Test plan

  • mix format --check-formatted (clean).
  • mix compile (clean; only pre-existing redundant-clause warning on an unrelated helper).
  • Pure unit constraint regression test passes (standalone ExUnit run that loads only the compiled beams, no Postgres):
    • test/unit/ecto_trail_constraint_unit_test.exs asserts audit_log_pkey and audit_logs_pkey appear in the changeset constraints.
  • Added TDD-style integration test under describe "constraint error handling for audit_log pkey (OPS-4567)":
    • Seeds a colliding row + rewinds the sequence, then calls upsert_and_log; asserts the mutation succeeds ({:ok, Resource}) instead of raising Ecto.ConstraintError.
  • mix test executed (DB-dependent tests cannot connect in this pod; the test helper's Ecto.Migrator.run fails with connection refused as expected; the deterministic checks above cover the change).
  • Upgraded benchee/credo within ranges (mix hex.outdatedmix deps.update); lockfile updated.
  • Version bump + CHANGELOG entry added before the PR.
  • Self-review: git diff inspected; no debug prints, no empty diff, no scope creep; branch name follows the NON-NEGOTIABLE palantir/OPS-4567-... convention.

Closes OPS-4567

…ges (OPS-4567)

- changelog_changeset now adds unique_constraint/3 for common pkey names
  (audit_log_pkey, audit_logs_pkey, _pkey) so Ecto turns
  ConstraintError into a changeset error that the existing log-and-swallow
  path already handles.
- Added TDD test (constraint collision under upsert_and_log) and pure
  unit test (no DB) asserting the declarations are present.
- Bumped version to 1.0.4; added CHANGELOG entry; upgraded benchee/credo
  within ranges for deps freshness.
- mix format clean.

Closes OPS-4567
@linear-code

linear-code Bot commented Jun 13, 2026

Copy link
Copy Markdown

OPS-4567

@acrogenesis

Copy link
Copy Markdown
Member

Closing as a duplicate of #24 — all of these PRs fix the same bug: Ecto.ConstraintError on audit_logs_pkey in EctoTrail.log_changes/5. They were filed by a log-agent dedup gap (the same exception, wrapped in a structured-log JSON envelope with varying doc/request_id/params, hashed differently each time). That gap is now fixed in palantir (commit 38438d6) so this won't recur. Consolidating on #24.

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