sequent 3.2.2 → 4.0.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/notices.rb +4 -0
  3. data/lib/sequent.rb +3 -0
  4. data/lib/sequent/application_record.rb +7 -0
  5. data/lib/sequent/configuration.rb +13 -0
  6. data/lib/sequent/core/aggregate_repository.rb +7 -1
  7. data/lib/sequent/core/command.rb +13 -2
  8. data/lib/sequent/core/command_record.rb +5 -2
  9. data/lib/sequent/core/command_service.rb +28 -12
  10. data/lib/sequent/core/event_publisher.rb +4 -0
  11. data/lib/sequent/core/event_record.rb +2 -1
  12. data/lib/sequent/core/event_store.rb +23 -4
  13. data/lib/sequent/core/helpers/attribute_support.rb +28 -7
  14. data/lib/sequent/core/helpers/mergable.rb +1 -0
  15. data/lib/sequent/core/persistors/active_record_persistor.rb +1 -1
  16. data/lib/sequent/core/persistors/replay_optimized_postgres_persistor.rb +2 -2
  17. data/lib/sequent/core/projector.rb +23 -1
  18. data/lib/sequent/core/stream_record.rb +1 -1
  19. data/lib/sequent/core/transactions/active_record_transaction_provider.rb +6 -4
  20. data/lib/sequent/generator.rb +1 -4
  21. data/lib/sequent/generator/generator.rb +4 -0
  22. data/lib/sequent/generator/project.rb +1 -1
  23. data/lib/sequent/generator/template_project/Gemfile +1 -1
  24. data/lib/sequent/generator/template_project/app/records/post_record.rb +1 -1
  25. data/lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb +1 -1
  26. data/lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb +1 -1
  27. data/lib/sequent/migrations/executor.rb +78 -0
  28. data/lib/sequent/migrations/functions.rb +76 -0
  29. data/lib/sequent/migrations/migrations.rb +1 -0
  30. data/lib/sequent/migrations/planner.rb +118 -0
  31. data/lib/sequent/migrations/projectors.rb +6 -5
  32. data/lib/sequent/migrations/sql.rb +17 -0
  33. data/lib/sequent/migrations/view_schema.rb +74 -73
  34. data/lib/sequent/rake/migration_tasks.rb +2 -2
  35. data/lib/sequent/rake/tasks.rb +1 -1
  36. data/lib/sequent/sequent.rb +5 -1
  37. data/lib/sequent/support/database.rb +11 -6
  38. data/lib/sequent/test/command_handler_helpers.rb +4 -0
  39. data/lib/sequent/util/dry_run.rb +191 -0
  40. data/lib/sequent/util/skip_if_already_processing.rb +19 -5
  41. data/lib/sequent/util/util.rb +1 -0
  42. data/lib/version.rb +1 -1
  43. metadata +77 -36
@@ -13,7 +13,7 @@ module Sequent
13
13
  end
14
14
  end
15
15
 
16
- class StreamRecord < ActiveRecord::Base
16
+ class StreamRecord < Sequent::ApplicationRecord
17
17
 
18
18
  self.table_name = "stream_records"
19
19
 
@@ -4,10 +4,12 @@ module Sequent
4
4
 
5
5
  class ActiveRecordTransactionProvider
6
6
  def transactional
7
- ActiveRecord::Base.transaction(requires_new: true) do
7
+ Sequent::ApplicationRecord.transaction(requires_new: true) do
8
8
  yield
9
9
  end
10
- after_commit_queue.each &:call
10
+ while(!after_commit_queue.empty?) do
11
+ after_commit_queue.pop.call
12
+ end
11
13
  ensure
12
14
  clear_after_commit_queue
13
15
  end
@@ -19,11 +21,11 @@ module Sequent
19
21
  private
20
22
 
21
23
  def after_commit_queue
22
- Thread.current[:after_commit_queue] ||= []
24
+ Thread.current[:after_commit_queue] ||= Queue.new
23
25
  end
24
26
 
25
27
  def clear_after_commit_queue
26
- Thread.current[:after_commit_queue] = []
28
+ after_commit_queue.clear
27
29
  end
28
30
  end
29
31
 
