Skip to content

Commit cc51df5

Browse files
committed
Revert "Also remove Pg/SQL exception handling to avoid savepoints"
This reverts commit bd8c976. Translation of exception messages depends on the aggregate id and type to be known when an aggregate unique key is violated.
1 parent 311b88d commit cc51df5

File tree

6 files changed

+38
-81
lines changed

6 files changed

+38
-81
lines changed

db/migrate/20260220122600_sequent_avoid_exception_handling_in_update_unique_keys.rb

Lines changed: 0 additions & 29 deletions
This file was deleted.

db/migrate/sequent/update_unique_keys_v04.sql

Lines changed: 0 additions & 46 deletions
This file was deleted.

db/structure.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,10 @@ BEGIN
734734
SET key = EXCLUDED.key
735735
WHERE target.key <> EXCLUDED.key;
736736
END LOOP;
737+
EXCEPTION
738+
WHEN unique_violation THEN
739+
RAISE unique_violation
740+
USING MESSAGE = 'duplicate unique key value for aggregate ' || (_aggregate->>'aggregate_type') || ' ' || _aggregate_id || ' (' || SQLERRM || ')';
737741
END;
738742
$$;
739743

@@ -1584,7 +1588,6 @@ ALTER TABLE ONLY sequent_schema.snapshot_records
15841588
SET search_path TO public,view_schema,sequent_schema;
15851589

15861590
INSERT INTO "schema_migrations" (version) VALUES
1587-
('20260220122600'),
15881591
('20260129130000'),
15891592
('20250815103000'),
15901593
('20250630113000'),

lib/sequent/core/event_store.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,24 @@
1010
module Sequent
1111
module Core
1212
class AggregateKeyNotUniqueError < RuntimeError
13+
attr_reader :aggregate_type, :aggregate_id
14+
1315
def self.unique_key_error_message?(message)
14-
message =~ /duplicate key value violates unique constraint \"aggregate_unique_keys_scope_key_key\"/
16+
message =~ /duplicate unique key value for aggregate/
17+
end
18+
19+
def initialize(message)
20+
super
21+
22+
match = message.match(
23+
# rubocop:disable Layout/LineLength
24+
/aggregate (\p{Upper}\p{Alnum}*(?:::\p{Upper}\p{Alnum}*)*) (\p{XDigit}{8}-\p{XDigit}{4}-\p{XDigit}{4}-\p{XDigit}{4}-\p{XDigit}{12})/,
25+
# rubocop:enable Layout/LineLength
26+
)
27+
if match
28+
@aggregate_type = match[1]
29+
@aggregate_id = match[2]
30+
end
1531
end
1632
end
1733

spec/lib/sequent/core/aggregate_repository_spec.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,11 @@ def change_ssn(ssn)
545545

546546
Sequent.aggregate_repository.add_aggregate(user_2)
547547

548-
expect { Sequent.aggregate_repository.commit(DummyCommand.new) }
549-
.to raise_error(Sequent::Core::AggregateKeyNotUniqueError)
548+
expect { Sequent.aggregate_repository.commit(DummyCommand.new) }.to raise_error(
549+
an_instance_of(Sequent::Core::AggregateKeyNotUniqueError)
550+
.and(having_attributes(message: /#{user_id_2}/))
551+
.and(having_attributes(message: /DummyAggregateWithoutEmail/)),
552+
)
550553
end
551554

552555
it 'enforces key uniqueness with the same key scope across different aggregate types' do
@@ -568,7 +571,13 @@ def change_ssn(ssn)
568571

569572
expect do
570573
Sequent.configuration.event_store.update_unique_keys([user_b.event_stream])
571-
end.to raise_error(Sequent::Core::AggregateKeyNotUniqueError)
574+
end.to raise_error(
575+
an_instance_of(Sequent::Core::AggregateKeyNotUniqueError)
576+
.and(having_attributes(message: /#{user_id_2}/))
577+
.and(having_attributes(message: /DummyAggregateWithoutEmail/))
578+
.and(having_attributes(aggregate_type: 'DummyAggregateWithoutEmail'))
579+
.and(having_attributes(aggregate_id: user_id_2)),
580+
)
572581
end
573582
end
574583
end

spec/lib/sequent/core/aggregate_unique_keys_spec.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ class UniqueKeysCommandHandler < Sequent::Core::BaseCommandHandler
122122
when_command UniqueKeysCommand.new(aggregate_id: aggregate_id_1, keys: %w[a])
123123
expect do
124124
when_command UniqueKeysCommand.new(aggregate_id: aggregate_id_2, keys: %w[a])
125-
end.to raise_error(Sequent::Core::AggregateKeyNotUniqueError)
125+
end.to raise_error(
126+
an_instance_of(Sequent::Core::AggregateKeyNotUniqueError)
127+
.and(having_attributes(aggregate_type: 'Sequent::Core::UniqueKeysAggregate'))
128+
.and(having_attributes(aggregate_id: aggregate_id_2)),
129+
)
126130
end
127131

128132
context 'find by unique key' do

0 commit comments

Comments
 (0)