ruby_event_store-rom 0.30.0 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f2cadf18b1a9e4c39002fd8d23c4d2b44a96f784eb4789d1e3faa972f3353af
4
- data.tar.gz: 259cdfd63aa4f52aeee63d5d1b0dbfc86f4d669f5a7794743c127d0b5f2b9767
3
+ metadata.gz: 578db4e9a6e68483348133d15dfee076b76a29a76ac6ae5ec6e7b94063bf7284
4
+ data.tar.gz: cb177a748a62f91911ace80e4c5175a5cc4cda773947eff6d855249d71a7b8e6
5
5
  SHA512:
6
- metadata.gz: e42552f06a8d409406f046385e70e4296048396bbe47d126b36d90280d41d50a62293d60e9ffc86bc8f7653a93118a13e615f46f941ba1b7e8a41189ee110c98
7
- data.tar.gz: 123ec9e8fafb080c5e48300b7f94c87a2c15a99bdf9cf898572767a43ffdd4ada396e87aa7621ed449df176ec0a6791954488f8fc0884dac0d711dd209ba1ab4
6
+ metadata.gz: b0124ece3841ae0774b5a758cf5c154d5406060dfeae4803072ad37d08ad56d0305d33a81fdbe3359e834fcc8412270e50176a39b49f3ca38ecf68283e8faa6a
7
+ data.tar.gz: f773ecdc66ee0ff1974ca9977ea9b003cf63b4ac8212ddfda997c8f7c13c76693c65281cf0684f35fb43290cb411b7e3b971780f6815480fb34a2c1dc871221f
data/Makefile CHANGED
@@ -1,25 +1,42 @@
1
1
  GEM_VERSION = $(shell cat ../RES_VERSION)
2
2
  GEM_NAME = ruby_event_store-rom
3
3
  REQUIRE = $(GEM_NAME)
4
- IGNORE = RubyEventStore::ROM::EventRepository\#handle_not_found_errors \
4
+ IGNORE = RubyEventStore::ROM::EventRepository\#initialize \
5
+ RubyEventStore::ROM::EventRepository\#handle_not_found_errors \
5
6
  RubyEventStore::ROM::EventRepository\#handle_unique_violation_errors \
6
7
  RubyEventStore::ROM::EventRepository\#has_event? \
7
8
  RubyEventStore::ROM::EventRepository\#last_stream_event \
8
9
  RubyEventStore::ROM::Repositories::Events\#find_nonexistent_pks \
10
+ RubyEventStore::ROM::Repositories::StreamEntries\#create_changeset \
9
11
  RubyEventStore::ROM::Env\#handle_error \
10
12
  RubyEventStore::ROM::Env\#initialize \
11
13
  RubyEventStore::ROM::Env\#register_error_handler \
12
14
  RubyEventStore::ROM::Env\#register_unit_of_work_options \
13
- RubyEventStore::ROM::Env\#transaction \
15
+ RubyEventStore::ROM::Env\#unit_of_work \
14
16
  RubyEventStore::ROM::UnitOfWork\#call \
15
17
  RubyEventStore::ROM::UnitOfWork\#commit! \
16
18
  RubyEventStore::ROM::SQL::Relations::StreamEntries\#normalize_stream_name \
17
19
  RubyEventStore::ROM::SQL::IndexViolationDetector\#detect \
20
+ RubyEventStore::ROM::SQL::SpecHelper\#initialize \
21
+ RubyEventStore::ROM::SQL::SpecHelper\#has_connection_pooling? \
22
+ RubyEventStore::ROM::SQL::SpecHelper\#close_pool_connection \
18
23
  RubyEventStore::ROM::SQL::SpecHelper\#load_gateway_schema \
19
24
  RubyEventStore::ROM::SQL::SpecHelper\#establish_gateway_connection \
20
25
  RubyEventStore::ROM::SQL::SpecHelper\#drop_gateway_schema \
21
26
  RubyEventStore::ROM::SQL::SpecHelper\#close_gateway_connection \
