ruby_event_store-rom 2.1.0 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3af23fb98d5ccf4b0730bfd4da1dfea36b511d5b7d00e82158daaa7ed3ba6979
4
- data.tar.gz: 741f05db9dc98c607888e5a3a07a8289a3d02094e8deecfcf48da150d6388954
3
+ metadata.gz: fd644498c9073a4fedae61d6bbc305373ce49f3b5a5dc474798905b2928b5013
4
+ data.tar.gz: 41947bff3903557aa6d816a5807165613c513f99fa8d4b97e84005628c4f6b31
5
5
  SHA512:
6
- metadata.gz: f6846ccb455e16a59fe7a3e655f912f77998af55527d7e0c49278f52454d3d283e9113b70d7fff4289268dc13018d3b0ab4e0dcb774767a313078c8081e7d7fa
7
- data.tar.gz: b02ae36dbe6641fda9bb4005821f220954f1ff09672736f2f895963ba0fa366442b1aa21100fee0b20663d9b718d5f66f2a28461419caf1b45c6589cefd92bc3
6
+ metadata.gz: e572f34403a3924f2ed6343b2bdb690d31d7cdb8e85f7eff0c44caafb3ece603224e7ad6dae950b2396124f709694904d539d811cc58847b6fa2e9aa4f04e9dd
7
+ data.tar.gz: 75a35e00b8bb953bd81c4a9a4b95596db5c555b4d813e6717ff5767b6bced436f346f5d5d09debcf044f16c7e71a585da132ea5e8ac32f56a1a97b9204ed342b
data/README.md CHANGED
@@ -7,3 +7,47 @@ A Ruby Object Model (ROM) implementation of events repository for [Ruby Event St
7
7
  This version of the ROM adapter supports [rom-sql](https://github.com/rom-rb/rom-sql) at this time. It is an alternative to the ActiveRecord `EventRepository` implementation used in `rails_event_store` gem.
8
8
 
9
9
  [Read the docs to get started.](http://railseventstore.org/docs/repository/)
10
+
11
+ ## Setup
12
+
13
+ ### Rake tasks
14
+
15
+ Add to your `Rakefile`
16
+
17
+ ```ruby
18
+ require "ruby_event_store/rom/rake_task"
19
+ ```
20
+
21
+ ### Database migration
22
+
23
+ A migration template can be found in [db/migrate/20210806000000_create_ruby_event_store_tables.rb](db/migrate/20210806000000_create_ruby_event_store_tables.rb).
24
+
25
+ You can choose the type of the `data` and `metadata` columns by using the `DATA_TYPE` environment variable:
26
+
27
+ ```shell
28
+ rake db:migrate DATA_TYPE='text' # or
29
+ rake db:migrate DATA_TYPE='json' # or
30
+ rake db:migrate DATA_TYPE='jsonb'
31
+ ```
32
+
33
+ ### Application
34
+
35
+ ```ruby
36
+ # config/initializers/ruby_event_store.rb
37
+
38
+ config = ROM::Configuration.new(:sql, ENV.fetch("DATABASE_URL"))
39
+ RES_ROM_CONTAINER = RubyEventStore::ROM.setup(config)
40
+
41
+ repository = RubyEventStore::ROM::EventRepository.new(
42
+ rom: RES_ROM_CONTAINER,
43
+ serializer: JSON # this setting is optional. Recommended when `data` and `metadata` are json(b) columns.
44
+ )
45
+
46
+ event_store = RubyEventStore::Client.new(repository: repository)
47
+
48
+ event_store.subscribe_to_all_events(RubyEventStore::LinkByCausationId.new(event_store: event_store))
49
+ event_store.subscribe_to_all_events(RubyEventStore::LinkByCorrelationId.new(event_store: event_store))
50
+ event_store.subscribe_to_all_events(RubyEventStore::LinkByEventType.new(event_store: event_store))
51
+
52
+ EVENT_STORE = event_store
53
+ ```
@@ -35,7 +35,7 @@ module RubyEventStore
35
35
  .dataset
36
36
  .insert_conflict(
37
37
  target: :event_id,
38
- update: UPSERT_COLUMNS.each_with_object({}) { |column, memo| memo[column] = Sequel[:excluded][column] }
38
+ update: UPSERT_COLUMNS.each_with_object({}) { |column, memo| memo[column] = Sequel[:excluded][column] },
39
39
  )
40
40
  .multi_insert(to_a)
41
41
  end
@@ -17,12 +17,11 @@ module RubyEventStore
17
17
  handle_unique_violation do
18
18
  @unit_of_work.call do |changesets|
19
19
  changesets << @events.create_changeset(serialized_records)
20
- changesets <<
21
- @stream_entries.create_changeset(
22
- event_ids,
23
- stream,
24
- @stream_entries.resolve_version(stream, expected_version)
25
- )
20
+ changesets << @stream_entries.create_changeset(
21
+ event_ids,
22
+ stream,
23
+ @stream_entries.resolve_version(stream, expected_version),
24
+ )
26
25
  end
27
26
  end
28
27
 
@@ -34,12 +33,11 @@ module RubyEventStore
34
33
 
35
34
  handle_unique_violation do
36
35
  @unit_of_work.call do |changesets|
37
- changesets <<
38
- @stream_entries.create_changeset(
39
- event_ids,
40
- stream,
41
- @stream_entries.resolve_version(stream, expected_version)
42
- )
36
+ changesets << @stream_entries.create_changeset(
37
+ event_ids,
38
+ stream,
39
+ @stream_entries.resolve_version(stream, expected_version),
40
+ )
43
41
  end
44
42
  end
45
43
 
@@ -65,7 +63,7 @@ module RubyEventStore
65
63
  def has_event?(event_id)
66
64
  @events.exist?(event_id)
67
65
  rescue Sequel::DatabaseError => doh
68
- raise doh unless doh.message =~ /PG::InvalidTextRepresentation.*uuid/
66
+ raise doh unless /PG::InvalidTextRepresentation.*uuid/.match?(doh.message)
69
67
  false
70
68
  end
71
69
 
@@ -34,20 +34,36 @@ module RubyEventStore
34
34
  where(event_type: types)
35
35
  end
36
36
 
37
- def newer_than(time)
38
- where { |r| r.events[:created_at] > time.localtime }
37
+ def newer_than(time, time_sort_by)
38
+ if time_sort_by == :as_of
39
+ where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) > time.localtime }
40
+ else
41
+ where { |r| r.events[:created_at] > time.localtime }
42
+ end
39
43
  end
40
44
 
41
- def newer_than_or_equal(time)
42
- where { |r| r.events[:created_at] >= time.localtime }
45
+ def newer_than_or_equal(time, time_sort_by)
46
+ if time_sort_by == :as_of
47
+ where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) >= time.localtime }
48
+ else
49
+ where { |r| r.events[:created_at] >= time.localtime }
50
+ end
43
51
  end