@@ -1,4 +1 @@
1
- require_relative './generator/project'
2
- require_relative './generator/aggregate'
3
- require_relative './generator/command'
4
- require_relative './generator/event'
1
+ require_relative './generator/generator'
@@ -0,0 +1,4 @@
1
+ require_relative 'aggregate'
2
+ require_relative 'command'
3
+ require_relative 'project'
4
+ require_relative 'event'
@@ -54,7 +54,7 @@ module Sequent
54
54
  end
55
55
 
56
56
  def name_camelized
57
- @name_camelized ||= name.camelize
57
+ @name_camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize
58
58
  end
59
59
  end
60
60
  end
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
- ruby "2.5.1"
2
+ ruby "2.6.5"
3
3
 
4
4
  gem 'rake'
5
5
  # let's use the latest and greatest
@@ -1,2 +1,2 @@
1
- class PostRecord < ActiveRecord::Base
1
+ class PostRecord < Sequent::ApplicationRecord
2
2
  end
@@ -1,4 +1,4 @@
1
- require_relative '../../spec_helper'
1
+ require 'spec_helper'
2
2
  require_relative '../../../app/projectors/post_projector'
3
3
 
4
4
  describe PostProjector do
@@ -1,4 +1,4 @@
1
- require_relative '../../spec_helper'
1
+ require 'spec_helper'
2
2
  require_relative '../../../lib/post'
3
3
 
4
4
  describe PostCommandHandler do
@@ -0,0 +1,78 @@
1
+ require_relative 'sql'
2
+
3
+ module Sequent
4
+ module Migrations
5
+
6
+ ##
7
+ # The executor is the implementation of the 3-phase deploy in Sequent.
8
+ # is responsible for executing the `Planner::Plan`.
9
+ #
10
+ class Executor
11
+ include Sql
12
+
13
+ def execute_online(plan)
14
+ plan.replay_tables.each do |migration|
15
+ table = migration.record_class
16
+ sql_file = "#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}.sql"
17
+ statements = sql_file_to_statements(sql_file) { |raw_sql| raw_sql.gsub('%SUFFIX%', "_#{migration.version}") }
18
+ statements.each(&method(:exec_sql))
19
+ table.table_name = "#{table.table_name}_#{migration.version}"
20
+ table.reset_column_information
21
+ end
22
+ end
23
+
24
+ def create_indexes_after_execute_online(plan)
25
+ plan.replay_tables.each do |migration|
26
+ table = migration.record_class
27
+ original_table_name = table.table_name.gsub("_#{migration.version}", '')
28
+ indexes_file_name = "#{Sequent.configuration.migration_sql_files_directory}/#{original_table_name}.indexes.sql"
29
+ if File.exist?(indexes_file_name)
30
+ statements = sql_file_to_statements(indexes_file_name) { |raw_sql| raw_sql.gsub('%SUFFIX%', "_#{migration.version}") }
31
+ statements.each(&method(:exec_sql))
32
+ end
33
+ end
34
+ end
35
+
36
+ def execute_offline(plan, current_version)
37
+ plan.replay_tables.each do |migration|
38
+ table = migration.record_class
39
+ current_table_name = table.table_name.gsub("_#{migration.version}", "")
40
+ # 2 Rename old table
41
+ exec_sql("ALTER TABLE IF EXISTS #{current_table_name} RENAME TO #{current_table_name}_#{current_version}")
42
+ # 3 Rename new table
43
+ exec_sql("ALTER TABLE #{table.table_name} RENAME TO #{current_table_name}")
44
+ # Use new table from now on
45
+ table.table_name = current_table_name
46
+ table.reset_column_information
47
+ end
48
+
49
+ plan.alter_tables.each do |migration|
50
+ table = migration.record_class
51
+ sql_file = "#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}_#{migration.version}.sql"
52
+ statements = sql_file_to_statements(sql_file)
53
+ statements.each(&method(:exec_sql))
54
+ end
55
+ end
56
+
57
+ def reset_table_names(plan)
58
+ plan.replay_tables.each do |migration|
59
+ table = migration.record_class
60
+ table.table_name = table.table_name.gsub("_#{migration.version}", "")
61
+ table.reset_column_information
62
+ end
63
+ end
64
+
65
+ def set_table_names_to_new_version(plan)
66
+ plan.replay_tables.each do |migration|
67
+ table = migration.record_class
68
+ unless table.table_name.end_with?("_#{migration.version}")
69
+ table.table_name = "#{table.table_name}_#{migration.version}"
70
+ table.reset_column_information
71
+ fail MigrationError.new("Table #{table.table_name} does not exist. Did you run ViewSchema.migrate_online first?") unless table.table_exists?
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,76 @@
1
+ module Sequent
2
+ module Migrations
3
+ class Migration
4
+
5
+ module ClassMethods
6
+ def create(record_class, version)
7
+ migration = new(record_class)
8
+ migration.version = version
9
+ migration
10
+ end
11
+ end
12
+
13
+ def self.inherited(child_class)
14
+ class << child_class
15
+ include ClassMethods
16
+ end
17
+ end
18
+
19
+ attr_reader :record_class
20
+ attr_accessor :version
21
+
22
+ def initialize(record_class)
23
+ @record_class = record_class
24
+ @version = nil
25
+ end
26
+
27
+ def table_name
28
+ @record_class.table_name
29
+ end
30
+
31
+ def copy(with_version)
32
+ self.class.create(record_class, with_version)
33
+ end
34
+
35
+ def ==(other)
36
+ return false unless other.class == self.class
37
+
38
+ self.table_name == other.table_name && version == other.version
39
+ end
40
+
41
+ def hash
42
+ self.table_name.hash + (version&.hash || 0)
43
+ end
44
+ end
45
+
46
+ class AlterTable < Migration; end
47
+
48
+ class ReplayTable < Migration; end
49
+
50
+ module Functions
51
+
52
+ module ClassMethods
53
+ def alter_table(name)
54
+ AlterTable.new(name)
55
+ end
56
+
57
+ def replay_table(name)
58
+ ReplayTable.new(name)
59
+ end
60
+
61
+ # Short hand for Sequent::Core::Migratable.all
62
+ def all_projectors
63
+ Sequent::Core::Migratable.all
64
+ end
65
+
66
+ end
67
+
68
+ def self.included(base)
69
+ base.extend(ClassMethods)
70
+ end
71
+
72
+ end
73
+
74
+ include Functions
75
+ end
76
+ end
@@ -7,3 +7,4 @@ end
7
7
  require_relative 'migrate_events'
