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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef19b8405b7afab8d877b0b3888ec88c70eeb840992ee14945ec2c7ca57d5744
4
- data.tar.gz: 325dc6f18f6a18b734aef78585d1650bef65975f0dfda7cadc8ff342f5ce4680
3
+ metadata.gz: 067a4f541fc38de8cf27a410bb6ffd32345e648c7875a59ddfba2d28fc835950
4
+ data.tar.gz: 332fb00fe13b2d437729f5de926f859f9978378e462e5c46062399fec6e3d08d
5
5
  SHA512:
6
- metadata.gz: e3f3076a4072842438e3ef20f8e167f1e2521ad2c4828eaef2ab29ad5d9a68d3e1dbc0d2ffd505525e82dac0bf4968ac21e31e8114dadf56c3653e7626bdec37
7
- data.tar.gz: c1d21b7db9bf332e37b7520219aa45f5059799bb0d32a463f5f4d070f44e7db55225d547242fc0e120622d251589d90c4f656e4c337a61fd4f2651be60ddae3f
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
- ActiveRecord::Base.transaction(requires_new: true) do
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.stream_name.eql?(EventRepository::SERIALIZED_GLOBAL_STREAM_NAME)
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.direction)) unless spec.global_stream?
31
- stream = stream.limit(spec.count) if spec.limit?
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.direction))
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, total_limit(spec), batch_reader).each
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.global_stream? ? EventRepository::SERIALIZED_GLOBAL_STREAM_NAME : specification.stream_name
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
- case specification.direction
57
- when :forward
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(direction)
65
- {forward: 'ASC', backward: 'DESC'}.fetch(direction)
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,3 +1,3 @@
1
1
  module RailsEventStoreActiveRecord
2
- VERSION = "0.31.1"
2
+ VERSION = "0.32.0"
3
3
  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.14'
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.31.1'
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.31.1
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-07-17 00:00:00.000000000 Z
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.14
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.14
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.31.1
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.31.1
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)