22
- RubyEventStore::ROM::SQL::UnitOfWork\#commit!
27
+ RubyEventStore::ROM::SQL::SpecHelper\#run_lifecycle \
28
+ RubyEventStore::ROM::SQL::UnitOfWork\#commit! \
29
+ RubyEventStore::ROM::Memory::SpecHelper\#initialize \
30
+ RubyEventStore::ROM::Memory::SpecHelper\#close_pool_connection \
31
+ RubyEventStore::ROM::Memory::SpecHelper\#load_gateway_schema \
32
+ RubyEventStore::ROM::Memory::SpecHelper\#establish_gateway_connection \
33
+ RubyEventStore::ROM::Memory::SpecHelper\#drop_gateway_schema \
34
+ RubyEventStore::ROM::Memory::SpecHelper\#close_gateway_connection \
35
+ RubyEventStore::ROM::Memory::SpecHelper\#run_lifecycle \
36
+ RubyEventStore::ROM::Memory::UnitOfWork\#commit! \
37
+ RubyEventStore::ROM::Memory::Relations::Events\#verify_uniquness! \
38
+ RubyEventStore::ROM::Memory::Relations::StreamEntries\#verify_uniquness! \
39
+ RubyEventStore::ROM::Memory::Relations::StreamEntries\#normalize_stream_name
23
40
  SUBJECT ?= RubyEventStore::ROM*
24
41
  DATABASE_URL ?= sqlite::memory:
25
42
 
