rails_event_store_active_record 0.23.0 → 0.24.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
  SHA1:
3
- metadata.gz: 06ea3fef184541012ee334e70e402adf48805ece
4
- data.tar.gz: ebe5b085930e57e45abbe1015e6cd31ca84c0650
3
+ metadata.gz: aa7cbc8a46e69a907a86eb49221525581ced5792
4
+ data.tar.gz: e585c4784333d52636512824facd16ebc5b09657
5
5
  SHA512:
6
- metadata.gz: bc05259c542106541612cc624832e3f2b475e579a510396b28e32adde6652e663151a2eb1ee5c8dd3f9f8e73340ae41c931482722d755b8513e8565b34ead33c
7
- data.tar.gz: df3e1ce033b90271cdb4b0a77bef69455ac807b176b73ffae84fe380bd7964c8265729203180a781fcdac3d04b09c1a26b0fcf9f7b76d54f59f1ac1d5c8dfca3
6
+ metadata.gz: 919a3e5a8715712d4a4750d7885a8889cacf8acca6abb23f1e975f797149a10df2cd4f5971cd406d6ff9a46972fae6890d648dd17d06d50c4cc2dccf728678e0
7
+ data.tar.gz: 00da8c71db44a47186acd50b1d99dcca82646d47777cdcb22d39cee96f15734c57babb722cdc73d0fffa4c0d1e04e8b7f68ed9bc3e5ce391ad5e5a40ee9eec5e
data/Makefile CHANGED
@@ -13,9 +13,7 @@ test: ## Run tests
13
13
  mutate: test ## Run mutation tests
14
14
  @echo "Running mutation tests - only 100% free mutation will be accepted"
15
15
  @bundle exec mutant --include lib --require ruby_event_store --use rspec "RailsEventStoreActiveRecord*" \
16
- --ignore-subject "RailsEventStoreActiveRecord::EventRepository#normalize_to_array" \
17
- --ignore-subject "RailsEventStoreActiveRecord::LegacyEventRepository#normalize_to_array" \
18
- --ignore-subject "RailsEventStoreActiveRecord::EventRepository#detect_index_violated"
16
+ --ignore-subject "RailsEventStoreActiveRecord::IndexViolationDetector#detect"
19
17
 
20
18
  build:
21
19
  @gem build -V rails_event_store_active_record.gemspec
@@ -2,5 +2,8 @@ require 'rails_event_store_active_record/generators/migration_generator'
2
2
  require 'rails_event_store_active_record/generators/v1_v2_migration_generator'
3
3
  require 'rails_event_store_active_record/event'
4
4
  require 'rails_event_store_active_record/event_repository'
5
+ require 'rails_event_store_active_record/event_repository_reader'
6
+ require 'rails_event_store_active_record/correct_schema_verifier'
7
+ require 'rails_event_store_active_record/index_violation_detector'
5
8
  require 'rails_event_store_active_record/legacy_event_repository'
6
9
  require 'rails_event_store_active_record/version'
@@ -0,0 +1,65 @@
1
+ module RailsEventStoreActiveRecord
2
+
3
+ class EventRepository
4
+ InvalidDatabaseSchema = Class.new(StandardError)
5
+ end
6
+
7
+ class CorrectSchemaVerifier
8
+ def verify
9
+ return unless ActiveRecord::Base.connected?
10
+ raise_invalid_db_schema if legacy_columns.eql?(current_columns)
11
+ end
12
+
13
+ private
14
+
15
+ def raise_invalid_db_schema
16
+ raise EventRepository::InvalidDatabaseSchema.new(incorrect_schema_message)
17
+ end
18
+
19
+ def legacy_columns
20
+ [
21
+ "id",
22
+ "stream",
23
+ "event_type",
24
+ "event_id",
25
+ "metadata",
26
+ "data",
27
+ "created_at"
28
+ ]
29
+ end
30
+
31
+ def current_columns
32
+ ActiveRecord::Base.connection.columns("event_store_events").map(&:name)
33
+ end
34
+
35
+ def incorrect_schema_message
36
+ <<-MESSAGE
37
+ Oh no!
38
+
39
+ It seems you're using RailsEventStoreActiveRecord::EventRepository
40
+ with incompaible database schema.
41
+
42
+ We've redesigned database structure in order to fix several concurrency-related
43
+ bugs. This repository is intended to work on that improved data layout.
44
+
45
+ We've prepared migration that would take you from old schema to new one.
46
+ This migration must be run offline -- take that into consideration:
47
+
48
+ rails g rails_event_store_active_record:v1_v2_migration
49
+ rake db:migrate
50
+
51
+
52
+ If you cannot migrate right now -- you can for some time continue using
53
+ old repository. In order to do so, change configuration accordingly:
54
+
55
+ config.event_store = RailsEventStore::Client.new(
56
+ repository: RailsEventStoreActiveRecord::LegacyEventRepository.new
57
+ )
58
+
59
+
60
+ MESSAGE
61
+ end
62
+ end
63
+
64
+ private_constant(:CorrectSchemaVerifier)
65
+ end
@@ -2,17 +2,17 @@ require 'activerecord-import'
2
2
 