44
52
 
45
- def older_than(time)
46
- where { |r| r.events[:created_at] < time.localtime }
53
+ def older_than(time, time_sort_by)
54
+ if time_sort_by == :as_of
55
+ where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) < time.localtime }
56
+ else
57
+ where { |r| r.events[:created_at] < time.localtime }
58
+ end
47
59
  end
48
60
 
49
- def older_than_or_equal(time)
50
- where { |r| r.events[:created_at] <= time.localtime }
61
+ def older_than_or_equal(time, time_sort_by)
62
+ if time_sort_by == :as_of
63
+ where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) <= time.localtime }
64
+ else
65
+ where { |r| r.events[:created_at] <= time.localtime }
66
+ end
51
67
  end
52
68
 
53
69
  DIRECTION_MAP = { forward: %i[asc > <], backward: %i[desc < >] }.freeze
@@ -23,7 +23,7 @@ module RubyEventStore
23
23
  end
24
24
 
25
25
  def by_event_type(types)
26
- join(:events).where(event_type: types)
26
+ join_events.where(event_type: types)
27
27
  end
28
28
 
29
29
  def by_stream_and_event_id(stream, event_id)
@@ -34,20 +34,36 @@ module RubyEventStore
34
34
  by_stream(stream).select(:position).order(Sequel.desc(:position)).first
35
35
  end
36
36
 
37
- def newer_than(time)
38
- join(:events).where { |r| r.events[:created_at] > time.localtime }
37
+ def newer_than(time, time_sort_by)
38
+ if time_sort_by == :as_of
39
+ join_events.where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) > time.localtime }
40
+ else
41
+ join_events.where { |r| r.events[:created_at] > time.localtime }
42
+ end
39
43
  end
40
44
 
41
- def newer_than_or_equal(time)
42
- join(:events).where { |r| r.events[:created_at] >= time.localtime }
45
+ def newer_than_or_equal(time, time_sort_by)
46
+ if time_sort_by == :as_of
47
+ join_events.where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) >= time.localtime }
48
+ else
49
+ join_events.where { |r| r.events[:created_at] >= time.localtime }
50
+ end
43
51
  end
