rails_event_store_active_record 0.31.1 → 0.32.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 -6
- data/lib/rails_event_store_active_record/event_repository.rb +23 -1
- data/lib/rails_event_store_active_record/event_repository_reader.rb +16 -18
- data/lib/rails_event_store_active_record/pg_linearized_event_repository.rb +18 -0
- data/lib/rails_event_store_active_record/version.rb +1 -1
- data/lib/rails_event_store_active_record.rb +1 -1
- data/rails_event_store_active_record.gemspec +2 -2
- metadata +7 -8
- data/lib/rails_event_store_active_record/generators/templates/v1_v2_migration_template.rb +0 -99
- data/lib/rails_event_store_active_record/generators/v1_v2_migration_generator.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 067a4f541fc38de8cf27a410bb6ffd32345e648c7875a59ddfba2d28fc835950
|
4
|
+
data.tar.gz: 332fb00fe13b2d437729f5de926f859f9978378e462e5c46062399fec6e3d08d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77466a3690ede3b10c7f45346f14efc17fcd08337734e72afeaf2df870efe8f69f3c48296d88d89e8aa50dbd5af6048410d119eee009c6b43df953d3c7bd9715
|
7
|
+
data.tar.gz: ef7e3dd291db6aadb4b5984dcf4d3768bb66e5dd475556e3011e3cf2f08fc47ccd5def474531a17e398aeb30bdff432070f242959bb7b273b304fc874cf793dc
|
data/Makefile
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
GEM_VERSION = $(shell cat ../RES_VERSION)
|
2
2
|
GEM_NAME = rails_event_store_active_record
|
3
3
|
REQUIRE = $(GEM_NAME)
|
4
|
-
IGNORE = RailsEventStoreActiveRecord::IndexViolationDetector\#detect
|
4
|
+
IGNORE = RailsEventStoreActiveRecord::IndexViolationDetector\#detect \
|
5
|
+
RailsEventStoreActiveRecord::PgLinearizedEventRepository* \
|
6
|
+
RailsEventStoreActiveRecord::EventRepository\#update_messages
|
5
7
|
SUBJECT ?= RailsEventStoreActiveRecord*
|
6
8
|
DATABASE_URL ?= sqlite3::memory:
|
7
9
|
|
8
10
|
install: ## Install gem dependencies
|
9
11
|
@echo "Installing gem dependencies"
|
10
12
|
@bundle install
|
11
|
-
@echo "Installing v1_v2_schema_migration gem dependencies"
|
12
|
-
@BUNDLE_GEMFILE=spec/v1_v2_schema_migration/Gemfile bundle install
|
13
13
|
@BUNDLE_GEMFILE=spec/without_rails/Gemfile bundle install
|
14
14
|
|
15
15
|
remove-lock:
|
16
16
|
@echo "Removing resolved dependency versions"
|
17
17
|
-rm Gemfile.lock
|
18
|
-
-rm spec/v1_v2_schema_migration/Gemfile.lock
|
19
18
|
-rm spec/without_rails/Gemfile.lock
|
20
19
|
|
21
20
|
reinstall: remove-lock install ## Removing resolved dependency versions
|
@@ -27,14 +26,14 @@ test: ## Run unit tests
|
|
27
26
|
|
28
27
|
mutate: test ## Run mutation tests
|
29
28
|
@echo "Running mutation tests"
|
30
|
-
@BUNDLE_GEMFILE=Gemfile DATABASE_URL=$(DATABASE_URL) bundle exec mutant --include lib \
|
29
|
+
@MUTATING=true BUNDLE_GEMFILE=Gemfile DATABASE_URL=$(DATABASE_URL) bundle exec mutant --include lib \
|
31
30
|
$(addprefix --require ,$(REQUIRE)) \
|
32
31
|
$(addprefix --ignore-subject ,$(IGNORE)) \
|
33
32
|
--use rspec "$(SUBJECT)"
|
34
33
|
|
35
34
|
mutate-fast: ## Run mutation tests with --fail-fast
|
36
35
|
@echo "Running mutation tests with --fail-fast"
|
37
|
-
@BUNDLE_GEMFILE=Gemfile DATABASE_URL=$(DATABASE_URL) bundle exec mutant --include lib \
|
36
|
+
@MUTATING=true BUNDLE_GEMFILE=Gemfile DATABASE_URL=$(DATABASE_URL) bundle exec mutant --include lib \
|
38
37
|
$(addprefix --require ,$(REQUIRE)) \
|
39
38
|
$(addprefix --ignore-subject ,$(IGNORE)) \
|
40
39
|
--fail-fast \
|
@@ -46,13 +46,31 @@ module RailsEventStoreActiveRecord
|
|
46
46
|
@repo_reader.read(specification)
|
47
47
|
end
|
48
48
|
|
49
|
+
def update_messages(messages)
|
50
|
+
hashes = messages.map(&:to_h)
|
51
|
+
hashes.each{|h| h[:id] = h.delete(:event_id) }
|
52
|
+
for_update = messages.map(&:event_id)
|
53
|
+
start_transaction do
|
54
|
+
existing = Event.where(id: for_update).pluck(:id)
|
55
|
+
(for_update - existing).each{|id| raise RubyEventStore::EventNotFound.new(id) }
|
56
|
+
Event.import(hashes, on_duplicate_key_update: [:data, :metadata, :event_type])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def streams_of(event_id)
|
61
|
+
EventInStream.where(event_id: event_id)
|
62
|
+
.where.not(stream: SERIALIZED_GLOBAL_STREAM_NAME)
|
63
|
+
.pluck(:stream)
|
64
|
+
.map{|name| RubyEventStore::Stream.new(name)}
|
65
|
+
end
|
66
|
+
|
49
67
|
private
|
50
68
|
|
51
69
|
def add_to_stream(collection, stream, expected_version, include_global, &to_event_id)
|
52
70
|
last_stream_version = ->(stream_) { EventInStream.where(stream: stream_.name).order("position DESC").first.try(:position) }
|
53
71
|
resolved_version = expected_version.resolve_for(stream, last_stream_version)
|
54
72
|
|
55
|
-
|
73
|
+
start_transaction do
|
56
74
|
in_stream = collection.flat_map.with_index do |element, index|
|
57
75
|
position = compute_position(resolved_version, index)
|
58
76
|
event_id = to_event_id.call(element)
|
@@ -115,6 +133,10 @@ module RailsEventStoreActiveRecord
|
|
115
133
|
# Overwritten in a sub-class
|
116
134
|
def fill_ids(_in_stream)
|
117
135
|
end
|
136
|
+
|
137
|
+
def start_transaction(&block)
|
138
|
+
ActiveRecord::Base.transaction(requires_new: true, &block)
|
139
|
+
end
|
118
140
|
end
|
119
141
|
|
120
142
|
end
|
@@ -24,17 +24,23 @@ module RailsEventStoreActiveRecord
|
|
24
24
|
|
25
25
|
|
26
26
|
def read(spec)
|
27
|
-
raise RubyEventStore::ReservedInternalName if spec.
|
27
|
+
raise RubyEventStore::ReservedInternalName if spec.stream.name.eql?(EventRepository::SERIALIZED_GLOBAL_STREAM_NAME)
|
28
28
|
|
29
29
|
stream = EventInStream.preload(:event).where(stream: normalize_stream_name(spec))
|
30
|
-
stream = stream.order(position: order(spec
|
31
|
-
stream = stream.limit(spec.
|
30
|
+
stream = stream.order(position: order(spec)) unless spec.stream.global?
|
31
|
+
stream = stream.limit(spec.limit) if spec.limit?
|
32
32
|
stream = stream.where(start_condition(spec)) unless spec.head?
|
33
|
-
stream = stream.order(id: order(spec
|
33
|
+
stream = stream.order(id: order(spec))
|
34
34
|
|
35
35
|
if spec.batched?
|
36
36
|
batch_reader = ->(offset, limit) { stream.offset(offset).limit(limit).map(&method(:build_event_instance)) }
|
37
|
-
RubyEventStore::BatchEnumerator.new(spec.batch_size,
|
37
|
+
RubyEventStore::BatchEnumerator.new(spec.batch_size, spec.limit, batch_reader).each
|
38
|
+
elsif spec.first?
|
39
|
+
record = stream.first
|
40
|
+
build_event_instance(record) if record
|
41
|
+
elsif spec.last?
|
42
|
+
record = stream.last
|
43
|
+
build_event_instance(record) if record
|
38
44
|
else
|
39
45
|
stream.map(&method(:build_event_instance)).each
|
40
46
|
end
|
@@ -42,27 +48,19 @@ module RailsEventStoreActiveRecord
|
|
42
48
|
|
43
49
|
private
|
44
50
|
|
45
|
-
def total_limit(specification)
|
46
|
-
specification.limit? ? specification.count : Float::INFINITY
|
47
|
-
end
|
48
|
-
|
49
51
|
def normalize_stream_name(specification)
|
50
|
-
specification.
|
52
|
+
specification.stream.global? ? EventRepository::SERIALIZED_GLOBAL_STREAM_NAME : specification.stream.name
|
51
53
|
end
|
52
54
|
|
53
55
|
def start_condition(specification)
|
54
56
|
event_record =
|
55
57
|
EventInStream.find_by!(event_id: specification.start, stream: normalize_stream_name(specification))
|
56
|
-
|
57
|
-
|
58
|
-
['id > ?', event_record]
|
59
|
-
else
|
60
|
-
['id < ?', event_record]
|
61
|
-
end
|
58
|
+
condition = specification.forward? ? 'id > ?' : 'id < ?'
|
59
|
+
[condition, event_record]
|
62
60
|
end
|
63
61
|
|
64
|
-
def order(
|
65
|
-
|
62
|
+
def order(spec)
|
63
|
+
spec.forward? ? 'ASC' : 'DESC'
|
66
64
|
end
|
67
65
|
|
68
66
|
def build_event_instance(record)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'activerecord-import'
|
2
|
+
|
3
|
+
module RailsEventStoreActiveRecord
|
4
|
+
class PgLinearizedEventRepository < EventRepository
|
5
|
+
|
6
|
+
def start_transaction(&proc)
|
7
|
+
ActiveRecord::Base.transaction(requires_new: true) do
|
8
|
+
ActiveRecord::Base.
|
9
|
+
connection.
|
10
|
+
execute("SELECT pg_advisory_xact_lock(1845240511599988039) as l").
|
11
|
+
each{}
|
12
|
+
|
13
|
+
proc.call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'rails_event_store_active_record/generators/migration_generator'
|
2
|
-
require 'rails_event_store_active_record/generators/v1_v2_migration_generator'
|
3
2
|
require 'rails_event_store_active_record/event'
|
4
3
|
require 'rails_event_store_active_record/event_repository'
|
5
4
|
require 'rails_event_store_active_record/event_repository_reader'
|
6
5
|
require 'rails_event_store_active_record/correct_schema_verifier'
|
7
6
|
require 'rails_event_store_active_record/index_violation_detector'
|
7
|
+
require 'rails_event_store_active_record/pg_linearized_event_repository'
|
8
8
|
require 'rails_event_store_active_record/version'
|
@@ -32,12 +32,12 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency 'sqlite3', '1.3.13'
|
33
33
|
spec.add_development_dependency 'pg', '0.21'
|
34
34
|
spec.add_development_dependency 'mysql2', '0.4.10'
|
35
|
-
spec.add_development_dependency 'mutant-rspec', '~> 0.8.
|
35
|
+
spec.add_development_dependency 'mutant-rspec', '~> 0.8.17'
|
36
36
|
spec.add_development_dependency 'fakefs', '~> 0.11.2'
|
37
37
|
spec.add_development_dependency 'childprocess'
|
38
38
|
spec.add_development_dependency 'google-protobuf', '~> 3.5.1.2'
|
39
39
|
|
40
|
-
spec.add_dependency 'ruby_event_store', '= 0.
|
40
|
+
spec.add_dependency 'ruby_event_store', '= 0.32.0'
|
41
41
|
spec.add_dependency 'activesupport', '>= 3.0'
|
42
42
|
spec.add_dependency 'activemodel', '>= 3.0'
|
43
43
|
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.
|
4
|
+
version: 0.32.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-
|
11
|
+
date: 2018-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.8.
|
117
|
+
version: 0.8.17
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.8.
|
124
|
+
version: 0.8.17
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: fakefs
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - '='
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 0.
|
173
|
+
version: 0.32.0
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - '='
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 0.
|
180
|
+
version: 0.32.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: activesupport
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -241,9 +241,8 @@ files:
|
|
241
241
|
- lib/rails_event_store_active_record/event_repository_reader.rb
|
242
242
|
- lib/rails_event_store_active_record/generators/migration_generator.rb
|
243
243
|
- lib/rails_event_store_active_record/generators/templates/migration_template.rb
|
244
|
-
- lib/rails_event_store_active_record/generators/templates/v1_v2_migration_template.rb
|
245
|
-
- lib/rails_event_store_active_record/generators/v1_v2_migration_generator.rb
|
246
244
|
- lib/rails_event_store_active_record/index_violation_detector.rb
|
245
|
+
- lib/rails_event_store_active_record/pg_linearized_event_repository.rb
|
247
246
|
- lib/rails_event_store_active_record/version.rb
|
248
247
|
- rails_event_store_active_record.gemspec
|
249
248
|
homepage: https://railseventstore.org
|
@@ -1,99 +0,0 @@
|
|
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
|
-
rails_42 = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("5.0.0")
|
17
|
-
enable_extension "pgcrypto" if postgres
|
18
|
-
create_table(:event_store_events_in_streams, force: false) do |t|
|
19
|
-
t.string :stream, null: false
|
20
|
-
t.integer :position, null: true
|
21
|
-
if postgres
|
22
|
-
t.references :event, null: false, type: :uuid
|
23
|
-
else
|
24
|
-
t.references :event, null: false, type: :string
|
25
|
-
end
|
26
|
-
t.datetime :created_at, null: false
|
27
|
-
end
|
28
|
-
streams = {}
|
29
|
-
RailsEventStoreActiveRecord::Event.reset_column_information
|
30
|
-
RailsEventStoreActiveRecord::Event.find_each do |ev|
|
31
|
-
position = nil
|
32
|
-
if preserve_positions?(ev.stream)
|
33
|
-
streams[ev.stream] ||= -1
|
34
|
-
position = streams[ev.stream] += 1
|
35
|
-
end
|
36
|
-
RailsEventStoreActiveRecord::EventInStream.create!(
|
37
|
-
stream: ev.stream,
|
38
|
-
position: position,
|
39
|
-
event_id: ev.event_id,
|
40
|
-
created_at: ev.created_at,
|
41
|
-
)
|
42
|
-
RailsEventStoreActiveRecord::EventInStream.create!(
|
43
|
-
stream: 'all',
|
44
|
-
position: nil,
|
45
|
-
event_id: ev.event_id,
|
46
|
-
created_at: ev.created_at,
|
47
|
-
) unless ev.stream == 'all'
|
48
|
-
end
|
49
|
-
|
50
|
-
add_index :event_store_events_in_streams, [:stream, :position], unique: true
|
51
|
-
add_index :event_store_events_in_streams, [:stream, :event_id], unique: true
|
52
|
-
add_index :event_store_events_in_streams, [:created_at]
|
53
|
-
|
54
|
-
remove_index :event_store_events, :event_type
|
55
|
-
remove_column :event_store_events, :stream
|
56
|
-
remove_column :event_store_events, :id
|
57
|
-
rename_column :event_store_events, :event_id, :id
|
58
|
-
change_column :event_store_events, :id, "uuid using id::uuid", default: -> { "gen_random_uuid()" } if postgres
|
59
|
-
change_column :event_store_events, :id, "string", limit: 36 if mysql || sqlite
|
60
|
-
|
61
|
-
case ActiveRecord::Base.connection.adapter_name
|
62
|
-
when "SQLite"
|
63
|
-
remove_index :event_store_events, name: :index_event_store_events_on_id
|
64
|
-
rename_table :event_store_events, :old_event_store_events
|
65
|
-
create_table(:event_store_events, id: false, force: false) do |t|
|
66
|
-
t.string :id, limit: 36, primary_key: true, null: false
|
67
|
-
t.string :event_type, null: false
|
68
|
-
t.text :metadata
|
69
|
-
t.text :data, null: false
|
70
|
-
t.datetime :created_at, null: false
|
71
|
-
end
|
72
|
-
add_index :event_store_events, :id, unique: true if rails_42
|
73
|
-
add_index :event_store_events, :created_at
|
74
|
-
execute <<-SQL
|
75
|
-
INSERT INTO event_store_events(id, event_type, metadata, data, created_at)
|
76
|
-
SELECT id, event_type, metadata, data, created_at FROM old_event_store_events;
|
77
|
-
SQL
|
78
|
-
drop_table :old_event_store_events
|
79
|
-
else
|
80
|
-
execute "ALTER TABLE event_store_events ADD PRIMARY KEY (id);"
|
81
|
-
remove_index :event_store_events, name: :index_event_store_events_on_id
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def preserve_positions?(stream_name)
|
86
|
-
# https://railseventstore.org/docs/expected_version/
|
87
|
-
#
|
88
|
-
# return true if you use given stream for event sourcing
|
89
|
-
# (especially with AggregateRoot gem)
|
90
|
-
# return true if you use an Integer or :none as
|
91
|
-
# expected_version when publishing in this stream
|
92
|
-
#
|
93
|
-
# return false if use use :any (the default) as expected_version
|
94
|
-
# when publishing to this stream
|
95
|
-
|
96
|
-
raise NotImplementedError
|
97
|
-
# false
|
98
|
-
end
|
99
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rails/generators'
|
3
|
-
rescue LoadError
|
4
|
-
end
|
5
|
-
|
6
|
-
module RailsEventStoreActiveRecord
|
7
|
-
class V1V2MigrationGenerator < Rails::Generators::Base
|
8
|
-
source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
|
9
|
-
|
10
|
-
def create_migration
|
11
|
-
template "v1_v2_migration_template.rb", "db/migrate/#{timestamp}_migrate_res_schema_v1_to_v2.rb"
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def rails_version
|
17
|
-
Rails::VERSION::STRING
|
18
|
-
end
|
19
|
-
|
20
|
-
def migration_version
|
21
|
-
return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
|
22
|
-
"[4.2]"
|
23
|
-
end
|
24
|
-
|
25
|
-
def timestamp
|
26
|
-
Time.now.strftime("%Y%m%d%H%M%S")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end if defined?(Rails::Generators::Base)
|