rails_event_store_active_record 0.18.2 → 0.19.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 +4 -4
- data/Makefile +5 -3
- data/lib/rails_event_store_active_record/event.rb +6 -0
- data/lib/rails_event_store_active_record/event_repository.rb +135 -41
- data/lib/rails_event_store_active_record/generators/templates/migration_template.rb +29 -8
- data/lib/rails_event_store_active_record/generators/templates/v1_v2_migration_template.rb +97 -0
- data/lib/rails_event_store_active_record/generators/v1_v2_migration_generator.rb +26 -0
- data/lib/rails_event_store_active_record/legacy_event_repository.rb +143 -0
- data/lib/rails_event_store_active_record/version.rb +1 -1
- data/lib/rails_event_store_active_record.rb +2 -0
- data/rails_event_store_active_record.gemspec +7 -3
- metadata +65 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c45bf6b63a5317bf916c5bc831573fab866c762
|
4
|
+
data.tar.gz: a0a1a1ad2c1c662911b3da70829bae860741bc51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f936d894bf5b5d64395527873cbdc300abfe18b8ee9536c4989e53a48bfad17703bf5e4f7b81633279490917d73074863b7b0ed63330c32d7cff565219624cd
|
7
|
+
data.tar.gz: 6f5c2f8e1b899bb296439728a84b745bb4c772e4b1f39924e27c3d327b95d5a98c66b75eed88afbf932d02b5c90fd5c52a37165f941a1709aa7b38cb02762602
|
data/Makefile
CHANGED
@@ -3,6 +3,8 @@ GEM_VERSION = `cat ../RES_VERSION`
|
|
3
3
|
install: ## Install gem dependencies
|
4
4
|
@echo "Installing gem dependencies"
|
5
5
|
@bundle install
|
6
|
+
@echo "Installing v1_v2_schema_migration gem dependencies"
|
7
|
+
@BUNDLE_GEMFILE=spec/v1_v2_schema_migration/Gemfile bundle install
|
6
8
|
|
7
9
|
test: ## Run tests
|
8
10
|
@echo "Running basic tests - beware: this won't guarantee build pass"
|
@@ -11,9 +13,9 @@ test: ## Run tests
|
|
11
13
|
mutate: test ## Run mutation tests
|
12
14
|
@echo "Running mutation tests - only 100% free mutation will be accepted"
|
13
15
|
@bundle exec mutant --include lib --require ruby_event_store --use rspec "RailsEventStoreActiveRecord*" \
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
--ignore-subject "RailsEventStoreActiveRecord::EventRepository#normalize_to_array" \
|
17
|
+
--ignore-subject "RailsEventStoreActiveRecord::LegacyEventRepository#normalize_to_array" \
|
18
|
+
--ignore-subject "RailsEventStoreActiveRecord::EventRepository#detect_pkey_index_violated"
|
17
19
|
|
18
20
|
build:
|
19
21
|
@gem build -V rails_event_store_active_record.gemspec
|
@@ -1,92 +1,186 @@
|
|
1
|
+
require 'activerecord-import'
|
2
|
+
|
1
3
|
module RailsEventStoreActiveRecord
|
2
4
|
class EventRepository
|
3
|
-
|
4
|
-
|
5
|
+
InvalidDatabaseSchema = Class.new(StandardError)
|
6
|
+
|
7
|
+
POSITION_SHIFT = 1
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
verify_correct_schema_present
|
5
11
|
end
|
6
|
-
attr_reader :adapter
|
7
12
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
def append_to_stream(events, stream_name, expected_version)
|
14
|
+
raise RubyEventStore::InvalidExpectedVersion if stream_name.eql?(RubyEventStore::GLOBAL_STREAM) && !expected_version.equal?(:any)
|
15
|
+
|
16
|
+
events = normalize_to_array(events)
|
17
|
+
expected_version =
|
18
|
+
case expected_version
|
19
|
+
when Integer, :any
|
20
|
+
expected_version
|
21
|
+
when :none
|
22
|
+
-1
|
23
|
+
when :auto
|
24
|
+
eis = EventInStream.where(stream: stream_name).order("position DESC").first
|
25
|
+
(eis && eis.position) || -1
|
26
|
+
else
|
27
|
+
raise RubyEventStore::InvalidExpectedVersion
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::Base.transaction(requires_new: true) do
|
31
|
+
in_stream = events.flat_map.with_index do |event, index|
|
32
|
+
position = unless expected_version.equal?(:any)
|
33
|
+
expected_version + index + POSITION_SHIFT
|
34
|
+
end
|
35
|
+
Event.create!(
|
36
|
+
id: event.event_id,
|
37
|
+
data: event.data,
|
38
|
+
metadata: event.metadata,
|
39
|
+
event_type: event.class,
|
40
|
+
)
|
41
|
+
events = [{
|
42
|
+
stream: RubyEventStore::GLOBAL_STREAM,
|
43
|
+
event_id: event.event_id
|
44
|
+
}]
|
45
|
+
events.unshift({
|
46
|
+
stream: stream_name,
|
47
|
+
position: position,
|
48
|
+
event_id: event.event_id
|
49
|
+
}) unless stream_name.eql?(RubyEventStore::GLOBAL_STREAM)
|
50
|
+
events
|
51
|
+
end
|
52
|
+
EventInStream.import(in_stream)
|
53
|
+
end
|
54
|
+
self
|
55
|
+
rescue ActiveRecord::RecordNotUnique => e
|
56
|
+
if detect_pkey_index_violated(e)
|
57
|
+
raise RubyEventStore::EventDuplicatedInStream
|
58
|
+
end
|
59
|
+
raise RubyEventStore::WrongExpectedEventVersion
|
12
60
|
end
|
13
61
|
|
14
62
|
def delete_stream(stream_name)
|
15
|
-
|
16
|
-
adapter.destroy_all condition
|
63
|
+
EventInStream.where(stream: stream_name).delete_all
|
17
64
|
end
|
18
65
|
|
19
66
|
def has_event?(event_id)
|
20
|
-
|
67
|
+
Event.exists?(id: event_id)
|
21
68
|
end
|
22
69
|
|
23
70
|
def last_stream_event(stream_name)
|
24
|
-
build_event_entity(
|
71
|
+
build_event_entity(
|
72
|
+
EventInStream.where(stream: stream_name).order('position DESC, id DESC').first
|
73
|
+
)
|
25
74
|
end
|
26
75
|
|
27
|
-
def read_events_forward(stream_name,
|
28
|
-
stream =
|
29
|
-
unless
|
30
|
-
|
31
|
-
stream = stream.where('id > ?',
|
76
|
+
def read_events_forward(stream_name, after_event_id, count)
|
77
|
+
stream = EventInStream.where(stream: stream_name)
|
78
|
+
unless after_event_id.equal?(:head)
|
79
|
+
after_event = stream.find_by!(event_id: after_event_id)
|
80
|
+
stream = stream.where('id > ?', after_event)
|
32
81
|
end
|
33
82
|
|
34
|
-
stream.order('id ASC').limit(count)
|
83
|
+
stream.preload(:event).order('position ASC, id ASC').limit(count)
|
35
84
|
.map(&method(:build_event_entity))
|
36
85
|
end
|
37
86
|
|
38
|
-
def read_events_backward(stream_name,
|
39
|
-
stream =
|
40
|
-
unless
|
41
|
-
|
42
|
-
stream = stream.where('id < ?',
|
87
|
+
def read_events_backward(stream_name, before_event_id, count)
|
88
|
+
stream = EventInStream.where(stream: stream_name)
|
89
|
+
unless before_event_id.equal?(:head)
|
90
|
+
before_event = stream.find_by!(event_id: before_event_id)
|
91
|
+
stream = stream.where('id < ?', before_event)
|
43
92
|
end
|
44
93
|
|
45
|
-
stream.order('id DESC').limit(count)
|
94
|
+
stream.preload(:event).order('position DESC, id DESC').limit(count)
|
46
95
|
.map(&method(:build_event_entity))
|
47
96
|
end
|
48
97
|
|
49
98
|
def read_stream_events_forward(stream_name)
|
50
|
-
|
99
|
+
EventInStream.preload(:event).where(stream: stream_name).order('position ASC, id ASC')
|
51
100
|
.map(&method(:build_event_entity))
|
52
101
|
end
|
53
102
|
|
54
103
|
def read_stream_events_backward(stream_name)
|
55
|
-
|
104
|
+
EventInStream.preload(:event).where(stream: stream_name).order('position DESC, id DESC')
|
56
105
|
.map(&method(:build_event_entity))
|
57
106
|
end
|
58
107
|
|
59
|
-
def read_all_streams_forward(
|
60
|
-
stream =
|
61
|
-
unless
|
62
|
-
|
63
|
-
stream = stream.where('id > ?',
|
108
|
+
def read_all_streams_forward(after_event_id, count)
|
109
|
+
stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
|
110
|
+
unless after_event_id.equal?(:head)
|
111
|
+
after_event = stream.find_by!(event_id: after_event_id)
|
112
|
+
stream = stream.where('id > ?', after_event)
|
64
113
|
end
|
65
114
|
|
66
|
-
stream.order('id ASC').limit(count)
|
115
|
+
stream.preload(:event).order('id ASC').limit(count)
|
67
116
|
.map(&method(:build_event_entity))
|
68
117
|
end
|
69
118
|
|
70
|
-
def read_all_streams_backward(
|
71
|
-
stream =
|
72
|
-
unless
|
73
|
-
|
74
|
-
stream = stream.where('id < ?',
|
119
|
+
def read_all_streams_backward(before_event_id, count)
|
120
|
+
stream = EventInStream.where(stream: RubyEventStore::GLOBAL_STREAM)
|
121
|
+
unless before_event_id.equal?(:head)
|
122
|
+
before_event = stream.find_by!(event_id: before_event_id)
|
123
|
+
stream = stream.where('id < ?', before_event)
|
75
124
|
end
|
76
125
|
|
77
|
-
stream.order('id DESC').limit(count)
|
126
|
+
stream.preload(:event).order('id DESC').limit(count)
|
78
127
|
.map(&method(:build_event_entity))
|
79
128
|
end
|
80
129
|
|
81
130
|
private
|
82
131
|
|
132
|
+
def detect_pkey_index_violated(e)
|
133
|
+
e.message.include?("for key 'PRIMARY'") || # MySQL
|
134
|
+
e.message.include?("event_store_events_pkey") || # Postgresql
|
135
|
+
e.message.include?("event_store_events.id") # Sqlite3
|
136
|
+
end
|
137
|
+
|
83
138
|
def build_event_entity(record)
|
84
139
|
return nil unless record
|
85
|
-
record.event_type.constantize.new(
|
86
|
-
event_id: record.
|
87
|
-
metadata: record.metadata,
|
88
|
-
data: record.data
|
140
|
+
record.event.event_type.constantize.new(
|
141
|
+
event_id: record.event.id,
|
142
|
+
metadata: record.event.metadata,
|
143
|
+
data: record.event.data
|
89
144
|
)
|
90
145
|
end
|
146
|
+
|
147
|
+
def normalize_to_array(events)
|
148
|
+
[*events]
|
149
|
+
end
|
150
|
+
|
151
|
+
def incorrect_schema_message
|
152
|
+
<<-MESSAGE
|
153
|
+
Oh no!
|
154
|
+
|
155
|
+
It seems you're using RailsEventStoreActiveRecord::EventRepository
|
156
|
+
with incompaible database schema.
|
157
|
+
|
158
|
+
We've redesigned database structure in order to fix several concurrency-related
|
159
|
+
bugs. This repository is intended to work on that improved data layout.
|
160
|
+
|
161
|
+
We've prepared migration that would take you from old schema to new one.
|
162
|
+
This migration must be run offline -- take that into consideration:
|
163
|
+
|
164
|
+
rails g rails_event_store_active_record:v1_v2_migration
|
165
|
+
rake db:migrate
|
166
|
+
|
167
|
+
|
168
|
+
If you cannot migrate right now -- you can for some time continue using
|
169
|
+
old repository. In order to do so, change configuration accordingly:
|
170
|
+
|
171
|
+
config.event_store = RailsEventStore::Client.new(
|
172
|
+
repository: RailsEventStoreActiveRecord::LegacyEventRepository.new
|
173
|
+
)
|
174
|
+
|
175
|
+
|
176
|
+
MESSAGE
|
177
|
+
end
|
178
|
+
|
179
|
+
def verify_correct_schema_present
|
180
|
+
return unless ActiveRecord::Base.connected?
|
181
|
+
legacy_columns = ["id", "stream", "event_type", "event_id", "metadata", "data", "created_at"]
|
182
|
+
current_columns = ActiveRecord::Base.connection.columns("event_store_events").map(&:name)
|
183
|
+
raise InvalidDatabaseSchema.new(incorrect_schema_message) if legacy_columns.eql?(current_columns)
|
184
|
+
end
|
91
185
|
end
|
92
186
|
end
|
@@ -1,16 +1,37 @@
|
|
1
1
|
class CreateEventStoreEvents < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
|
3
|
+
postgres = ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
4
|
+
enable_extension "pgcrypto" if postgres
|
5
|
+
create_table(:event_store_events_in_streams, force: false) do |t|
|
4
6
|
t.string :stream, null: false
|
5
|
-
t.
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
t.integer :position, null: true
|
8
|
+
if postgres
|
9
|
+
t.references :event, null: false, type: :uuid
|
10
|
+
else
|
11
|
+
t.references :event, null: false, type: :string
|
12
|
+
end
|
9
13
|
t.datetime :created_at, null: false
|
10
14
|
end
|
11
|
-
add_index :
|
15
|
+
add_index :event_store_events_in_streams, [:stream, :position], unique: true
|
16
|
+
add_index :event_store_events_in_streams, [:created_at]
|
17
|
+
add_index :event_store_events_in_streams, [:stream, :event_id], unique: true
|
18
|
+
|
19
|
+
if postgres
|
20
|
+
create_table(:event_store_events, id: :uuid, default: 'gen_random_uuid()', force: false) do |t|
|
21
|
+
t.string :event_type, null: false
|
22
|
+
t.text :metadata
|
23
|
+
t.text :data, null: false
|
24
|
+
t.datetime :created_at, null: false
|
25
|
+
end
|
26
|
+
else
|
27
|
+
create_table(:event_store_events, id: false, force: false) do |t|
|
28
|
+
t.string :id, limit: 36, primary_key: true, null: false
|
29
|
+
t.string :event_type, null: false
|
30
|
+
t.text :metadata
|
31
|
+
t.text :data, null: false
|
32
|
+
t.datetime :created_at, null: false
|
33
|
+
end
|
34
|
+
end
|
12
35
|
add_index :event_store_events, :created_at
|
13
|
-
add_index :event_store_events, :event_type
|
14
|
-
add_index :event_store_events, :event_id, unique: true
|
15
36
|
end
|
16
37
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# This migration is not intended for live data migration
|
2
|
+
# It assumes no data is added at when it is running.
|
3
|
+
# So stop your application servers from accepting new requests
|
4
|
+
# and processing background jobs before running
|
5
|
+
|
6
|
+
# Make sure you have a backup before running on production
|
7
|
+
|
8
|
+
# 10_000_000 distinct stream names
|
9
|
+
# can cause around 2GB of RAM usage
|
10
|
+
# make sure you can run this migration on your production system
|
11
|
+
class MigrateResSchemaV1ToV2 < ActiveRecord::Migration<%= migration_version %>
|
12
|
+
def up
|
13
|
+
postgres = ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
14
|
+
mysql = ActiveRecord::Base.connection.adapter_name == "Mysql2"
|
15
|
+
sqlite = ActiveRecord::Base.connection.adapter_name == "SQLite"
|
16
|
+
enable_extension "pgcrypto" if postgres
|
17
|
+
create_table(:event_store_events_in_streams, force: false) do |t|
|
18
|
+
t.string :stream, null: false
|
19
|
+
t.integer :position, null: true
|
20
|
+
if postgres
|
21
|
+
t.references :event, null: false, type: :uuid
|
22
|
+
else
|
23
|
+
t.references :event, null: false, type: :string
|
24
|
+
end
|
25
|
+
t.datetime :created_at, null: false
|
26
|
+
end
|
27
|
+
streams = {}
|
28
|
+
RailsEventStoreActiveRecord::Event.reset_column_information
|
29
|
+
RailsEventStoreActiveRecord::Event.find_each do |ev|
|
30
|
+
position = nil
|
31
|
+
if preserve_positions?(ev.stream)
|
32
|
+
streams[ev.stream] ||= -1
|
33
|
+
position = streams[ev.stream] += 1
|
34
|
+
end
|
35
|
+
RailsEventStoreActiveRecord::EventInStream.create!(
|
36
|
+
stream: ev.stream,
|
37
|
+
position: position,
|
38
|
+
event_id: ev.event_id,
|
39
|
+
created_at: ev.created_at,
|
40
|
+
)
|
41
|
+
RailsEventStoreActiveRecord::EventInStream.create!(
|
42
|
+
stream: 'all',
|
43
|
+
position: nil,
|
44
|
+
event_id: ev.event_id,
|
45
|
+
created_at: ev.created_at,
|
46
|
+
) unless ev.stream == 'all'
|
47
|
+
end
|
48
|
+
|
49
|
+
add_index :event_store_events_in_streams, [:stream, :position], unique: true
|
50
|
+
add_index :event_store_events_in_streams, [:stream, :event_id], unique: true
|
51
|
+
add_index :event_store_events_in_streams, [:created_at]
|
52
|
+
|
53
|
+
remove_index :event_store_events, :event_type
|
54
|
+
remove_column :event_store_events, :stream
|
55
|
+
remove_column :event_store_events, :id
|
56
|
+
rename_column :event_store_events, :event_id, :id
|
57
|
+
change_column :event_store_events, :id, "uuid using id::uuid", default: -> { "gen_random_uuid()" } if postgres
|
58
|
+
change_column :event_store_events, :id, "string", limit: 36 if mysql || sqlite
|
59
|
+
|
60
|
+
case ActiveRecord::Base.connection.adapter_name
|
61
|
+
when "SQLite"
|
62
|
+
remove_index :event_store_events, name: :index_event_store_events_on_id
|
63
|
+
rename_table :event_store_events, :old_event_store_events
|
64
|
+
create_table(:event_store_events, id: false, force: false) do |t|
|
65
|
+
t.string :id, limit: 36, primary_key: true, null: false
|
66
|
+
t.string :event_type, null: false
|
67
|
+
t.text :metadata
|
68
|
+
t.text :data, null: false
|
69
|
+
t.datetime :created_at, null: false
|
70
|
+
end
|
71
|
+
add_index :event_store_events, :created_at
|
72
|
+
execute <<-SQL
|
73
|
+
INSERT INTO event_store_events(id, event_type, metadata, data, created_at)
|
74
|
+
SELECT id, event_type, metadata, data, created_at FROM old_event_store_events;
|
75
|
+
SQL
|
76
|
+
drop_table :old_event_store_events
|
77
|
+
else
|
78
|
+
execute "ALTER TABLE event_store_events ADD PRIMARY KEY (id);"
|
79
|
+
remove_index :event_store_events, name: :index_event_store_events_on_id
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def preserve_positions?(stream_name)
|
84
|
+
# http://railseventstore.org/docs/expected_version/
|
85
|
+
#
|
86
|
+
# return true if you use given stream for event sourcing
|
87
|
+
# (especially with AggregateRoot gem)
|
88
|
+
# return true if you use an Integer or :none as
|
89
|
+
# expected_version when publishing in this stream
|
90
|
+
#
|
91
|
+
# return false if use use :any (the default) as expected_version
|
92
|
+
# when publishing to this stream
|
93
|
+
|
94
|
+
raise NotImplementedError
|
95
|
+
# false
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module RailsEventStoreActiveRecord
|
4
|
+
class V1V2MigrationGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
|
6
|
+
|
7
|
+
def create_migration
|
8
|
+
template "v1_v2_migration_template.rb", "db/migrate/#{timestamp}_migrate_res_schema_v1_to_v2.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def rails_version
|
14
|
+
Rails::VERSION::STRING
|
15
|
+
end
|
16
|
+
|
17
|
+
def migration_version
|
18
|
+
return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
|
19
|
+
"[4.2]"
|
20
|
+
end
|
21
|
+
|
22
|
+
def timestamp
|
23
|
+
Time.now.strftime("%Y%m%d%H%M%S")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module RailsEventStoreActiveRecord
|
4
|
+
class LegacyEventRepository
|
5
|
+
class LegacyEvent < ::ActiveRecord::Base
|
6
|
+
self.primary_key = :id
|
7
|
+
self.table_name = 'event_store_events'
|
8
|
+
serialize :metadata
|
9
|
+
serialize :data
|
10
|
+
end
|
11
|
+
|
12
|
+
private_constant :LegacyEvent
|
13
|
+
|
14
|
+
def append_to_stream(events, stream_name, expected_version)
|
15
|
+
validate_expected_version_is_not_auto(expected_version)
|
16
|
+
validate_expected_version_is_any_for_global_stream(expected_version, stream_name)
|
17
|
+
|
18
|
+
case expected_version
|
19
|
+
when :none
|
20
|
+
validate_stream_is_empty(stream_name)
|
21
|
+
when :any
|
22
|
+
when Integer
|
23
|
+
validate_expected_version_number(expected_version, stream_name)
|
24
|
+
else
|
25
|
+
raise RubyEventStore::InvalidExpectedVersion
|
26
|
+
end
|
27
|
+
|
28
|
+
normalize_to_array(events).each do |event|
|
29
|
+
data = event.to_h.merge!(stream: stream_name, event_type: event.class)
|
30
|
+
LegacyEvent.create!(data)
|
31
|
+
end
|
32
|
+
self
|
33
|
+
rescue ActiveRecord::RecordNotUnique
|
34
|
+
raise RubyEventStore::EventDuplicatedInStream
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_stream(stream_name)
|
38
|
+
LegacyEvent.where({stream: stream_name}).update_all(stream: RubyEventStore::GLOBAL_STREAM)
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_event?(event_id)
|
42
|
+
LegacyEvent.exists?(event_id: event_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_stream_event(stream_name)
|
46
|
+
build_event_entity(LegacyEvent.where(stream: stream_name).last)
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_events_forward(stream_name, start_event_id, count)
|
50
|
+
stream = LegacyEvent.where(stream: stream_name)
|
51
|
+
unless start_event_id.equal?(:head)
|
52
|
+
starting_event = LegacyEvent.find_by(event_id: start_event_id)
|
53
|
+
stream = stream.where('id > ?', starting_event)
|
54
|
+
end
|
55
|
+
|
56
|
+
stream.order('id ASC').limit(count)
|
57
|
+
.map(&method(:build_event_entity))
|
58
|
+
end
|
59
|
+
|
60
|
+
def read_events_backward(stream_name, start_event_id, count)
|
61
|
+
stream = LegacyEvent.where(stream: stream_name)
|
62
|
+
unless start_event_id.equal?(:head)
|
63
|
+
starting_event = LegacyEvent.find_by(event_id: start_event_id)
|
64
|
+
stream = stream.where('id < ?', starting_event)
|
65
|
+
end
|
66
|
+
|
67
|
+
stream.order('id DESC').limit(count)
|
68
|
+
.map(&method(:build_event_entity))
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_stream_events_forward(stream_name)
|
72
|
+
LegacyEvent.where(stream: stream_name).order('id ASC')
|
73
|
+
.map(&method(:build_event_entity))
|
74
|
+
end
|
75
|
+
|
76
|
+
def read_stream_events_backward(stream_name)
|
77
|
+
LegacyEvent.where(stream: stream_name).order('id DESC')
|
78
|
+
.map(&method(:build_event_entity))
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_all_streams_forward(start_event_id, count)
|
82
|
+
stream = LegacyEvent
|
83
|
+
unless start_event_id.equal?(:head)
|
84
|
+
starting_event = LegacyEvent.find_by(event_id: start_event_id)
|
85
|
+
stream = stream.where('id > ?', starting_event)
|
86
|
+
end
|
87
|
+
|
88
|
+
stream.order('id ASC').limit(count)
|
89
|
+
.map(&method(:build_event_entity))
|
90
|
+
end
|
91
|
+
|
92
|
+
def read_all_streams_backward(start_event_id, count)
|
93
|
+
stream = LegacyEvent
|
94
|
+
unless start_event_id.equal?(:head)
|
95
|
+
starting_event = LegacyEvent.find_by(event_id: start_event_id)
|
96
|
+
stream = stream.where('id < ?', starting_event)
|
97
|
+
end
|
98
|
+
|
99
|
+
stream.order('id DESC').limit(count)
|
100
|
+
.map(&method(:build_event_entity))
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def normalize_to_array(events)
|
106
|
+
[*events]
|
107
|
+
end
|
108
|
+
|
109
|
+
def build_event_entity(record)
|
110
|
+
return nil unless record
|
111
|
+
record.event_type.constantize.new(
|
112
|
+
event_id: record.event_id,
|
113
|
+
metadata: record.metadata,
|
114
|
+
data: record.data
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
def last_stream_version(stream_name)
|
119
|
+
LegacyEvent.where(stream: stream_name).count - 1
|
120
|
+
end
|
121
|
+
|
122
|
+
def stream_non_empty?(stream_name)
|
123
|
+
LegacyEvent.where(stream: stream_name).exists?
|
124
|
+
end
|
125
|
+
|
126
|
+
def validate_expected_version_is_any_for_global_stream(expected_version, stream_name)
|
127
|
+
raise RubyEventStore::InvalidExpectedVersion if stream_name.eql?(RubyEventStore::GLOBAL_STREAM) && !expected_version.equal?(:any)
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_stream_is_empty(stream_name)
|
131
|
+
raise RubyEventStore::WrongExpectedEventVersion if stream_non_empty?(stream_name)
|
132
|
+
end
|
133
|
+
|
134
|
+
def validate_expected_version_number(expected_version, stream_name)
|
135
|
+
raise RubyEventStore::WrongExpectedEventVersion unless last_stream_version(stream_name).equal?(expected_version)
|
136
|
+
end
|
137
|
+
|
138
|
+
def validate_expected_version_is_not_auto(expected_version)
|
139
|
+
raise RubyEventStore::InvalidExpectedVersion, ":auto mode is not supported by LegacyEventRepository" if expected_version.equal?(:auto)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'rails_event_store_active_record/generators/migration_generator'
|
2
|
+
require 'rails_event_store_active_record/generators/v1_v2_migration_generator'
|
2
3
|
require 'rails_event_store_active_record/event'
|
3
4
|
require 'rails_event_store_active_record/event_repository'
|
5
|
+
require 'rails_event_store_active_record/legacy_event_repository'
|
4
6
|
require 'rails_event_store_active_record/version'
|
@@ -22,12 +22,16 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
23
23
|
spec.add_development_dependency 'rake', '~> 10.0'
|
24
24
|
spec.add_development_dependency 'rspec', '~> 3.6'
|
25
|
-
spec.add_development_dependency 'rails', '~>
|
25
|
+
spec.add_development_dependency 'rails', '~> 5.1'
|
26
26
|
spec.add_development_dependency 'sqlite3'
|
27
|
+
spec.add_development_dependency 'postgresql'
|
28
|
+
spec.add_development_dependency 'mysql2'
|
27
29
|
spec.add_development_dependency 'mutant-rspec', '~> 0.8.14'
|
28
|
-
spec.add_development_dependency
|
30
|
+
spec.add_development_dependency 'fakefs', '~> 0.11.2'
|
31
|
+
spec.add_development_dependency 'childprocess'
|
29
32
|
|
30
|
-
spec.add_dependency 'ruby_event_store', '= 0.
|
33
|
+
spec.add_dependency 'ruby_event_store', '= 0.19.0'
|
31
34
|
spec.add_dependency 'activesupport', '>= 3.0'
|
32
35
|
spec.add_dependency 'activemodel', '>= 3.0'
|
36
|
+
spec.add_dependency 'activerecord-import'
|
33
37
|
end
|
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.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkency
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '5.1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '5.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sqlite3
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: postgresql
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mysql2
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: mutant-rspec
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,20 +136,34 @@ dependencies:
|
|
108
136
|
- - "~>"
|
109
137
|
- !ruby/object:Gem::Version
|
110
138
|
version: 0.11.2
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: childprocess
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
154
|
name: ruby_event_store
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
114
156
|
requirements:
|
115
157
|
- - '='
|
116
158
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
159
|
+
version: 0.19.0
|
118
160
|
type: :runtime
|
119
161
|
prerelease: false
|
120
162
|
version_requirements: !ruby/object:Gem::Requirement
|
121
163
|
requirements:
|
122
164
|
- - '='
|
123
165
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
166
|
+
version: 0.19.0
|
125
167
|
- !ruby/object:Gem::Dependency
|
126
168
|
name: activesupport
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +192,20 @@ dependencies:
|
|
150
192
|
- - ">="
|
151
193
|
- !ruby/object:Gem::Version
|
152
194
|
version: '3.0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: activerecord-import
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
153
209
|
description: Implementation of events repository based on Rails Active Record for
|
154
210
|
Rails Event Store'
|
155
211
|
email:
|
@@ -169,6 +225,9 @@ files:
|
|
169
225
|
- lib/rails_event_store_active_record/event_repository.rb
|
170
226
|
- lib/rails_event_store_active_record/generators/migration_generator.rb
|
171
227
|
- lib/rails_event_store_active_record/generators/templates/migration_template.rb
|
228
|
+
- lib/rails_event_store_active_record/generators/templates/v1_v2_migration_template.rb
|
229
|
+
- lib/rails_event_store_active_record/generators/v1_v2_migration_generator.rb
|
230
|
+
- lib/rails_event_store_active_record/legacy_event_repository.rb
|
172
231
|
- lib/rails_event_store_active_record/version.rb
|
173
232
|
- rails_event_store_active_record.gemspec
|
174
233
|
homepage: https://github.com/arkency/rails_event_store_active_record
|