8
8
  require_relative 'projectors'
9
9
  require_relative 'view_schema'
10
+ require_relative 'functions'
@@ -0,0 +1,118 @@
1
+ module Sequent
2
+ module Migrations
3
+ class Planner
4
+ Plan = Struct.new(:projectors, :migrations) do
5
+ def replay_tables
6
+ migrations.select { |m| m.class == ReplayTable }
7
+ end
8
+
9
+ def alter_tables
10
+ migrations.select { |m| m.class == AlterTable }
11
+ end
12
+
13
+ def empty?
14
+ migrations.empty?
15
+ end
16
+ end
17
+
18
+ attr_reader :versions
19
+
20
+ def initialize(versions)
21
+ @versions = versions
22
+ end
23
+
24
+ def plan(old, new)
25
+ migrations = versions.slice(*Range.new(old + 1, new).to_a.map(&:to_s))
26
+
27
+ Plan.new(
28
+ migrations.yield_self(&method(:select_projectors)),
29
+ migrations
30
+ .yield_self(&method(:create_migrations))
31
+ .yield_self(&method(:remove_redundant_migrations))
32
+ )
33
+ end
34
+
35
+ private
36
+
37
+ def select_projectors(migrations)
38
+ migrations
39
+ .values
40
+ .flatten
41
+ .select { |v| v.is_a?(Class) && v < Sequent::Projector }.uniq
42
+ end
43
+
44
+ def remove_redundant_migrations(migrations)
45
+ redundant_migrations = migrations
46
+ .yield_self(&method(:group_identical_migrations))
47
+ .yield_self(&method(:select_redundant_migrations))
48
+ .yield_self(&method(:remove_redundancy))
49
+ .values
50
+ .flatten
51
+
52
+ (migrations - redundant_migrations)
53
+ .yield_self(&method(:remove_alter_tables_before_replay_table))
54
+ end
55
+
56
+ def group_identical_migrations(migrations)
57
+ migrations
58
+ .group_by { |migration| {migration_type: migration.class, record_class: migration.record_class} }
59
+ end
60
+
61
+ def select_redundant_migrations(grouped_migrations)
62
+ grouped_migrations.select { |type, ms| type[:migration_type] == ReplayTable && ms.length > 1 }
63
+ end
64
+
65
+ def remove_alter_tables_before_replay_table(migrations)
66
+ migrations - migrations
67
+ .each_with_index
68
+ .select { |migration, _index| migration.class == AlterTable }
69
+ .select { |migration, index| migrations
70
+ .slice((index + 1)..-1)
71
+ .find { |m| m.class == ReplayTable && m.record_class == migration.record_class }
72
+ }.map(&:first)
73
+ end
74
+
75
+ def remove_redundancy(grouped_migrations)
76
+ grouped_migrations.reduce({}) { |memo, (key, ms)|
77
+ memo[key] = ms
78
+ .yield_self(&method(:order_by_version_desc))
79
+ .slice(1..-1)
80
+ memo
81
+ }
82
+ end
83
+
84
+ def order_by_version_desc(migrations)
85
+ migrations.sort_by { |m| m.version.to_i }
86
+ .reverse
87
+ end
88
+
89
+ def create_migrations(migrations)
90
+ migrations
91
+ .yield_self(&method(:map_to_migrations))
92
+ .values
93
+ .compact
94
+ .flatten
95
+ end
96
+
97
+ def map_to_migrations(migrations)
98
+ migrations.reduce({}) do |memo, (version, _migrations)|
99
+ fail "Declared migrations for version #{version} must be an Array. For example: {'3' => [FooProjector]}" unless _migrations.is_a?(Array)
100
+
101
+ memo[version] = _migrations.flat_map do |migration|
102
+ if migration.is_a?(AlterTable)
103
+ alter_table_sql_file_name = "#{Sequent.configuration.migration_sql_files_directory}/#{migration.table_name}_#{version}.sql"
104
+ fail "Missing file #{alter_table_sql_file_name} to apply for version #{version}" unless File.exist?(alter_table_sql_file_name)
105
+ migration.copy(version)
106
+ elsif migration < Sequent::Projector
107
+ migration.managed_tables.map { |table| ReplayTable.create(table, version) }
108
+ else
109
+ fail "Unknown Migration #{migration}"
110
+ end
111
+ end
112
+
113
+ memo
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,18 +1,19 @@
1
+ require_relative 'planner'
1
2
  module Sequent
