Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.4] - 2026-06-13

### Fixed

- `changelog_changeset` now declares `unique_constraint(:id, name: "<table>_pkey")` so `Ecto.ConstraintError` on `audit_logs_pkey` (or custom table pkey) during `log_changes/5` (called from `*_and_log` inside transactions) is turned into a changeset error instead of crashing the caller. The log failure path already swallows errors and returns `{:ok, reason}`. Closes OPS-4624.

## [1.0.3] - 2026-05-28

### Fixed
Expand Down
6 changes: 5 additions & 1 deletion lib/ecto_trail/ecto_trail.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ defmodule EctoTrail do

# Cache frequently accessed config to avoid repeated lookups
@redacted_fields_config Application.compile_env(:ecto_trail, :redacted_fields, nil)
@audit_log_table_name Application.compile_env(:ecto_trail, :table_name, "audit_log")
@audit_log_pkey_name "#{@audit_log_table_name}_pkey"
@default_max_params 65_000
@changelog_fields [:actor_id, :resource, :resource_id, :changeset, :change_type]
@not_loaded_pattern "Ecto.Association.NotLoaded"
Expand Down Expand Up @@ -572,6 +574,8 @@ defmodule EctoTrail do
defp map_custom_ecto_type(value), do: value

defp changelog_changeset(attrs) do
Changeset.cast(%Changelog{}, attrs, @changelog_fields)
%Changelog{}
|> Changeset.cast(attrs, @changelog_fields)
|> Changeset.unique_constraint(:id, name: @audit_log_pkey_name)
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule EctoTrail.Mixfile do
use Mix.Project

@version "1.0.3"
@version "1.0.4"

def project do
[
Expand Down
19 changes: 19 additions & 0 deletions test/unit/ecto_trail_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,23 @@ defmodule EctoTrailTest do
)
end
end

describe "audit log primary key constraint handling" do
test "does not raise Ecto.ConstraintError when audit log pkey is violated; main operation succeeds and log failure is swallowed" do
{:ok, _} = TestRepo.insert_and_log(%Resource{name: "seed"}, "actor-seed")

%Postgrex.Result{rows: [[max_id]]} = TestRepo.query!("SELECT max(id) FROM audit_log")
next_id = max_id + 1

TestRepo.query!(
"INSERT INTO audit_log (id, actor_id, resource, resource_id, changeset, change_type, inserted_at) VALUES ($1, 'conflict', 'resources', '999', $2, 'insert', now())",
[next_id, %{}]
)

TestRepo.query!("SELECT setval('audit_log_id_seq', $1, false)", [max_id])

assert {:ok, %Resource{name: "after"}} =
TestRepo.insert_and_log(%Resource{name: "after"}, "actor-after")
end
end
end