3
3
  module RailsEventStoreActiveRecord
4
4
  class EventRepository
5
- InvalidDatabaseSchema = Class.new(StandardError)
6
5
 
7
6
  POSITION_SHIFT = 1
8
7
 
9
8
  def initialize(mapper: RubyEventStore::Mappers::Default.new)
10
9
  verify_correct_schema_present
11
- @mapper = mapper
10
+ @mapper = mapper
11
+ @repo_reader = EventRepositoryReader.new(mapper)
12
12
  end
13
13
 
14
14
  def append_to_stream(events, stream_name, expected_version)
15
- add_to_stream(events, stream_name, expected_version, true) do |event|
15
+ add_to_stream(normalize_to_array(events), stream_name, expected_version, true) do |event|
16
16
  build_event_record(event).save!
17
17
  event.event_id
18
18
  end
@@ -22,7 +22,7 @@ module RailsEventStoreActiveRecord
22
22
  (normalize_to_array(event_ids) - Event.where(id: event_ids).pluck(:id)).each do |id|
23
23
  raise RubyEventStore::EventNotFound.new(id)
24
24
  end
25
- add_to_stream(event_ids, stream_name, expected_version, nil) do |event_id|
25
+ add_to_stream(normalize_to_array(event_ids), stream_name, expected_version, nil) do |event_id|
26
26
  event_id
27
27
  end
28
28
  end
@@ -32,85 +32,43 @@ module RailsEventStoreActiveRecord
32
32
  end
33
33
 
34
34
  def has_event?(event_id)
35
- Event.exists?(id: event_id)
35
+ @repo_reader.has_event?(event_id)
36
36
  end
37
37
 
38
38
  def last_stream_event(stream_name)
39
- record = EventInStream.where(stream: stream_name).order('position DESC, id DESC').first
40
- record && build_event_instance(record)
39
+ @repo_reader.last_stream_event(stream_name)
41
40
  end
42
41
 
43
42
  def read_events_forward(stream_name, after_event_id, count)
44
- stream = EventInStream.where(stream: stream_name)
45
- unless after_event_id.equal?(:head)
46
- after_event = stream.find_by!(event_id: after_event_id)
47
- stream = stream.where('id > ?', after_event)
48
- end
49
-
50
- stream.preload(:event).order('position ASC, id ASC').limit(count)
51
- .map(&method(:build_event_instance))
43
+ @repo_reader.read_events_forward(stream_name, after_event_id, count)
52
44
  end
53
45
 
54
46
  def read_events_backward(stream_name, before_event_id, count)
55
- stream = EventInStream.where(stream: stream_name)
56
- unless before_event_id.equal?(:head)
57
- before_event = stream.find_by!(event_id: before_event_id)
58
- stream = stream.where('id < ?', before_event)
59
- end
60
-
61
- stream.preload(:event).order('position DESC, id DESC').limit(count)
62
- .map(&method(:build_event_instance))
47
+ @repo_reader.read_events_backward(stream_name, before_event_id, count)
63
48
  end
64
49
 
65
50
  def read_stream_events_forward(stream_name)
66
- EventInStream.preload(:event).where(stream: stream_name).order('position ASC, id ASC')
67
- .map(&method(:build_event_instance))
51
+ @repo_reader.read_stream_events_forward(stream_name)
68
52
  end
69
53
 
70
54
  def read_stream_events_backward(stream_name)
71
- EventInStream.preload(:event).where(stream: stream_name).order('position DESC, id DESC')
72
- .map(&method(:build_event_instance))
55
+ @repo_reader.read_stream_events_backward(stream_name)
73
56
  end
74
57
 
75
58
  def read_all_streams_forward(after_event_id, count)
76
- stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
77
- unless after_event_id.equal?(:head)
78
- after_event = stream.find_by!(event_id: after_event_id)
79
- stream = stream.where('id > ?', after_event)
80
- end
81
-
82
- stream.preload(:event).order('id ASC').limit(count)
83
- .map(&method(:build_event_instance))
59
+ @repo_reader.read_all_streams_forward(after_event_id, count)
84
60
  end
