fix: declare unique_constraint on audit log pkey to avoid Ecto.ConstraintError#65
Conversation
…aintError changelog_changeset now calls unique_constraint(:id, name: "<table>_pkey") so duplicate pkey inserts (e.g. concurrent/retried tx, sequence rewind in tests) become changeset errors instead of raising Ecto.ConstraintError. The *_and_log / log_* paths already swallow audit log failures (log and continue); the primary DB operation succeeds. TDD: added repro test that forces pkey collision via setval on the sequence and asserts the main update succeeds without propagating ConstraintError. Bumped to 1.0.4 (bugfix) and updated CHANGELOG. Closes OPS-4603
There was a problem hiding this comment.
Overall Assessment
The PR adds Changeset.unique_constraint(:id, name: "#{@table_name}_pkey") to changelog_changeset/1, converting a pkey unique violation on the audit_log insert into a changeset error that the existing log_changes* paths already swallow. The implementation is sound; the surrounding error-handling already turns {:error, _} from audit-log inserts into logged {:ok, reason} results and lets the outer transaction succeed. No blocking bugs found.
Findings
No actionable findings.
Notes
- The test at
test/unit/ecto_trail_test.exs:202-226follows the samefrom(...)pattern used elsewhere in the file (lines 267, 292, etc.), which impliesEcto.Queryis brought in viaEctoTrail.DataCase; the compile-clean claim is consistent with that. - The
@table_namemodule attribute is computed viaApplication.compile_env/3at compile time, matching the style of@redacted_fields_configalready present at line 54. - The PR only touches the minimal surface (
changelog_changeset+ TDD test + version bump); no other call sites ofchangelog_changesetneeded adjustment.
|
Thanks for the review. Confirmed:
The Re-affirming the PR for merge when protection allows. |
Description
changelog_changeset/1(used by all*_and_log/*andlog*paths) now callsChangeset.unique_constraint(:id, name: "<table>_pkey")(default tableaudit_log).This prevents
Ecto.ConstraintErroronaudit_logs_pkey(or the configured table's pkey) when the audit-log insert inside the transaction would violate the unique constraint (concurrent/retried transactions, sequence rewinds, etc.). The surrounding code already swallows audit-log write failures (logs and returns{:ok, reason}or continues with the primary operation result), so the caller's main DB mutation succeeds.Files changed:
lib/ecto_trail/ecto_trail.ex(the constraint declaration +@table_namemodule attr to compute the constraint name dynamically)test/unit/ecto_trail_test.exs(TDD repro test underupdate_and_log/3that forces a pkey collision viasetvalon the sequence and asserts the primary update succeeds)mix.exs(1.0.3 → 1.0.4)CHANGELOG.md(entry for 1.0.4)Fixes OPS-4603 (and matches the observed stack in the Linear issue).
Type of change
How Has This Been Tested?
Ecto.ConstraintErrordescribed in the issue.mix format(clean)mix compile(clean; validates the change)mix testrequires a running Postgres (not available in this agent pod; CI will exercise the new test + all existing tests against a real DB with the sandbox).git diff; only the minimal targeted change + version/changelog + the TDD test.log_changes,log_changes_alone, etc.) already turn{:error, _}from the insert into a logged{:ok, reason}and let the outer transaction succeed with the primary result.Test Configuration:
audit_logtable with serial PK).Checklist:
mix format)