@@ -0,0 +1,45 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ module Relations
5
+ class Events < ::ROM::Relation[:memory]
6
+ schema(:events) do
7
+ attribute :id, ::ROM::Types::Strict::String.meta(primary_key: true)
8
+ attribute :event_type, ::ROM::Types::Strict::String
9
+ attribute :metadata, ::ROM::Types::Strict::String.optional
10
+ attribute :data, ::ROM::Types::Strict::String
11
+ attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
12
+ end
13
+
14
+ def insert(tuple)
15
+ verify_uniquness!(tuple)
16
+ super
17
+ end
18
+
19
+ def for_stream_entries(_assoc, stream_entries)
20
+ restrict(id: stream_entries.map { |e| e[:event_id] })
21
+ end
22
+
23
+ def by_pk(id)
24
+ restrict(id: id)
25
+ end
26
+
27
+ def exist?
28
+ one?
29
+ end
30
+
31
+ def pluck(name)
32
+ map { |e| e[name] }
33
+ end
34
+
35
+ private
36
+
37
+ def verify_uniquness!(tuple)
38
+ return unless by_pk(tuple[:id]).exist?
39
+ raise TupleUniquenessError.for_event_id(tuple[:id])
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,95 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ module Relations
5
+ class StreamEntries < ::ROM::Relation[:memory]
6
+ schema(:stream_entries) do
7
+ attribute :id, ::ROM::Types::Strict::Int.meta(primary_key: true).default { RubyEventStore::ROM::Memory.fetch_next_id }
8
+ attribute :stream, ::ROM::Types::Strict::String
9
+ attribute :position, ::ROM::Types::Strict::Int.optional
10
+ attribute :event_id, ::ROM::Types::Strict::String.meta(foreign_key: true, relation: :events)
11
+ attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
12
+
13
+ associations do
14
+ belongs_to :events, as: :event, foreign_key: :event_id, override: true, view: :for_stream_entries
15
+ end
16
+ end
17
+
18
+ auto_struct true
19
+
20
+ SERIALIZED_GLOBAL_STREAM_NAME = 'all'.freeze
21
+
22
+ def offset(num)
23
+ num.zero? ? self : new(dataset.slice(num..-1))
24
+ end
25
+
26
+ def take(num)
27
+ num.nil? ? self : super
28
+ end
29
+
30
+ def insert(tuple)
31
+ verify_uniquness!(tuple)
32
+ super
33
+ end
34
+
35
+ def delete(tuple)
36
+ super tuple.to_h
37
+ end
38
+
39
+ def by_stream(stream)
40
+ restrict(stream: normalize_stream_name(stream))
41
+ end
42
+
43
+ def by_stream_and_event_id(stream, event_id)
44
+ restrict(stream: normalize_stream_name(stream), event_id: event_id).one!
45
+ end
46
+
47
+ def max_position(stream)
48
+ new(by_stream(stream).order(:position).dataset.reverse).project(:position).take(1).one
49
+ end
50
+
51
+ DIRECTION_MAP = {
52
+ forward: [false, :>],
53
+ backward: [true, :<]
54
+ }.freeze
55
+
56
+ def ordered(direction, stream, offset_entry_id = nil)
57
+ reverse, operator = DIRECTION_MAP[direction]
58
+
59
+ raise ArgumentError, 'Direction must be :forward or :backward' if order.nil?
60
+
61
+ order_columns = %i[position id]
62
+ order_columns.delete(:position) if stream.global?
63
+
64
+ query = by_stream(stream)
65
+ query = query.restrict { |tuple| tuple[:id].public_send(operator, offset_entry_id) } if offset_entry_id
66
+ query = query.order(*order_columns)
67
+ query = new(query.dataset.reverse) if reverse
68
+
69
+ query
70
+ end
71
+
72
+ private
73
+
74
+ # Verifies uniqueness of [stream, event_id] and [stream, position]
75
+ def verify_uniquness!(tuple)
76
+ stream = tuple[:stream]
77
+ attrs = %i[position event_id]
78
+ attrs.delete(:position) if Stream.new(stream).global?
79
+
80
+ attrs.each do |key|
81
+ next if key == :position && tuple[key].nil?
82
+ next if restrict(:stream => stream, key => tuple.fetch(key)).none?
83
+
84
+ raise TupleUniquenessError.public_send(:"for_stream_and_#{key}", stream, tuple.fetch(key))
85
+ end
86
+ end
87
+
88
+ def normalize_stream_name(stream)
89
+ stream.global? ? SERIALIZED_GLOBAL_STREAM_NAME : stream.name
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,49 @@
1
+ module RubyEventStore
2
+ module ROM
3
+ module Memory
4
+ class UnitOfWork < ROM::UnitOfWork
5
+ def self.mutex
6
+ @mutex ||= Mutex.new
7
+ end
8
+
9
+ def commit!(gateway, changesets, **options)
10
+ self.class.mutex.synchronize do
11
+ committed = []
12
+
13
+ begin
14
+ while changesets.size > 0
15
+ changeset = changesets.shift
16
+ relation = env.container.relations[changeset.relation.name]
17
+
18
+ case changeset
19
+ when ROM::Repositories::Events::Create
20
+ relation.by_pk(changeset.to_a.map{ |e| e[:id] }).each do |tuple|
21
+ raise TupleUniquenessError.for_event_id(tuple[:id])
22
+ end
23
+ when ROM::Repositories::StreamEntries::Create
24
+ changeset.to_a.each do |tuple|
25
+ relation.send(:verify_uniquness!, tuple)
26
+ end
27
+ else
28
+ raise ArgumentError, 'Unknown changeset'
29
+ end
30
+
31
+ committed << [changeset, relation]
32
+
33
+ changeset.commit
34
+ end
35
+ rescue StandardError
36
+ committed.reverse.each do |changeset, relation|
37
+ relation
38
+ .restrict(id: changeset.to_a.map { |e| e[:id] })
39
+ .command(:delete, result: :many).call
40
+ end
41
+
42
+ raise
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -3,7 +3,9 @@ module RubyEventStore
3
3
  module SQL
4
4
  module Relations
5
5
  class Events < ::ROM::Relation[:sql]
6
- schema(:event_store_events, as: :events, infer: true)
6
+ schema(:event_store_events, as: :events, infer: true) do
7
+ attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -4,6 +4,8 @@ module RubyEventStore
4
4
  module Relations
