ruby_event_store-rom 1.3.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/ruby_event_store/rom/changesets/create_events.rb +10 -18
  4. data/lib/ruby_event_store/rom/changesets/create_stream_entries.rb +3 -12
  5. data/lib/ruby_event_store/rom/changesets/update_events.rb +33 -19
  6. data/lib/ruby_event_store/rom/event_repository.rb +65 -61
  7. data/lib/ruby_event_store/rom/index_violation_detector.rb +25 -0
  8. data/lib/ruby_event_store/rom/mappers/event_to_serialized_record.rb +10 -6
  9. data/lib/ruby_event_store/rom/mappers/stream_entry_to_serialized_record.rb +11 -6
  10. data/lib/ruby_event_store/rom/rake_task.rb +5 -0
  11. data/lib/ruby_event_store/rom/relations/events.rb +78 -0
  12. data/lib/ruby_event_store/rom/relations/stream_entries.rb +83 -0
  13. data/lib/ruby_event_store/rom/repositories/events.rb +55 -30
  14. data/lib/ruby_event_store/rom/repositories/stream_entries.rb +15 -16
  15. data/lib/ruby_event_store/rom/tasks/migration_tasks.rake +36 -0
  16. data/lib/ruby_event_store/rom/types.rb +16 -14
  17. data/lib/ruby_event_store/rom/unit_of_work.rb +28 -13
  18. data/lib/ruby_event_store/rom/version.rb +1 -1
  19. data/lib/ruby_event_store/rom.rb +28 -103
  20. data/lib/ruby_event_store-rom.rb +1 -1
  21. metadata +31 -49
  22. data/.rubocop.yml +0 -1
  23. data/.rubocop_todo.yml +0 -84
  24. data/CHANGELOG.md +0 -9
  25. data/Gemfile +0 -12
  26. data/Makefile +0 -57
  27. data/Rakefile +0 -20
  28. data/db/migrate/20180327044629_create_ruby_event_store_tables.rb +0 -54
  29. data/db/migrate/20181026152045_index_by_event_type.rb +0 -9
  30. data/lib/ruby_event_store/rom/adapters/memory/changesets/create_events.rb +0 -19
  31. data/lib/ruby_event_store/rom/adapters/memory/changesets/create_stream_entries.rb +0 -19
  32. data/lib/ruby_event_store/rom/adapters/memory/changesets/update_events.rb +0 -18
  33. data/lib/ruby_event_store/rom/adapters/memory/relations/events.rb +0 -56
  34. data/lib/ruby_event_store/rom/adapters/memory/relations/stream_entries.rb +0 -114
  35. data/lib/ruby_event_store/rom/adapters/memory/unit_of_work.rb +0 -36
  36. data/lib/ruby_event_store/rom/adapters/sql/changesets/create_events.rb +0 -15
  37. data/lib/ruby_event_store/rom/adapters/sql/changesets/update_events.rb +0 -41
  38. data/lib/ruby_event_store/rom/adapters/sql/index_violation_detector.rb +0 -31
  39. data/lib/ruby_event_store/rom/adapters/sql/rake_task.rb +0 -5
  40. data/lib/ruby_event_store/rom/adapters/sql/relations/events.rb +0 -27
  41. data/lib/ruby_event_store/rom/adapters/sql/relations/stream_entries.rb +0 -72
  42. data/lib/ruby_event_store/rom/adapters/sql/tasks/migration_tasks.rake +0 -36
  43. data/lib/ruby_event_store/rom/memory.rb +0 -82
  44. data/lib/ruby_event_store/rom/sql.rb +0 -169
  45. data/lib/ruby_event_store/rom/tuple_uniqueness_error.rb +0 -21
  46. data/lib/ruby_event_store/spec/rom/event_repository_lint.rb +0 -176
  47. data/lib/ruby_event_store/spec/rom/relations/events_lint.rb +0 -75
  48. data/lib/ruby_event_store/spec/rom/relations/stream_entries_lint.rb +0 -198
  49. data/lib/ruby_event_store/spec/rom/spec_helper_lint.rb +0 -15
  50. data/lib/ruby_event_store/spec/rom/unit_of_work_lint.rb +0 -37
  51. data/ruby_event_store-rom.gemspec +0 -37
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- module ROM
5
- module SQL
6
- module Relations
7
- class StreamEntries < ::ROM::Relation[:sql]
8
- schema(:event_store_events_in_streams, as: :stream_entries, infer: true) do
9
- attribute :created_at, RubyEventStore::ROM::Types::DateTime
10
-
11
- associations do
12
- belongs_to :events, as: :event, foreign_key: :event_id
13
- end
14
- end
15
-
16
- alias take limit
17
-
18
- SERIALIZED_GLOBAL_STREAM_NAME = 'all'.freeze
19
-
20
- def create_changeset(tuples)
21
- changeset(ROM::Changesets::CreateStreamEntries, tuples)
22
- end
23
-
24
- def by_stream(stream)
25
- where(stream: normalize_stream_name(stream))
26
- end
27
-
28
- def by_event_id(event_id)
29
- where(event_id: event_id)
30
- end
31
-
32
- def by_event_type(types)
33
- join(:events).where(event_type: types)
34
- end
35
-
36
- def by_stream_and_event_id(stream, event_id)
37
- where(stream: normalize_stream_name(stream), event_id: event_id).one!
38
- end
39
-
40
- def max_position(stream)
41
- by_stream(stream).select(:position).order(Sequel.desc(:position)).first
42
- end
43
-
44
- DIRECTION_MAP = {
45
- forward: %i[asc > <],
46
- backward: %i[desc < >]
47
- }.freeze
48
-
49
- def ordered(direction, stream, offset_entry_id = nil, stop_entry_id = nil)
50
- order, operator_offset, operator_stop = DIRECTION_MAP[direction]
51
-
52
- raise ArgumentError, 'Direction must be :forward or :backward' if order.nil?
53
-
54
- order_columns = %i[position id]
55
- order_columns.delete(:position) if stream.global?
56
-
57
- query = by_stream(stream)
58
- query = query.where { id.public_send(operator_offset, offset_entry_id) } if offset_entry_id
59
- query = query.where { id.public_send(operator_stop, stop_entry_id) } if stop_entry_id
60
- query.order { |r| order_columns.map { |c| r[:stream_entries][c].public_send(order) } }
61
- end
62
-
63
- private
64
-
65
- def normalize_stream_name(stream)
66
- stream.global? ? SERIALIZED_GLOBAL_STREAM_NAME : stream.name
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby_event_store/rom/sql'
4
-
5
- MIGRATIONS_PATH = 'db/migrate'.freeze
6
-
7
- desc 'Setup ROM EventRespository environment'
8
- task 'db:setup' do
9
- Dir.chdir(Dir.pwd)
10
- ROM::SQL::RakeSupport.env = ::RubyEventStore::ROM.configure(:sql).rom_container
11
- end
12
-
13
- desc 'Copy RubyEventStore SQL migrations to db/migrate'
14
- task 'db:migrations:copy' => 'db:setup' do
15
- # Optional data type for `data` and `metadata`
16
- data_type = ENV['DATA_TYPE']
17
-
18
- Dir[File.join(File.dirname(__FILE__), '../../../../../../', MIGRATIONS_PATH, '/*.rb')].each do |input|
19
- contents = File.read(input)
20
- name = File.basename(input, '.*').sub(/\d+_/, '')
21
-
22
- re_data_type = /(ENV.+?DATA_TYPE.+?\|\|=\s*)['"](jsonb?|text)['"]/
23
-
24
- if data_type && contents =~ re_data_type
25
- # Search/replace this string: ENV['DATA_TYPE'] ||= 'text'
26
- contents = contents.sub(re_data_type, format('\1"%<data_type>s"', data_type: data_type))
27
- name += "_with_#{data_type}"
28
- end
29
-
30
- output = ROM::SQL::RakeSupport.create_migration(name, path: File.join(Dir.pwd, MIGRATIONS_PATH))
31
-
32
- File.write output, contents
33
-
34
- puts "<= migration file created #{output}"
35
- end
36
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby_event_store/rom'
4
- require 'rom/memory'
5
- require_relative 'adapters/memory/unit_of_work'
6
- require_relative 'adapters/memory/relations/events'
7
- require_relative 'adapters/memory/relations/stream_entries'
8
- require_relative 'adapters/memory/changesets/create_events'
9
- require_relative 'adapters/memory/changesets/update_events'
10
- require_relative 'adapters/memory/changesets/create_stream_entries'
11
-
12
- module RubyEventStore
13
- module ROM
14
- module Memory
15
- class << self
16
- def fetch_next_id
17
- @last_id ||= 0
18
- @mutex ||= Mutex.new
19
- @mutex.synchronize { @last_id += 1 }
20
- end
21
-
22
- def setup(config)
23
- config.register_relation Relations::Events
24
- config.register_relation Relations::StreamEntries
25
- end
26
-
27
- def configure(env)
28
- env.register_unit_of_work_options(class: UnitOfWork)
29
-
30
- env.register_error_handler :unique_violation, lambda { |ex|
31
- case ex
32
- when TupleUniquenessError
33
- raise EventDuplicatedInStream if ex.message =~ /event_id/
34
-
35
- raise WrongExpectedEventVersion
36
- end
37
- }
38
- end
39
- end
40
-
41
- class SpecHelper
42
- attr_reader :env
43
- attr_reader :connection_pool_size, :close_pool_connection
44
-
45
- def initialize
46
- @connection_pool_size = 5
47
- @env = ROM.setup(:memory)
48
- end
49
-
50
- def run_lifecycle
51
- yield
52
- ensure
53
- drop_gateway_schema
54
- end
55
-
56
- def gateway
57
- env.rom_container.gateways.fetch(:default)
58
- end
59
-
60
- def drop_gateway_schema
61
- gateway.connection.data.values.each { |v| v.data.clear }
62
- end
63
-
64
- def close_gateway_connection
65
- gateway.disconnect
66
- end
67
-
68
- def gateway_type?(name)
69
- name == :memory
70
- end
71
-
72
- def has_connection_pooling?
73
- true
74
- end
75
-
76
- def supports_upsert?
77
- true
78
- end
79
- end
80
- end
81
- end
82
- end
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby_event_store/rom'
4
- require 'rom/sql'
5
- require_relative 'adapters/sql/index_violation_detector'
6
- require_relative 'adapters/sql/relations/events'
7
- require_relative 'adapters/sql/relations/stream_entries'
8
- require_relative 'adapters/sql/changesets/create_events'
9
- require_relative 'adapters/sql/changesets/update_events'
10
-
11
- module RubyEventStore
12
- module ROM
13
- module SQL
14
- class << self
15
- def setup(config)
16
- config.register_relation Relations::Events
17
- config.register_relation Relations::StreamEntries
18
- end
19
-
20
- def configure(env)
21
- # See: https://github.com/jeremyevans/sequel/blob/master/doc/transactions.rdoc
22
- env.register_unit_of_work_options(
23
- savepoint: true,
24
- # Committing changesets concurrently causes MySQL deadlocks
25
- # which are not caught and retried by Sequel's built-in
26
- # :retry_on option. This appears to be a result of how ROM
27
- # handles exceptions which don't bubble up so that Sequel
28
- # can retry transactions with the :retry_on option when there's
29
- # a deadlock.
30
- #
31
- # This is exacerbated by the fact that changesets insert multiple
32
- # tuples with individual INSERT statements because ROM specifies
33
- # to Sequel to return a list of primary keys created. The likelihood
34
- # of a deadlock is reduced with batched INSERT statements.
35
- #
36
- # For this reason we need to manually insert changeset records to avoid
37
- # MySQL deadlocks or to allow Sequel to retry transactions
38
- # when the :retry_on option is specified.
39
- retry_on: Sequel::SerializationFailure,
40
- before_retry: lambda { |_num, ex|
41
- env.logger.warn("RETRY TRANSACTION [#{self.class.name} => #{ex.class.name}] #{ex.message}")
42
- }
43
- )
44
-
45
- env.register_error_handler :unique_violation, lambda { |ex|
46
- case ex
47
- when ::ROM::SQL::UniqueConstraintError, Sequel::UniqueConstraintViolation
48
- raise EventDuplicatedInStream if IndexViolationDetector.new.detect(ex.message)
49
-
50
- raise WrongExpectedEventVersion
51
- end
52
- }
53
-
54
- env.register_error_handler :not_found, lambda { |ex, event_id|
55
- case ex
56
- when ::ROM::TupleCountMismatchError
57
- raise EventNotFound, event_id
58
- when Sequel::DatabaseError
59
- raise ex unless ex.message =~ /PG::InvalidTextRepresentation.*uuid/
60
-
61
- raise EventNotFound, event_id
62
- end
63
- }
64
- end
65
-
66
- def supports_upsert?(db)
67
- supports_on_duplicate_key_update?(db) ||
68
- supports_insert_conflict_update?(db)
69
- end
70
-
71
- def supports_on_duplicate_key_update?(db)
72
- db.adapter_scheme =~ /mysql/
73
- end
74
-
75
- def supports_insert_conflict_update?(db)
76
- case db.adapter_scheme
77
- when :postgres
78
- true
79
- when :sqlite
80
- # Sqlite 3.24.0+ supports PostgreSQL upsert syntax
81
- db.sqlite_version >= 32_400
82
- else
83
- false
84
- end
85
- end
86
- end
87
-
88
- class SpecHelper
89
- attr_reader :env
90
-
91
- def initialize(database_uri = ENV['DATABASE_URL'])
92
- config = ::ROM::Configuration.new(
93
- :sql,
94
- database_uri,
95
- max_connections: database_uri =~ /sqlite/ ? 1 : 5,
96
- preconnect: :concurrently
97
- # sql_mode: %w[NO_AUTO_VALUE_ON_ZERO STRICT_ALL_TABLES]
98
- )
99
- # $stdout.sync = true
100
- # config.default.use_logger Logger.new(STDOUT)
101
- # config.default.connection.pool.send(:preconnect, true)
102
- config.default.run_migrations
103
-
104
- @env = ROM.setup(config)
105
- end
106
-
107
- def run_lifecycle
108
- establish_gateway_connection
109
- load_gateway_schema
110
-
111
- yield
112
- ensure
113
- drop_gateway_schema
114
- close_gateway_connection
115
- end
116
-
117
- def gateway
118
- env.rom_container.gateways.fetch(:default)
119
- end
120
-
121
- def gateway_type?(name)
122
- gateway.connection.database_type.eql?(name)
123
- end
124
-
125
- def has_connection_pooling?
126
- !gateway_type?(:sqlite)
127
- end
128
-
129
- def connection_pool_size
130
- gateway.connection.pool.size
131
- end
132
-
133
- def close_pool_connection
134
- gateway.connection.pool.disconnect
135
- end
136
-
137
- def supports_upsert?
138
- SQL.supports_upsert?(gateway.connection)
139
- end
140
-
141
- protected
142
-
143
- def establish_gateway_connection
144
- # Manually preconnect because disconnecting and reconnecting
145
- # seems to lose the "preconnect concurrently" setting
146
- gateway.connection.pool.send(:preconnect, true)
147
- end
148
-
149
- def load_gateway_schema
150
- gateway.run_migrations
151
- end
152
-
153
- def drop_gateway_schema
154
- gateway.connection.drop_table?('event_store_events')
155
- gateway.connection.drop_table?('event_store_events_in_streams')
156
- gateway.connection.drop_table?('schema_migrations')
157
- end
158
-
159
- # See: https://github.com/rom-rb/rom-sql/blob/master/spec/shared/database_setup.rb
160
- def close_gateway_connection
161
- gateway.connection.disconnect
162
- # Prevent the auto-reconnect when the test completed
163
- # This will save from hardly reproducible connection run outs
164
- gateway.connection.pool.available_connections.freeze
165
- end
166
- end
167
- end
168
- end
169
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- module ROM
5
- class TupleUniquenessError < StandardError
6
- class << self
7
- def for_event_id(event_id)
8
- new "Uniquness violated for event_id (#{event_id.inspect})"
9
- end
10
-
11
- def for_stream_and_event_id(stream_name, event_id)
12
- new "Uniquness violated for stream (#{stream_name.inspect}) and event_id (#{event_id.inspect})"
13
- end
14
-
15
- def for_stream_and_position(stream_name, position)
16
- new "Uniquness violated for stream (#{stream_name.inspect}) and position (#{position.inspect})"
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,176 +0,0 @@
1
- require 'ruby_event_store/rom/event_repository'
2
- require 'ruby_event_store/spec/event_repository_lint'
3
-
4
- module RubyEventStore::ROM
5
- RSpec.shared_examples :rom_event_repository do |repository_class|
6
- subject(:repository) { repository_class.new(rom: env) }
7
-
8
- let(:env) { rom_helper.env }
9
- let(:rom_container) { env.rom_container }
10
- let(:rom_db) { rom_container.gateways[:default] }
11
-
12
- around(:each) do |example|
13
- rom_helper.run_lifecycle { example.run }
14
- end
15
-
16
- let(:test_race_conditions_auto) { rom_helper.has_connection_pooling? }
17
- let(:test_race_conditions_any) { rom_helper.has_connection_pooling? }
18
- let(:test_binary) { false }
19
- let(:test_change) { rom_helper.supports_upsert? }
20
-
21
- let(:default_stream) { RubyEventStore::Stream.new('stream') }
22
- let(:global_stream) { RubyEventStore::Stream.new('all') }
23
- let(:mapper) { RubyEventStore::Mappers::NullMapper.new }
24
-
25
- let(:reader) { RubyEventStore::SpecificationReader.new(repository, mapper) }
26
- let(:specification) { RubyEventStore::Specification.new(reader) }
27
-
28
- require 'ruby_event_store/rom/sql'
29
- it_behaves_like :event_repository, repository_class, [ROM::SQL::Error]
30
-
31
- specify '#initialize requires ROM::Env' do
32
- expect { repository_class.new(rom: nil) }.to raise_error do |err|
33
- expect(err).to be_a(ArgumentError)
34
- expect(err.message).to eq('Must specify rom')
35
- end
36
- end
37
-
38
- specify '#initialize uses ROM.env by default' do
39
- expect { repository_class.new }.to raise_error(ArgumentError)
40
- RubyEventStore::ROM.env = env
41
- expect { repository_class.new }.not_to raise_error
42
- RubyEventStore::ROM.env = nil
43
- end
44
-
45
- specify '#has_event? to raise exception for bad ID' do
46
- expect(repository.has_event?('0')).to eq(false)
47
- end
48
-
49
- specify 'all considered internal detail' do
50
- repository.append_to_stream(
51
- [RubyEventStore::SRecord.new],
52
- RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
53
- RubyEventStore::ExpectedVersion.any
54
- )
55
-
56
- expect { repository.read(specification.stream('all').result) }.to raise_error(RubyEventStore::ReservedInternalName)
57
- expect { repository.read(specification.stream('all').backward.result) }.to raise_error(RubyEventStore::ReservedInternalName)
58
- expect { repository.read(specification.stream('all').limit(5).result) }.to raise_error(RubyEventStore::ReservedInternalName)
59
- expect { repository.read(specification.stream('all').limit(5).backward.result) }.to raise_error(RubyEventStore::ReservedInternalName)
60
-
61
- expect { repository.count(specification.stream('all').result) }.to raise_error(RubyEventStore::ReservedInternalName)
62
- end
63
-
64
- specify 'explicit sorting by position rather than accidental' do
65
- events = [
66
- RubyEventStore::SRecord.new(event_id: u1 = SecureRandom.uuid),
67
- RubyEventStore::SRecord.new(event_id: u2 = SecureRandom.uuid),
68
- RubyEventStore::SRecord.new(event_id: u3 = SecureRandom.uuid)
69
- ]
70
-
71
- repo = Repositories::Events.new(rom_container)
72
- repo.create_changeset(events).commit
73
-
74
- expect(repo.events.to_a.size).to eq(3)
75
-
76
- repo.stream_entries.changeset(Changesets::CreateStreamEntries, [
77
- { stream: default_stream.name, event_id: events[1].event_id, position: 1 },
78
- { stream: default_stream.name, event_id: events[0].event_id, position: 0 },
79
- { stream: default_stream.name, event_id: events[2].event_id, position: 2 }
80
- ]).commit
81
-
82
- expect(repo.stream_entries.to_a.size).to eq(3)
83
-
84
- # ActiveRecord::Schema.define do
85
- # self.verbose = false
86
- # remove_index :event_store_events_in_streams, [:stream, :position]
87
- # end
88
-
89
- expect(repository.read(specification.stream('stream').limit(3).result).map(&:event_id)).to eq([u1, u2, u3])
90
- expect(repository.read(specification.stream('stream').result).map(&:event_id)).to eq([u1, u2, u3])
91
-
92
- expect(repository.read(specification.stream('stream').backward.limit(3).result).map(&:event_id)).to eq([u3, u2, u1])
93
- expect(repository.read(specification.stream('stream').backward.result).map(&:event_id)).to eq([u3, u2, u1])
94
- end
95
-
96
- specify 'explicit sorting by id rather than accidental for all events' do
97
- events = [
98
- RubyEventStore::SRecord.new(event_id: u1 = SecureRandom.uuid),
99
- RubyEventStore::SRecord.new(event_id: u2 = SecureRandom.uuid),
100
- RubyEventStore::SRecord.new(event_id: u3 = SecureRandom.uuid)
101
- ]
102
-
103
- repo = Repositories::Events.new(rom_container)
104
- repo.create_changeset(events).commit
105
-
106
- expect(repo.events.to_a.size).to eq(3)
107
-
108
- repo.stream_entries.changeset(Changesets::CreateStreamEntries, [
109
- { stream: global_stream.name, event_id: events[0].event_id, position: 1 },
110
- { stream: global_stream.name, event_id: events[1].event_id, position: 0 },
111
- { stream: global_stream.name, event_id: events[2].event_id, position: 2 }
112
- ]).commit
113
-
114
- expect(repo.stream_entries.to_a.size).to eq(3)
115
-
116
- expect(repository.read(specification.limit(3).result).map(&:event_id)).to eq([u1, u2, u3])
117
- expect(repository.read(specification.limit(3).backward.result).map(&:event_id)).to eq([u3, u2, u1])
118
- end
119
-
120
- specify 'nested transaction - events still not persisted if append failed' do
121
- repository.append_to_stream([
122
- event = RubyEventStore::SRecord.new(event_id: SecureRandom.uuid)
123
- ], default_stream, RubyEventStore::ExpectedVersion.none)
124
-
125
- env.unit_of_work do
126
- expect do
127
- repository.append_to_stream([
128
- RubyEventStore::SRecord.new(event_id: '9bedf448-e4d0-41a3-a8cd-f94aec7aa763')
129
- ], default_stream, RubyEventStore::ExpectedVersion.none)
130
- end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
131
- expect(repository.has_event?('9bedf448-e4d0-41a3-a8cd-f94aec7aa763')).to be_falsey
132
- expect(repository.read(specification.limit(2).result).to_a).to eq([event])
133
- end
134
- expect(repository.has_event?('9bedf448-e4d0-41a3-a8cd-f94aec7aa763')).to be_falsey
135
- expect(repository.read(specification.limit(2).result).to_a).to eq([event])
136
- end
137
-
138
- def cleanup_concurrency_test
139
- rom_helper.close_pool_connection
140
- end
141
-
142
- def verify_conncurency_assumptions
143
- expect(rom_helper.connection_pool_size).to eq(5)
144
- end
145
-
146
- # TODO: Port from AR to ROM
147
- def additional_limited_concurrency_for_auto_check
148
- positions = rom_container.relations[:stream_entries]
149
- .ordered(:forward, default_stream)
150
- .map { |entity| entity[:position] }
151
- expect(positions).to eq((0..positions.size - 1).to_a)
152
- end
153
-
154
- private
155
-
156
- # TODO: Port from AR to ROM
157
- def count_queries
158
- count = 0
159
- # counter_f = lambda { |_name, _started, _finished, _unique_id, payload|
160
- # count += 1 unless %w[CACHE SCHEMA].include?(payload[:name])
161
- # }
162
- # ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)
163
- count
164
- end
165
-
166
- # TODO: Port from AR to ROM
167
- def expect_query(_match)
168
- count = 0
169
- # counter_f = lambda { |_name, _started, _finished, _unique_id, payload|
170
- # count += 1 if match === payload[:sql]
171
- # }
172
- # ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)
173
- expect(count).to eq(1)
174
- end
175
- end
176
- end
@@ -1,75 +0,0 @@
1
- RSpec.shared_examples :events_relation do |_relation_class|
2
- subject(:relation) { rom_container.relations[:events] }
3
-
4
- let(:env) { rom_helper.env }
5
- let(:rom_container) { env.rom_container }
6
- let(:rom_db) { rom_container.gateways[:default] }
7
-
8
- around(:each) do |example|
9
- rom_helper.run_lifecycle { example.run }
10
- end
11
-
12
- it 'just created is empty' do
13
- expect(relation.to_a).to be_empty
14
- end
15
-
16
- specify '#exist? indicates if one instance of the record exists by primary key' do
17
- event = { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now }
18
-
19
- expect(relation.by_pk(event[:id]).exist?).to eq(false)
20
-
21
- relation.insert(event)
22
-
23
- expect(relation.by_pk(event[:id]).exist?).to eq(true)
24
- end
25
-
26
- specify '#insert verifies tuple is unique' do
27
- events = [
28
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
29
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
30
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now }
31
- ]
32
-
33
- relation.command(:create).call(events[0..1])
34
-
35
- expect do
36
- env.handle_error(:unique_violation) { relation.insert(events[0]) }
37
- end.to raise_error(RubyEventStore::EventDuplicatedInStream)
38
- expect do
39
- env.handle_error(:unique_violation) { relation.insert(events[1]) }
40
- end.to raise_error(RubyEventStore::EventDuplicatedInStream)
41
- expect { relation.insert(events[2]) }.not_to raise_error
42
- expect do
43
- env.handle_error(:unique_violation) { relation.insert(events[2]) }
44
- end.to raise_error(RubyEventStore::EventDuplicatedInStream)
45
- end
46
-
47
- specify '#by_pk finds tuples by ID' do
48
- events = [
49
- { id: id = SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
50
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
51
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now }
52
- ]
53
-
54
- relation.command(:create).call(events)
55
-
56
- expect(relation.by_pk(id).to_a.size).to eq(1)
57
- expect(relation.by_pk(id).to_a.map { |e| e[:id] }).to eq([id])
58
- end
59
-
60
- specify 'each method returns proper type' do
61
- events = [
62
- { id: id = SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
63
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now },
64
- { id: SecureRandom.uuid, event_type: 'TestEvent', data: '{}', metadata: '{}', created_at: Time.now }
65
- ]
66
-
67
- relation.command(:create).call(events)
68
-
69
- expect(relation.by_pk(SecureRandom.uuid).exist?).to eq(false)
70
- expect(relation.by_pk(id).exist?).to eq(true)
71
-
72
- expect(relation.by_pk(id)).to be_a(relation.class)
73
- # expect(relation.by_pk(id).first).to be_a(::ROM::Struct)
74
- end
75
- end