rails_event_store_active_record 0.31.1 → 0.32.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
  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)