5
5
  class StreamEntries < ::ROM::Relation[:sql]
6
6
  schema(:event_store_events_in_streams, as: :stream_entries, infer: true) do
7
+ attribute :created_at, ::ROM::Types::Strict::Time.default { Time.now }
8
+
7
9
  associations do
8
10
  belongs_to :events, as: :event, foreign_key: :event_id
9
11
  end
@@ -11,10 +13,6 @@ module RubyEventStore
11
13
 
12
14
  alias_method :take, :limit
13
15
 
14
- def by_stream(stream)
15
- where(stream: stream.name)
16
- end
17
-
18
16
  SERIALIZED_GLOBAL_STREAM_NAME = 'all'.freeze
19
17
 
20
18
  def by_stream(stream)
@@ -47,8 +45,6 @@ module RubyEventStore
47
45
  query.order { |r| order_columns.map { |c| r[:stream_entries][c].public_send(order) } }
48
46
  end
49
47
 
50
- alias_method :take, :limit
51
-
52
48
  private
53
49
 
54
50
  def normalize_stream_name(stream)
@@ -1,15 +1,18 @@
1
1
  require 'ruby_event_store/rom/sql'
2
2
 
3
+ MIGRATIONS_PATH = 'db/migrate'
4
+
3
5
  desc 'Setup ROM EventRespository environment'
4
6
  task 'db:setup' do
7
+ Dir.chdir(Dir.pwd)
5
8
  ROM::SQL::RakeSupport.env = ::RubyEventStore::ROM.configure(:sql).container
6
9
  end
7
10
 
8
- desc "Copy RubyEventStore SQL migrations to db/migrate"
9
- task 'db:copy_migrations' => 'db:setup' do
10
- Dir[File.join(File.dirname(__FILE__), '../../../../../../db/migrate/*.rb')].each do |input|
11
+ desc 'Copy RubyEventStore SQL migrations to db/migrate'
12
+ task 'db:migrations:copy' => 'db:setup' do
13
+ Dir[File.join(File.dirname(__FILE__), '../../../../../../', MIGRATIONS_PATH, '/*.rb')].each do |input|
11
14
  name = File.basename(input, '.*').sub(/\d+_/, '')
12
- output = ROM::SQL::RakeSupport.create_migration(name)
15
+ output = ROM::SQL::RakeSupport.create_migration(name, path: File.join(Dir.pwd, MIGRATIONS_PATH))
13
16
 
14
17
  File.write output, File.read(input)
15
18
 
@@ -1,9 +1,17 @@
1
1
  require 'ruby_event_store/rom/unit_of_work'
2
+ require 'forwardable'
2
3
 
3
4
  module RubyEventStore
4
5
  module ROM
5
6
  class EventRepository
7
+ extend Forwardable
8
+
9
+ def_delegator :@rom, :handle_error, :guard_for
10
+ def_delegators :@rom, :unit_of_work
11
+
6
12
  def initialize(rom: ROM.env)
13
+ raise ArgumentError, "Must specify rom" unless rom && rom.instance_of?(Env)
14
+
7
15
  @rom = rom
8
16
  @events = Repositories::Events.new(rom.container)
9
17
  @stream_entries = Repositories::StreamEntries.new(rom.container)
@@ -13,31 +21,44 @@ module RubyEventStore
13
21
  events = normalize_to_array(events)
14
22
  event_ids = events.map(&:event_id)
15
23
 
16
- @rom.transaction do |changesets|
17
- # Create changesets inside transaction because
18
- # we want to find the last position (a.k.a. version)
19
- # again if the transaction is retried due to a
20
- # deadlock in MySQL
21
- changesets << @events.create_changeset(events)
22
- changesets << @stream_entries.create_changeset(event_ids, stream, expected_version, global_stream: true)
24
+ guard_for(:unique_violation) do
25
+ unit_of_work do |changesets|
26
+ # Create changesets inside transaction because
27
+ # we want to find the last position (a.k.a. version)
28
+ # again if the transaction is retried due to a
29
+ # deadlock in MySQL
30
+ changesets << @events.create_changeset(events)
31
+ changesets << @stream_entries.create_changeset(
32
+ event_ids,
33
+ stream,
34
+ @stream_entries.resolve_version(stream, expected_version),
35
+ global_stream: true
36
+ )
37
+ end
23
38
  end