85
61
 
86
62
  def read_all_streams_backward(before_event_id, count)
87
- stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
88
- unless before_event_id.equal?(:head)
89
- before_event = stream.find_by!(event_id: before_event_id)
90
- stream = stream.where('id < ?', before_event)
91
- end
92
-
93
- stream.preload(:event).order('id DESC').limit(count)
94
- .map(&method(:build_event_instance))
63
+ @repo_reader.read_all_streams_backward(before_event_id, count)
95
64
  end
96
65
 
97
66
  def read_event(event_id)
98
- event = Event.find(event_id)
99
- serialized_record = RubyEventStore::SerializedRecord.new(
100
- event_id: event.id,
101
- metadata: event.metadata,
102
- data: event.data,
103
- event_type: event.event_type
104
- )
105
- mapper.serialized_record_to_event(serialized_record)
106
- rescue ActiveRecord::RecordNotFound
107
- raise RubyEventStore::EventNotFound.new(event_id)
67
+ @repo_reader.read_event(event_id)
108
68
  end
109
69
 
110
70
  def get_all_streams
111
- (["all"] + EventInStream.pluck(:stream))
112
- .uniq
113
- .map { |name| RubyEventStore::Stream.new(name) }
71
+ @repo_reader.get_all_streams
114
72
  end
115
73
 
116
74
  private
@@ -120,7 +78,6 @@ module RailsEventStoreActiveRecord
120
78
  def add_to_stream(collection, stream_name, expected_version, include_global, &to_event_id)
121
79
  raise RubyEventStore::InvalidExpectedVersion if stream_name.eql?(RubyEventStore::GLOBAL_STREAM) && !expected_version.equal?(:any)
122
80
 
123
- collection = normalize_to_array(collection)
124
81
  expected_version = normalize_expected_version(expected_version, stream_name)
125
82
 
126
83
  ActiveRecord::Base.transaction(requires_new: true) do
@@ -148,7 +105,7 @@ module RailsEventStoreActiveRecord
148
105
  end
149
106
 
150
107
  def raise_error(e)
151
- if detect_index_violated(e)
108
+ if detect_index_violated(e.message)
152
109
  raise RubyEventStore::EventDuplicatedInStream
153
110
  end
154
111
  raise RubyEventStore::WrongExpectedEventVersion
@@ -174,23 +131,8 @@ module RailsEventStoreActiveRecord
174
131
  end
175
132
  end
176
133
 
177
- MYSQL_PKEY_ERROR = "for key 'PRIMARY'"
178
- POSTGRES_PKEY_ERROR = "event_store_events_pkey"
179
- SQLITE3_PKEY_ERROR = "event_store_events.id"
180
-
181
- MYSQL_INDEX_ERROR = "for key 'index_event_store_events_in_streams_on_stream_and_event_id'"
182
- POSTGRES_INDEX_ERROR = "Key (stream, event_id)"
183
- SQLITE3_INDEX_ERROR = "event_store_events_in_streams.stream, event_store_events_in_streams.event_id"
184
-
185
- def detect_index_violated(e)
186
- m = e.message
187
- m.include?(MYSQL_PKEY_ERROR) ||
188
- m.include?(POSTGRES_PKEY_ERROR) ||
189
- m.include?(SQLITE3_PKEY_ERROR) ||
190
-
191
- m.include?(MYSQL_INDEX_ERROR) ||
192
- m.include?(POSTGRES_INDEX_ERROR) ||
193
- m.include?(SQLITE3_INDEX_ERROR)
134
+ def detect_index_violated(message)
135
+ IndexViolationDetector.new.detect(message)
194
136
  end
195
137
 
196
138
  def build_event_record(event)
@@ -203,53 +145,14 @@ module RailsEventStoreActiveRecord
203
145
  )
204
146
  end
205
147
 
206
- def build_event_instance(record)
207
- serialized_record = RubyEventStore::SerializedRecord.new(
208
- event_id: record.event.id,
209
- metadata: record.event.metadata,
210
- data: record.event.data,
211
- event_type: record.event.event_type
212
- )
213
- mapper.serialized_record_to_event(serialized_record)
214
- end
215
-
216
148
  def normalize_to_array(events)