44
52
 
45
- def older_than(time)
46
- join(:events).where { |r| r.events[:created_at] < time.localtime }
53
+ def older_than(time, time_sort_by)
54
+ if time_sort_by == :as_of
55
+ join_events.where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) < time.localtime }
56
+ else
57
+ join_events.where { |r| r.events[:created_at] < time.localtime }
58
+ end
47
59
  end
48
60
 
49
- def older_than_or_equal(time)
50
- join(:events).where { |r| r.events[:created_at] <= time.localtime }
61
+ def older_than_or_equal(time, time_sort_by)
62
+ if time_sort_by == :as_of
63
+ join_events.where { |r| string.coalesce(r.events[:valid_at], r.events[:created_at]) <= time.localtime }
64
+ else
65
+ join_events.where { |r| r.events[:created_at] <= time.localtime }
66
+ end
51
67
  end
52
68
 
53
69
  DIRECTION_MAP = { forward: %i[asc > <], backward: %i[desc < >] }.freeze
@@ -74,9 +90,13 @@ module RubyEventStore
74
90
  if event_order_columns.empty?
75
91
  query.order { |r| stream_order_columns.map { |c| r[:stream_entries][c].public_send(order) } }
76
92
  else
77
- query.join(:events).order { |r| event_order_columns.map { |c| r.events[c].public_send(order) } }
93
+ query.join_events.order { |r| event_order_columns.map { |c| r.events[c].public_send(order) } }
78
94
  end
79
95
  end
96
+
97
+ def join_events
98
+ dataset.opts[:join]&.map(&:table)&.include?(events.dataset.first_source_table) ? self : join(:events)
99
+ end
80
100
  end
81
101
  end
82
102
  end
@@ -37,7 +37,7 @@ module RubyEventStore
37
37
  BatchEnumerator.new(
38
38
  specification.batch_size,
39
39
  specification.limit,
40
- ->(offset, limit) { query_builder(serializer, query, offset: offset, limit: limit).to_ary }
40
+ ->(offset, limit) { query_builder(serializer, query, offset: offset, limit: limit).to_ary },
41
41
  ).each
42
42
  else
43
43
  query = query_builder(serializer, query, limit: (specification.limit if specification.limit?))
@@ -65,6 +65,18 @@ module RubyEventStore
65
65
 
66
66
  protected
67
67
 
68
+ def find_event_id_in_stream(specification_event_id, specification_stream_name)
69
+ stream_entries.by_stream_and_event_id(specification_stream_name, specification_event_id).fetch(:id)
70
+ rescue ::ROM::TupleCountMismatchError
71
+ raise EventNotFound.new(specification_event_id)
72
+ end
73
+
74
+ def find_event_id_globally(specification_event_id)
75
+ events.by_event_id(specification_event_id).one!.fetch(:id)
76
+ rescue ::ROM::TupleCountMismatchError
77
+ raise EventNotFound.new(specification_event_id)
78
+ end
79
+
68
80
  def read_scope(specification)
69
81
  direction = specification.forward? ? :forward : :backward
70
82
 
@@ -73,20 +85,14 @@ module RubyEventStore
73
85
  end
74
86
 
75
87
  if specification.stream.global?
76
- offset_entry_id = events.by_event_id(specification.start).one!.fetch(:id) if specification.start
77
- stop_entry_id = events.by_event_id(specification.stop).one!.fetch(:id) if specification.stop
88
+ offset_entry_id = find_event_id_globally(specification.start) if specification.start
89
+ stop_entry_id = find_event_id_globally(specification.stop) if specification.stop
78
90
 
79
91
  query = events.ordered(direction, offset_entry_id, stop_entry_id, specification.time_sort_by)
80
92
  query = query.map_with(:event_to_serialized_record, auto_struct: false)
81
93
  else
82
- offset_entry_id =
83
- stream_entries
84
- .by_stream_and_event_id(specification.stream, specification.start)
85
- .fetch(:id) if specification.start
86
- stop_entry_id =
87
- stream_entries
88
- .by_stream_and_event_id(specification.stream, specification.stop)
89
- .fetch(:id) if specification.stop
94
+ offset_entry_id = find_event_id_in_stream(specification.start, specification.stream) if specification.start
95
+ stop_entry_id = find_event_id_in_stream(specification.stop, specification.stream) if specification.stop
90
96
 
91
97
  query =
92
98
  stream_entries.ordered(
@@ -94,7 +100,7 @@ module RubyEventStore
94
100
  specification.stream,
95
101
  offset_entry_id,
96
102
  stop_entry_id,
97
- specification.time_sort_by
103
+ specification.time_sort_by,
98
104
  )