24
39
 
25
40
  self
26
- rescue => ex
27
- @rom.handle_error(:unique_violation, ex)
28
41
  end
29
42
 
30
43
  def link_to_stream(event_ids, stream, expected_version)
31
44
  event_ids = normalize_to_array(event_ids)
32
- nonexistent_ids = @events.find_nonexistent_pks(event_ids)
33
-
34
- nonexistent_ids.each { |id| raise EventNotFound.new(id) }
35
45
 
36
- @stream_entries.create_changeset(event_ids, stream, expected_version).commit
46
+ # Validate event IDs
47
+ @events
48
+ .find_nonexistent_pks(event_ids)
49
+ .each { |id| raise EventNotFound.new(id) }
50
+
51
+ guard_for(:unique_violation) do
52
+ unit_of_work do |changesets|
53
+ changesets << @stream_entries.create_changeset(
54
+ event_ids,
55
+ stream,
56
+ @stream_entries.resolve_version(stream, expected_version)
57
+ )
58
+ end
59
+ end
37
60
 
38
61
  self
39
- rescue => ex
40
- @rom.handle_error(:unique_violation, ex)
41
62
  end
42
63
 
43
64
  def delete_stream(stream)
@@ -45,12 +66,8 @@ module RubyEventStore
45
66
  end
46
67
 
47
68
  def has_event?(event_id)
48
- @events.exist?(event_id)
49
- rescue => ex
50
- begin
51
- @rom.handle_error(:not_found, ex, event_id)
52
- rescue EventNotFound
53
- false
69
+ !! guard_for(:not_found, event_id, swallow: EventNotFound) do
70
+ @events.exist?(event_id)
54
71
  end
55
72
  end
56
73
 
@@ -65,9 +82,9 @@ module RubyEventStore
65
82
  end
66
83
 
67
84
  def read_event(event_id)
68
- @events.by_id(event_id)
69
- rescue => ex
70
- @rom.handle_error(:not_found, ex, event_id)
85
+ guard_for(:not_found, event_id) do
86
+ @events.by_id(event_id)
87
+ end
71
88
  end
72
89
 
73
90
  def read(specification)
@@ -0,0 +1,68 @@
1
+ require 'ruby_event_store/rom'
2
+ require 'rom/memory'
3
+ require_relative 'adapters/memory/unit_of_work'
4
+ require_relative 'adapters/memory/relations/events'
5
+ require_relative 'adapters/memory/relations/stream_entries'
6
+
7
+ module RubyEventStore
8
+ module ROM
9
+ module Memory
10
+ class << self
11
+ def fetch_next_id
12
+ @last_id ||= 0
13
+ @mutex ||= Mutex.new
14
+ @mutex.synchronize { @last_id += 1 }
15
+ end
16
+
17
+ def setup(config)
18
+ config.register_relation Relations::Events
19
+ config.register_relation Relations::StreamEntries
20
+ end
21
+
22
+ def configure(env)
23
+ env.register_unit_of_work_options(class: UnitOfWork)
24
+
25
+ env.register_error_handler :unique_violation, -> ex {
26
+ case ex
27
+ when TupleUniquenessError
28
+ raise EventDuplicatedInStream if ex.message =~ /event_id/
29
+ raise WrongExpectedEventVersion
30
+ end
31
+ }
32
+ end
33
+ end
34
+
35
+ class SpecHelper
36
+ attr_reader :env
37
+ attr_reader :connection_pool_size, :close_pool_connection
38
+
39
+ def initialize
40
+ @connection_pool_size = 5
41
+ @env = ROM.setup(:memory)
42
+ end
43
+
44
+ def run_lifecycle
45
+ yield
46
+ ensure
47
+ drop_gateway_schema
48
+ end
49
+
50
+ def gateway
51
+ env.container.gateways.fetch(:default)
52
+ end
53
+
54
+ def drop_gateway_schema
55
+ gateway.connection.data.values.each { |v| v.data.clear }
56
+ end
57
+
58
+ def close_gateway_connection
59
+ gateway.disconnect
60
+ end
61
+
62
+ def has_connection_pooling?
63
+ true
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -47,7 +47,7 @@ module RubyEventStore
47
47
  .offset(offset)