2
3
  module Migrations
3
4
  class Projectors
4
5
  def self.versions
5
- fail "Define your own Sequent::Migrations::Projectors class that extends this class and implements this method"
6
+ fail "Define your own Sequent::Migrations::List class that extends this class and implements this method"
6
7
  end
7
8
 
8
9
  def self.version
9
- fail "Define your own Sequent::Migrations::Projectors class that extends this class and implements this method"
10
+ fail "Define your own Sequent::Migrations::List class that extends this class and implements this method"
10
11
  end
11
12
 
12
- def self.projectors_between(old, new)
13
- versions.values_at(*Range.new(old + 1, new).to_a.map(&:to_s)).compact.flatten.uniq
13
+ def self.migrations_between(old, new)
14
+ Planner.new(versions).plan(old, new)
14
15
  end
15
16
  end
17
+
16
18
  end
17
19
  end
18
-
@@ -0,0 +1,17 @@
1
+ require_relative '../application_record'
2
+
3
+ module Sequent
4
+ module Migrations
5
+ module Sql
6
+ def sql_file_to_statements(file_location)
7
+ sql_string = File.read(file_location, encoding: 'bom|utf-8')
8
+ sql_string = yield(sql_string) if block_given?
9
+ sql_string.split(/;$/).reject { |statement| statement.remove("\n").blank? }
10
+ end
11
+
12
+ def exec_sql(sql)
13
+ Sequent::ApplicationRecord.connection.execute(sql)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,30 +6,56 @@ require_relative '../sequent'
6
6
  require_relative '../util/timer'
7
7
  require_relative '../util/printer'
8
8
  require_relative './projectors'