99
105
  query = query.combine(:event)
100
106
  query = query.map_with(:stream_entry_to_serialized_record, auto_struct: false)
@@ -102,10 +108,18 @@ module RubyEventStore
102
108
 
103
109
  query = query.by_event_id(specification.with_ids) if specification.with_ids
104
110
  query = query.by_event_type(specification.with_types) if specification.with_types?
105
- query = query.older_than(specification.older_than) if specification.older_than
106
- query = query.older_than_or_equal(specification.older_than_or_equal) if specification.older_than_or_equal
107
- query = query.newer_than(specification.newer_than) if specification.newer_than
108
- query = query.newer_than_or_equal(specification.newer_than_or_equal) if specification.newer_than_or_equal
111
+ query = query.older_than(specification.older_than, specification.time_sort_by) if specification.older_than
112
+ query =
113
+ query.older_than_or_equal(
114
+ specification.older_than_or_equal,
115
+ specification.time_sort_by,
116
+ ) if specification.older_than_or_equal
117
+ query = query.newer_than(specification.newer_than, specification.time_sort_by) if specification.newer_than
118
+ query =
119
+ query.newer_than_or_equal(
120
+ specification.newer_than_or_equal,
121
+ specification.time_sort_by,
122
+ ) if specification.newer_than_or_equal
109
123
  query
110
124
  end
111
125
 
@@ -14,7 +14,7 @@ module RubyEventStore
14
14
  tuples << {
15
15
  stream: stream.name,
16
16
  position: resolved_version && resolved_version + index + POSITION_SHIFT,
17
- event_id: event_id
17
+ event_id: event_id,
18
18
  }
19
19
  end
20
20
  end
@@ -29,7 +29,7 @@ module RubyEventStore
29
29
  def resolve_version(stream, expected_version)
30
30
  expected_version.resolve_for(
31
31
  stream,
32
- lambda { |_stream| (stream_entries.max_position(stream) || {})[:position] }
32
+ lambda { |_stream| (stream_entries.max_position(stream) || {})[:position] },
33
33
  )
34
34
  end
35
35
 
@@ -32,7 +32,7 @@ module RubyEventStore
32
32
  before_retry:
33
33
  lambda do |_num, ex|
34
34
  env.logger.warn("RETRY TRANSACTION [#{self.class.name} => #{ex.class.name}] #{ex.message}")
35
- end
35
+ end,
36
36
  ) { changesets.each(&:commit) }
37
37
  end
38
38
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyEventStore
4
4
  module ROM
5
- VERSION = "2.1.0"
5
+ VERSION = "2.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_event_store-rom
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Van Horn
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-03-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: dry-container
@@ -117,7 +116,7 @@ dependencies:
117
116
  version: 2.0.0
118
117
  - - "<"
119
118
  - !ruby/object:Gem::Version
120
- version: 3.0.0
119
+ version: 4.0.0
121
120
  type: :runtime
122
121
  prerelease: false
123
122
  version_requirements: !ruby/object:Gem::Requirement
@@ -127,7 +126,7 @@ dependencies:
127
126
  version: 2.0.0
128
127
  - - "<"
129
128
  - !ruby/object:Gem::Version
130
- version: 3.0.0
129
+ version: 4.0.0
131
130
  description: Implementation of events repository based on ROM for Ruby Event Store
132
131
  email: joel@joelvanhorn.com
133
132
  executables: []
@@ -163,7 +162,6 @@ metadata:
163
162
  source_code_uri: https://github.com/RailsEventStore/rails_event_store
164
163
  bug_tracker_uri: https://github.com/RailsEventStore/rails_event_store/issues
165
164
  rubygems_mfa_required: 'true'
166
- post_install_message:
167
165
  rdoc_options: []
168
166
  require_paths:
169
167
  - lib
@@ -171,15 +169,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
171
169
  requirements:
172
170
  - - ">="
173
171
  - !ruby/object:Gem::Version
174
- version: '2.5'
172
+ version: '2.7'
175
173
  required_rubygems_version: !ruby/object:Gem::Requirement
176
174
  requirements:
177
175
  - - ">="
178
176
  - !ruby/object:Gem::Version
179
177
  version: '0'
180
178
  requirements: []
181
- rubygems_version: 3.4.6
182
- signing_key:
179
+ rubygems_version: 3.7.1
183
180
  specification_version: 4
184
181
  summary: ROM events repository for Ruby Event Store
185
182
  test_files: []