217
- [*events]
218
- end
219
-
220
- def incorrect_schema_message
221
- <<-MESSAGE
222
- Oh no!
223
-
224
- It seems you're using RailsEventStoreActiveRecord::EventRepository
225
- with incompaible database schema.
226
-
227
- We've redesigned database structure in order to fix several concurrency-related
228
- bugs. This repository is intended to work on that improved data layout.
229
-
230
- We've prepared migration that would take you from old schema to new one.
231
- This migration must be run offline -- take that into consideration:
232
-
233
- rails g rails_event_store_active_record:v1_v2_migration
234
- rake db:migrate
235
-
236
-
237
- If you cannot migrate right now -- you can for some time continue using
238
- old repository. In order to do so, change configuration accordingly:
239
-
240
- config.event_store = RailsEventStore::Client.new(
241
- repository: RailsEventStoreActiveRecord::LegacyEventRepository.new
242
- )
243
-
244
-
245
- MESSAGE
149
+ return events if events.is_a?(Enumerable)
150
+ [events]
246
151
  end
247
152
 
248
153
  def verify_correct_schema_present
249
- return unless ActiveRecord::Base.connected?
250
- legacy_columns = ["id", "stream", "event_type", "event_id", "metadata", "data", "created_at"]
251
- current_columns = ActiveRecord::Base.connection.columns("event_store_events").map(&:name)
252
- raise InvalidDatabaseSchema.new(incorrect_schema_message) if legacy_columns.eql?(current_columns)
154
+ CorrectSchemaVerifier.new.verify
253
155
  end
254
156
  end
157
+
255
158
  end
@@ -0,0 +1,104 @@
1
+ module RailsEventStoreActiveRecord
2
+ class EventRepositoryReader
3
+
4
+ def initialize(mapper)
5
+ @mapper = mapper
6
+ end
7
+
8
+ def has_event?(event_id)
9
+ Event.exists?(id: event_id)
10
+ end
11
+
12
+ def last_stream_event(stream_name)
13
+ record = EventInStream.where(stream: stream_name).order('position DESC, id DESC').first
14
+ record && build_event_instance(record)
15
+ end
16
+
17
+ def read_events_forward(stream_name, after_event_id, count)
18
+ stream = EventInStream.where(stream: stream_name)
19
+ unless after_event_id.equal?(:head)
20
+ after_event = stream.find_by!(event_id: after_event_id)
21
+ stream = stream.where('id > ?', after_event)
22
+ end
23
+
24
+ stream.preload(:event).order('position ASC, id ASC').limit(count)
25
+ .map(&method(:build_event_instance))
26
+ end
27
+
28
+ def read_events_backward(stream_name, before_event_id, count)
29
+ stream = EventInStream.where(stream: stream_name)
30
+ unless before_event_id.equal?(:head)
31
+ before_event = stream.find_by!(event_id: before_event_id)
32
+ stream = stream.where('id < ?', before_event)
33
+ end
34
+
35
+ stream.preload(:event).order('position DESC, id DESC').limit(count)
36
+ .map(&method(:build_event_instance))
37
+ end
38
+
39
+ def read_stream_events_forward(stream_name)
40
+ EventInStream.preload(:event).where(stream: stream_name).order('position ASC, id ASC')
41
+ .map(&method(:build_event_instance))
42
+ end
43
+
44
+ def read_stream_events_backward(stream_name)
45
+ EventInStream.preload(:event).where(stream: stream_name).order('position DESC, id DESC')
46
+ .map(&method(:build_event_instance))
47
+ end
48
+
49
+ def read_all_streams_forward(after_event_id, count)
50
+ stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
51
+ unless after_event_id.equal?(:head)
52
+ after_event = stream.find_by!(event_id: after_event_id)
53
+ stream = stream.where('id > ?', after_event)
54
+ end
55
+
56
+ stream.preload(:event).order('id ASC').limit(count)
57
+ .map(&method(:build_event_instance))
58
+ end
59
+
60
+ def read_all_streams_backward(before_event_id, count)
61
+ stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
62
+ unless before_event_id.equal?(:head)
63
+ before_event = stream.find_by!(event_id: before_event_id)
64
+ stream = stream.where('id < ?', before_event)
65
+ end
66
+
67
+ stream.preload(:event).order('id DESC').limit(count)
68
+ .map(&method(:build_event_instance))
69
+ end
70
+
71
+ def read_event(event_id)
72
+ event = Event.find(event_id)
73
+ serialized_record = RubyEventStore::SerializedRecord.new(
74
+ event_id: event.id,
75
+ metadata: event.metadata,
76
+ data: event.data,
77
+ event_type: event.event_type
78
+ )
79
+ @mapper.serialized_record_to_event(serialized_record)
80
+ rescue ActiveRecord::RecordNotFound
81
+ raise RubyEventStore::EventNotFound.new(event_id)
82
+ end
83
+
84
+ def get_all_streams
85
+ (["all"] + EventInStream.pluck(:stream))
86
+ .uniq
87
+ .map { |name| RubyEventStore::Stream.new(name) }
88
+ end
89
+
90
+ private
91
+
92
+ def build_event_instance(record)
93
+ serialized_record = RubyEventStore::SerializedRecord.new(
94
+ event_id: record.event.id,
95
+ metadata: record.event.metadata,
96
+ data: record.event.data,
97
+ event_type: record.event.event_type
98
+ )
99
+ @mapper.serialized_record_to_event(serialized_record)
100
+ end
101
+ end
102
+
103
+ private_constant(:EventRepositoryReader)
104
+ end
@@ -0,0 +1,24 @@
1
+ module RailsEventStoreActiveRecord
2
+ class IndexViolationDetector
3
+
4
+ MYSQL_PKEY_ERROR = "for key 'PRIMARY'"
5
+ POSTGRES_PKEY_ERROR = "event_store_events_pkey"
6
+ SQLITE3_PKEY_ERROR = "event_store_events.id"
7
+
8
+ MYSQL_INDEX_ERROR = "for key 'index_event_store_events_in_streams_on_stream_and_event_id'"
9
+ POSTGRES_INDEX_ERROR = "Key (stream, event_id)"
10
+ SQLITE3_INDEX_ERROR = "event_store_events_in_streams.stream, event_store_events_in_streams.event_id"
11
+
12
+ def detect(message)
13
+ message.include?(MYSQL_PKEY_ERROR) ||
14
+ message.include?(POSTGRES_PKEY_ERROR) ||
15
+ message.include?(SQLITE3_PKEY_ERROR) ||
16
+
17
+ message.include?(MYSQL_INDEX_ERROR) ||
18
+ message.include?(POSTGRES_INDEX_ERROR) ||
19
+ message.include?(SQLITE3_INDEX_ERROR)
20
+ end
21
+ end
22
+
23
+ private_constant(:IndexViolationDetector)
24
+ end
@@ -129,7 +129,8 @@ instead:
129
129
  private