9
+ require_relative 'planner'
10
+ require_relative 'executor'
11
+ require_relative 'sql'
9
12
 
10
13
  module Sequent
11
14
  module Migrations
12
15
  class MigrationError < RuntimeError; end
13
16
 
14
-
15
17
  ##
16
- # Responsible for migration of Projectors between view schema versions.
18
+ # ViewSchema is used for migration of you view_schema. For instance
19
+ # when you create new Projectors or change existing Projectors.
17
20
  #
18
- # A Projector needs migration when for instance:
21
+ # The following migrations are supported:
19
22
  #
20
- # - New columns are added
21
- # - Structure is changed
23
+ # - ReplayTable (Projector migrations)
24
+ # - AlterTable (For instance if you introduce a new column)
22
25
  #
23
26
  # To maintain your migrations you need to:
24
27
  # 1. Create a class that extends `Sequent::Migrations::Projectors` and specify in `Sequent.configuration.migrations_class_name`
25
- # 2. Define per version which Projectors you want to migrate
28
+ # 2. Define per version which migrations you want to execute
26
29
  # See the definition of `Sequent::Migrations::Projectors.versions` and `Sequent::Migrations::Projectors.version`
27
30
  # 3. Specify in Sequent where your sql files reside (Sequent.configuration.migration_sql_files_directory)
28
31
  # 4. Ensure that you add %SUFFIX% to each name that needs to be unique in postgres (like TABLE names, INDEX names, PRIMARY KEYS)
29
32
  # E.g. `create table foo%SUFFIX% (id serial NOT NULL, CONSTRAINT foo_pkey%SUFFIX% PRIMARY KEY (id))`
33
+ # 5. If you want to run an `alter_table` migration ensure that
34
+ # a sql file named `table_name_VERSION.sql` exists.
35
+ #
36
+ # Example:
37
+ #
38
+ # class AppMigrations < Sequent::Migrations::Projectors
39
+ # def self.version
40
+ # '3'
41
+ # end
42
+ #
43
+ # def self.versions
44
+ # {
45
+ # '1' => [Sequent.all_projectors],
46
+ # '2' => [
47
+ # UserProjector,
48
+ # InvoiceProjector,
49
+ # ],
50
+ # '3' => [
51
+ # Sequent::Migrations.alter_table(UserRecord)
52
+ # ]
53
+ #
54
+ # }
55
+ # end
30
56
  #
57
+ # end
31
58
  class ViewSchema
32
-
33
59
  # Corresponds with the index on aggregate_id column in the event_records table
34
60
  #
35
61
  # Since we replay in batches of the first 3 chars of the uuid we created an index on
@@ -42,9 +68,10 @@ module Sequent
42
68
 
43
69
  include Sequent::Util::Timer
44
70
  include Sequent::Util::Printer
71
+ include Sql
45
72
 
46
- class Versions < ActiveRecord::Base; end
47
- class ReplayedIds < ActiveRecord::Base; end
73
+ class Versions < Sequent::ApplicationRecord; end
74
+ class ReplayedIds < Sequent::ApplicationRecord; end
48
75
 
49
76
  attr_reader :view_schema, :db_config, :logger
50
77
 
@@ -71,6 +98,12 @@ module Sequent
71
98
  Sequent::Core::Migratable.all.flat_map(&:managed_tables).each do |table|
72
99
  statements = sql_file_to_statements("#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}.sql") { |raw_sql| raw_sql.remove('%SUFFIX%') }
73
100
  statements.each { |statement| exec_sql(statement) }
101
+
102
+ indexes_file_name = "#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}.indexes.sql"
103
+ if File.exist?(indexes_file_name)
104
+ statements = sql_file_to_statements(indexes_file_name) { |raw_sql| raw_sql.remove('%SUFFIX%') }
105
+ statements.each(&method(:exec_sql))
106
+ end
74
107
  end
75
108
  end
76
109
  end
@@ -80,7 +113,7 @@ module Sequent
80
113
  #
81
114
  # This method is mainly useful in test scenario's or development tasks
82
115
  def replay_all!
83
- replay!(Sequent::Core::Migratable.all, Sequent.configuration.online_replay_persistor_class.new)
116
+ replay!(Sequent.configuration.online_replay_persistor_class.new)
84
117
  end