48
48
  .take(limit)
49
49
  .combine(:event)
50
- .map_with(:stream_entry_to_serialized_record) # Add `auto_struct: false` for Memory adapter
50
+ .map_with(:stream_entry_to_serialized_record, auto_struct: false)
51
51
  .to_ary
52
52
  end
53
53
  BatchEnumerator.new(batch_size, limit || Float::INFINITY, reader).each
@@ -56,7 +56,7 @@ module RubyEventStore
56
56
  .ordered(direction, stream, offset_entry_id)
57
57
  .take(limit)
58
58
  .combine(:event)
59
- .map_with(:stream_entry_to_serialized_record) # Add `auto_struct: false` for Memory adapter
59
+ .map_with(:stream_entry_to_serialized_record, auto_struct: false)
60
60
  .each
61
61
  end
62
62
  end
@@ -12,22 +12,19 @@ module RubyEventStore
12
12
 
13
13
  POSITION_SHIFT = 1.freeze
14
14
 
15
- def create_changeset(event_ids, stream, expected_version, global_stream: nil)
16
- resolved_version = expected_version.resolve_for(stream, ->(_stream) {
17
- (stream_entries.max_position(stream) || {})[:position]
18
- })
19
-
15
+ def create_changeset(event_ids, stream, resolved_version, global_stream: nil)
20
16
  tuples = []
21
-
17
+
22
18
  event_ids.each_with_index do |event_id, index|
23
19
  tuples << {
24
20
  stream: stream.name,
25
21
  position: resolved_version && resolved_version + index + POSITION_SHIFT,
26
22
  event_id: event_id
27
- } unless stream.global?
23
+ } unless stream.global?
28
24
 