130
130
 
131
131
  def normalize_to_array(events)
132
- [*events]
132
+ return events if events.is_a?(Enumerable)
133
+ [events]
133
134
  end
134
135
 
135
136
  def build_event_entity(record)
@@ -1,3 +1,3 @@
1
1
  module RailsEventStoreActiveRecord
2
- VERSION = "0.23.0"
2
+ VERSION = "0.24.0"
3
3
  end
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency 'fakefs', '~> 0.11.2'
31
31
  spec.add_development_dependency 'childprocess'
32
32
 
33
- spec.add_dependency 'ruby_event_store', '= 0.23.0'
33
+ spec.add_dependency 'ruby_event_store', '= 0.24.0'
34
34
  spec.add_dependency 'activesupport', '>= 3.0'
35
35
  spec.add_dependency 'activemodel', '>= 3.0'
36
36
  spec.add_dependency 'activerecord-import', '~> 0.21'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_event_store_active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arkency
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-11 00:00:00.000000000 Z
11
+ date: 2018-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - '='
158
158
  - !ruby/object:Gem::Version
159
- version: 0.23.0
159
+ version: 0.24.0
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - '='
165
165
  - !ruby/object:Gem::Version
166
- version: 0.23.0
166
+ version: 0.24.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: activesupport
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -221,12 +221,15 @@ files:
221
221
  - bin/console
222
222
  - bin/setup
223
223
  - lib/rails_event_store_active_record.rb
224
+ - lib/rails_event_store_active_record/correct_schema_verifier.rb
224
225
  - lib/rails_event_store_active_record/event.rb
225
226
  - lib/rails_event_store_active_record/event_repository.rb
227
+ - lib/rails_event_store_active_record/event_repository_reader.rb
226
228
  - lib/rails_event_store_active_record/generators/migration_generator.rb
227
229
  - lib/rails_event_store_active_record/generators/templates/migration_template.rb
228
230
  - lib/rails_event_store_active_record/generators/templates/v1_v2_migration_template.rb
229
231
  - lib/rails_event_store_active_record/generators/v1_v2_migration_generator.rb
232
+ - lib/rails_event_store_active_record/index_violation_detector.rb
230
233
  - lib/rails_event_store_active_record/legacy_event_repository.rb
231
234
  - lib/rails_event_store_active_record/version.rb
232
235
  - rails_event_store_active_record.gemspec