85
118
 
86
119
  ##
@@ -95,6 +128,14 @@ module Sequent
95
128
  end
96
129
  end
97
130
 
131
+ def plan
132
+ @plan ||= Planner.new(Sequent.migration_class.versions).plan(current_version, Sequent.new_version)
133
+ end
134
+
135
+ def executor
136
+ @executor ||= Executor.new
137
+ end
138
+
98
139
  ##
99
140
  # First part of a view schema migration
100
141
  #
@@ -118,14 +159,16 @@ module Sequent
118
159
  truncate_replay_ids_table!
119
160
 
120
161
  drop_old_tables(Sequent.new_version)
121
- for_each_table_to_migrate do |table|
122
- statements = sql_file_to_statements("#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}.sql") { |raw_sql| raw_sql.gsub('%SUFFIX%', "_#{Sequent.new_version}") }
123
- statements.each { |statement| exec_sql(statement) }
124
- table.table_name = "#{table.table_name}_#{Sequent.new_version}"
125
- table.reset_column_information
126
- end
162
+ executor.execute_online(plan)
163
+ end
164
+
165
+ if plan.projectors.any?
166
+ replay!(Sequent.configuration.online_replay_persistor_class.new)
167
+ end
168
+
169
+ in_view_schema do
170
+ executor.create_indexes_after_execute_online(plan)
127
171
  end
128
- replay!(projectors_to_migrate, Sequent.configuration.online_replay_persistor_class.new)
129
172
  rescue Exception => e
130
173
  rollback_migration
131
174
  raise e
@@ -155,28 +198,20 @@ module Sequent
155
198
 
156
199
  ensure_version_correct!
157
200
 
158
- set_table_names_to_new_version
201
+ executor.set_table_names_to_new_version(plan)
159
202
 
160
203
  # 1 replay events not yet replayed
161
- replay!(projectors_to_migrate, Sequent.configuration.offline_replay_persistor_class.new, exclude_ids: true, group_exponent: 1)
204
+ replay!(Sequent.configuration.offline_replay_persistor_class.new, exclude_ids: true, group_exponent: 1) if plan.projectors.any?
162
205
 
163
206
  in_view_schema do
164
- ActiveRecord::Base.transaction do
165
- for_each_table_to_migrate do |table|
166
- current_table_name = table.table_name.gsub("_#{Sequent.new_version}", "")
167
- # 2 Rename old table
168
- exec_sql("ALTER TABLE IF EXISTS #{current_table_name} RENAME TO #{current_table_name}_#{current_version}")
169
- # 3 Rename new table
170
- exec_sql("ALTER TABLE #{table.table_name} RENAME TO #{current_table_name}")
171
- # Use new table from now on
172
- table.table_name = current_table_name
173
- table.reset_column_information
174
- end
175
- # 4. Create migration record
207
+ Sequent::ApplicationRecord.transaction do
208
+ # 2.1, 2.2
209
+ executor.execute_offline(plan, current_version)
210
+ # 2.3 Create migration record
176
211
  Versions.create!(version: Sequent.new_version)
177
212
  end
178
213
 
179
- # 5. Truncate replayed ids
214
+ # 3. Truncate replayed ids
180
215
  truncate_replay_ids_table!
181
216
  end
182
217
  logger.info "Migrated to version #{Sequent.new_version}"
@@ -186,41 +221,27 @@ module Sequent
186
221
  end
187
222
 
188
223
  private
189
- def set_table_names_to_new_version
190
- for_each_table_to_migrate do |table|
191
- unless table.table_name.end_with?("_#{Sequent.new_version}")
192
- table.table_name = "#{table.table_name}_#{Sequent.new_version}"
193
- table.reset_column_information
194
- fail MigrationError.new("Table #{table.table_name} does not exist. Did you run migrate_online first?") unless table.table_exists?
195
- end
196
- end
197
- end
198
224
 
199
- def reset_table_names
200
- for_each_table_to_migrate do |table|
201
- table.table_name = table.table_name.gsub("_#{Sequent.new_version}", "")
202
- table.reset_column_information
203
- end
204
- end
205
225
 
206
226
  def ensure_version_correct!