29
- tuples << {
25
+ tuples << {
30
26
  stream: stream_entries.class::SERIALIZED_GLOBAL_STREAM_NAME,
27
+ position: nil,
31
28
  event_id: event_id
32
29
  } if global_stream
33
30
  end
@@ -36,11 +33,13 @@ module RubyEventStore
36
33
  end
37
34
 
38
35
  def delete(stream)
39
- delete_changeset(stream).commit
36
+ stream_entries.by_stream(stream).command(:delete).call
40
37
  end
41
38
 
42
- def delete_changeset(stream)
43
- stream_entries.by_stream(stream).changeset(:delete)
39
+ def resolve_version(stream, expected_version)
40
+ expected_version.resolve_for(stream, ->(_stream) {
41
+ (stream_entries.max_position(stream) || {})[:position]
42
+ })
44
43
  end
45
44
  end
46
45
  end
@@ -1,5 +1,5 @@
1
- require 'rom/sql'
2
1
  require 'ruby_event_store/rom'
2
+ require 'rom/sql'
3
3
  require_relative 'adapters/sql/index_violation_detector'
4
4
  require_relative 'adapters/sql/unit_of_work'
5
5
  require_relative 'adapters/sql/relations/events'
@@ -44,14 +44,50 @@ module RubyEventStore
44
44
  class SpecHelper
45
45
  attr_reader :env
46
46
 
47
- def initialize(rom: ROM.env)
48
- @env = rom
47
+ def initialize(database_uri = ENV['DATABASE_URL'])
48
+ config = ::ROM::Configuration.new(
49
+ :sql,
50
+ database_uri,
51
+ max_connections: database_uri =~ /sqlite/ ? 1 : 5,
52
+ preconnect: :concurrently,
53
+ # sql_mode: %w[NO_AUTO_VALUE_ON_ZERO STRICT_ALL_TABLES]
54
+ )
55
+ # $stdout.sync = true
56
+ # config.default.use_logger Logger.new(STDOUT)
57
+ # config.default.connection.pool.send(:preconnect, true)
58
+ config.default.run_migrations
59
+
60
+ @env = ROM.setup(config)
61
+ end
62
+
63
+ def run_lifecycle
64
+ establish_gateway_connection
65
+ load_gateway_schema
66
+
67
+ yield
68
+ ensure
69
+ drop_gateway_schema
70
+ close_gateway_connection
49
71
  end
50
72
 
51
73
  def gateway
52
74
  env.container.gateways.fetch(:default)
53
75
  end
54
76
 
77
+ def has_connection_pooling?
78
+ !gateway.connection.database_type.eql?(:sqlite)
79
+ end
80
+
81
+ def connection_pool_size
82
+ gateway.connection.pool.size
83
+ end
84
+
85
+ def close_pool_connection
86
+ gateway.connection.pool.disconnect
87
+ end
88
+
89
+ protected
90
+
55
91
  def establish_gateway_connection
56
92
  # Manually preconnect because disconnecting and reconnecting
57
93
  # seems to lose the "preconnect concurrently" setting
@@ -1,6 +1,19 @@
1
1
  module RubyEventStore
2
2
  module ROM
3
3
  class TupleUniquenessError < StandardError
4
+ class << self
5
+ def for_event_id(event_id)
6
+ new "Uniquness violated for event_id (#{event_id.inspect})"
7
+ end
8
+
9
+ def for_stream_and_event_id(stream_name, event_id)
10
+ new "Uniquness violated for stream (#{stream_name.inspect}) and event_id (#{event_id.inspect})"
11
+ end
12
+
13
+ def for_stream_and_position(stream_name, position)
14
+ new "Uniquness violated for stream (#{stream_name.inspect}) and position (#{position.inspect})"
15
+ end
16
+ end
4
17
  end
5
18
  end
6
19
  end
@@ -1,5 +1,5 @@
1
1
  module RubyEventStore
2
2
  module ROM
3
- VERSION = "0.30.0"
3
+ VERSION = "0.31.0"
4
4
  end
5
5
  end
@@ -24,7 +24,7 @@ module RubyEventStore
24
24
  container[:logger]
25
25
  end
26
26
 
27
- def transaction(&block)
27
+ def unit_of_work(&block)
28
28
  options = container[:unit_of_work_options].dup
29
29
  options.delete(:class){UnitOfWork}.new(rom: self).call(**options, &block)
30
30
  end
@@ -37,9 +37,15 @@ module RubyEventStore
37
37
  container[:"#{type}_error_handlers"] << handler
38
38
  end
39
39
 
40
- def handle_error(type, ex, *args)
41
- container[:"#{type}_error_handlers"].each{ |h| h.call(ex, *args) }
42
- raise ex
40
+ def handle_error(type, *args, swallow: [])
41
+ yield
42
+ rescue => ex
43
+ begin
44
+ container[:"#{type}_error_handlers"].each{ |h| h.call(ex, *args) }
45
+ raise ex
46
+ rescue *swallow
47
+ # swallow
48
+ end
43
49
  end
44
50
  end
45
51
 
@@ -51,8 +57,6 @@ module RubyEventStore
51
57
  if adapter_name.is_a?(::ROM::Configuration)
52
58
  # Call config block manually
53
59
  Env.new ::ROM.container(adapter_name.tap(&block), &block)
54
- elsif database_uri.nil?
55
- raise ArgumentError.new('Missing database URI argument or DATABASE_URL environment variable')
56
60
  else
57
61
  Env.new ::ROM.container(adapter_name, database_uri, &block)
58
62
  end