207
227
  create_view_schema_if_not_exists
208
228
  new_version = Sequent.new_version
209
229
 
210
230
  fail ArgumentError.new("new_version [#{new_version}] must be greater or equal to current_version [#{current_version}]") if new_version < current_version
231
+
211
232
  end
212
233
 
213
- def replay!(projectors, replay_persistor, exclude_ids: false, group_exponent: 3)
234
+ def replay!(replay_persistor, projectors: plan.projectors, exclude_ids: false, group_exponent: 3)
214
235
  logger.info "group_exponent: #{group_exponent.inspect}"
215
236
 
216
237
  with_sequent_config(replay_persistor, projectors) do
217
238
  logger.info "Start replaying events"
218
239
 
219
- time("#{16**group_exponent} groups replayed") do
240
+ time("#{16 ** group_exponent} groups replayed") do
220
241
  event_types = projectors.flat_map { |projector| projector.message_mapping.keys }.uniq.map(&:name)
221
242
  disconnect!
222
243
 
223
- number_of_groups = 16**group_exponent
244
+ number_of_groups = 16 ** group_exponent
224
245
  groups = groups_of_aggregate_id_prefixes(number_of_groups)
225
246
 
226
247
  @connected = false
@@ -264,7 +285,7 @@ module Sequent
264
285
  drop_old_tables(Sequent.new_version)
265
286
 
266
287
  truncate_replay_ids_table!
267
- reset_table_names
288
+ executor.reset_table_names(plan)
268
289
  end
269
290
 
270
291
  def truncate_replay_ids_table!
@@ -272,7 +293,7 @@ module Sequent
272
293
  end
273
294
 
274
295
  def groups_of_aggregate_id_prefixes(number_of_groups)
275
- all_prefixes = (0...16**LENGTH_OF_SUBSTRING_INDEX_ON_AGGREGATE_ID_IN_EVENT_STORE).to_a.map { |i| i.to_s(16) } # first x digits of hex
296
+ all_prefixes = (0...16 ** LENGTH_OF_SUBSTRING_INDEX_ON_AGGREGATE_ID_IN_EVENT_STORE).to_a.map { |i| i.to_s(16) } # first x digits of hex
276
297
  all_prefixes = all_prefixes.map { |s| s.length == 3 ? s : "#{"0" * (3 - s.length)}#{s}" }
277
298
 
278
299
  logger.info "Number of groups #{number_of_groups}"
@@ -280,17 +301,7 @@ module Sequent
280
301
  logger.debug "Prefixes: #{all_prefixes.length}"
281
302
  fail "Can not have more groups #{number_of_groups} than number of prefixes #{all_prefixes.length}" if number_of_groups > all_prefixes.length
282
303
 
283
- all_prefixes.each_slice(all_prefixes.length/number_of_groups).to_a
284
- end
285
-
286
- def for_each_table_to_migrate
287
- projectors_to_migrate.flat_map(&:managed_tables).each do |managed_table|
288
- yield(managed_table)
289
- end
290
- end
291
-
292
- def projectors_to_migrate
293
- Sequent.migration_class.projectors_between(current_version, Sequent.new_version)
304
+ all_prefixes.each_slice(all_prefixes.length / number_of_groups).to_a
294
305
  end
295
306
 
296
307
  def in_view_schema
@@ -299,12 +310,6 @@ module Sequent
299
310
  end
300
311
  end
301
312
 
302
- def sql_file_to_statements(file_location)
303
- raw_sql_string = File.read(file_location, encoding: 'bom|utf-8')
304
- sql_string = yield(raw_sql_string)
305
- sql_string.split(/;$/).reject { |statement| statement.remove("\n").blank? }
306
- end
307
-
308
313
  def drop_old_tables(new_version)
309
314
  versions_to_check = (current_version - 10)..new_version
310
315
  old_tables = versions_to_check.flat_map do |old_version|
@@ -358,10 +363,6 @@ module Sequent
358
363
  def establish_connection
359
364
  Sequent::Support::Database.establish_connection(db_config)
360
365
  end
361
-
362
- def exec_sql(sql)
363
- ActiveRecord::Base.connection.execute(sql)
364
- end
365
366
  end
366
367
  end
367
368
  end