sequent 3.3.1 → 4.1.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/bin/sequent +31 -25
- data/lib/notices.rb +6 -0
- data/lib/sequent/application_record.rb +2 -0
- data/lib/sequent/configuration.rb +29 -29
- data/lib/sequent/core/aggregate_repository.rb +24 -14
- data/lib/sequent/core/aggregate_root.rb +16 -7
- data/lib/sequent/core/aggregate_roots.rb +24 -0
- data/lib/sequent/core/aggregate_snapshotter.rb +8 -5
- data/lib/sequent/core/base_command_handler.rb +4 -2
- data/lib/sequent/core/command.rb +30 -11
- data/lib/sequent/core/command_record.rb +12 -4
- data/lib/sequent/core/command_service.rb +41 -25
- data/lib/sequent/core/core.rb +2 -0
- data/lib/sequent/core/current_event.rb +2 -0
- data/lib/sequent/core/event.rb +16 -11
- data/lib/sequent/core/event_publisher.rb +20 -15
- data/lib/sequent/core/event_record.rb +7 -7
- data/lib/sequent/core/event_store.rb +75 -49
- data/lib/sequent/core/ext/ext.rb +9 -1
- data/lib/sequent/core/helpers/array_with_type.rb +4 -1
- data/lib/sequent/core/helpers/association_validator.rb +9 -7
- data/lib/sequent/core/helpers/attribute_support.rb +64 -33
- data/lib/sequent/core/helpers/autoset_attributes.rb +4 -4
- data/lib/sequent/core/helpers/boolean_validator.rb +6 -1
- data/lib/sequent/core/helpers/copyable.rb +2 -2
- data/lib/sequent/core/helpers/date_time_validator.rb +4 -1
- data/lib/sequent/core/helpers/date_validator.rb +6 -1
- data/lib/sequent/core/helpers/default_validators.rb +12 -10
- data/lib/sequent/core/helpers/equal_support.rb +8 -6
- data/lib/sequent/core/helpers/helpers.rb +2 -0
- data/lib/sequent/core/helpers/mergable.rb +6 -4
- data/lib/sequent/core/helpers/message_handler.rb +3 -1
- data/lib/sequent/core/helpers/param_support.rb +19 -15
- data/lib/sequent/core/helpers/secret.rb +14 -12
- data/lib/sequent/core/helpers/string_support.rb +5 -4
- data/lib/sequent/core/helpers/string_to_value_parsers.rb +7 -2
- data/lib/sequent/core/helpers/string_validator.rb +6 -1
- data/lib/sequent/core/helpers/type_conversion_support.rb +5 -3
- data/lib/sequent/core/helpers/uuid_helper.rb +5 -2
- data/lib/sequent/core/helpers/value_validators.rb +23 -9
- data/lib/sequent/core/persistors/active_record_persistor.rb +19 -9
- data/lib/sequent/core/persistors/persistor.rb +16 -14
- data/lib/sequent/core/persistors/persistors.rb +2 -0
- data/lib/sequent/core/persistors/replay_optimized_postgres_persistor.rb +70 -47
- data/lib/sequent/core/projector.rb +25 -22
- data/lib/sequent/core/random_uuid_generator.rb +2 -0
- data/lib/sequent/core/sequent_oj.rb +2 -0
- data/lib/sequent/core/stream_record.rb +9 -3
- data/lib/sequent/core/transactions/active_record_transaction_provider.rb +7 -9
- data/lib/sequent/core/transactions/no_transactions.rb +2 -1
- data/lib/sequent/core/transactions/transactions.rb +2 -0
- data/lib/sequent/core/value_object.rb +8 -10
- data/lib/sequent/core/workflow.rb +7 -5
- data/lib/sequent/generator/aggregate.rb +16 -10
- data/lib/sequent/generator/command.rb +26 -19
- data/lib/sequent/generator/event.rb +19 -17
- data/lib/sequent/generator/generator.rb +6 -0
- data/lib/sequent/generator/project.rb +3 -1
- data/lib/sequent/generator/template_project/Gemfile +1 -1
- data/lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb +1 -1
- data/lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb +1 -1
- data/lib/sequent/generator.rb +3 -4
- data/lib/sequent/migrations/executor.rb +30 -9
- data/lib/sequent/migrations/functions.rb +5 -6
- data/lib/sequent/migrations/migrate_events.rb +12 -9
- data/lib/sequent/migrations/migrations.rb +2 -1
- data/lib/sequent/migrations/planner.rb +33 -23
- data/lib/sequent/migrations/projectors.rb +4 -3
- data/lib/sequent/migrations/sql.rb +2 -0
- data/lib/sequent/migrations/view_schema.rb +93 -44
- data/lib/sequent/rake/migration_tasks.rb +59 -23
- data/lib/sequent/rake/tasks.rb +5 -2
- data/lib/sequent/sequent.rb +6 -1
- data/lib/sequent/support/database.rb +39 -17
- data/lib/sequent/support/view_projection.rb +6 -3
- data/lib/sequent/support/view_schema.rb +2 -0
- data/lib/sequent/support.rb +2 -0
- data/lib/sequent/test/command_handler_helpers.rb +39 -17
- data/lib/sequent/test/event_handler_helpers.rb +10 -4
- data/lib/sequent/test/event_stream_helpers.rb +7 -3
- data/lib/sequent/test/time_comparison.rb +12 -5
- data/lib/sequent/test.rb +2 -0
- data/lib/sequent/util/dry_run.rb +194 -0
- data/lib/sequent/util/printer.rb +6 -5
- data/lib/sequent/util/skip_if_already_processing.rb +21 -5
- data/lib/sequent/util/timer.rb +2 -0
- data/lib/sequent/util/util.rb +3 -0
- data/lib/sequent.rb +4 -0
- data/lib/version.rb +3 -1
- metadata +110 -59
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
|
3
5
|
module Sequent
|
@@ -14,8 +16,7 @@ module Sequent
|
|
14
16
|
end
|
15
17
|
|
16
18
|
class StreamRecord < Sequent::ApplicationRecord
|
17
|
-
|
18
|
-
self.table_name = "stream_records"
|
19
|
+
self.table_name = 'stream_records'
|
19
20
|
|
20
21
|
validates_presence_of :aggregate_type, :aggregate_id
|
21
22
|
validates_numericality_of :snapshot_threshold, only_integer: true, greater_than: 0, allow_nil: true
|
@@ -23,7 +24,12 @@ module Sequent
|
|
23
24
|
has_many :event_records
|
24
25
|
|
25
26
|
def event_stream
|
26
|
-
EventStream.new(
|
27
|
+
EventStream.new(
|
28
|
+
aggregate_type: aggregate_type,
|
29
|
+
aggregate_id: aggregate_id,
|
30
|
+
snapshot_threshold: snapshot_threshold,
|
31
|
+
stream_record_id: id,
|
32
|
+
)
|
27
33
|
end
|
28
34
|
|
29
35
|
def event_stream=(data)
|
@@ -1,13 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sequent
|
2
4
|
module Core
|
3
5
|
module Transactions
|
4
|
-
|
5
6
|
class ActiveRecordTransactionProvider
|
6
|
-
def transactional
|
7
|
-
Sequent::ApplicationRecord.transaction(requires_new: true)
|
8
|
-
|
9
|
-
end
|
10
|
-
after_commit_queue.each &:call
|
7
|
+
def transactional(&block)
|
8
|
+
Sequent::ApplicationRecord.transaction(requires_new: true, &block)
|
9
|
+
after_commit_queue.pop.call until after_commit_queue.empty?
|
11
10
|
ensure
|
12
11
|
clear_after_commit_queue
|
13
12
|
end
|
@@ -19,14 +18,13 @@ module Sequent
|
|
19
18
|
private
|
20
19
|
|
21
20
|
def after_commit_queue
|
22
|
-
Thread.current[:after_commit_queue] ||=
|
21
|
+
Thread.current[:after_commit_queue] ||= Queue.new
|
23
22
|
end
|
24
23
|
|
25
24
|
def clear_after_commit_queue
|
26
|
-
|
25
|
+
after_commit_queue.clear
|
27
26
|
end
|
28
27
|
end
|
29
|
-
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_model'
|
2
4
|
require_relative 'helpers/string_support'
|
3
5
|
require_relative 'helpers/equal_support'
|
@@ -6,7 +8,6 @@ require_relative 'helpers/attribute_support'
|
|
6
8
|
require_relative 'helpers/param_support'
|
7
9
|
|
8
10
|
module Sequent
|
9
|
-
|
10
11
|
module Core
|
11
12
|
#
|
12
13
|
# ValueObject is a container for data that belongs together but requires no identity
|
@@ -26,20 +27,17 @@ module Sequent
|
|
26
27
|
#
|
27
28
|
# This a deep clone of the address with the street attribute containing "New Street"
|
28
29
|
class ValueObject
|
29
|
-
include
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
include ActiveModel::Validations
|
31
|
+
include Sequent::Core::Helpers::ParamSupport
|
32
|
+
include Sequent::Core::Helpers::AttributeSupport
|
33
|
+
include Sequent::Core::Helpers::Copyable
|
34
|
+
include Sequent::Core::Helpers::EqualSupport
|
35
|
+
include Sequent::Core::Helpers::StringSupport
|
35
36
|
include Sequent::Core::Helpers::TypeConversionSupport
|
36
37
|
|
37
38
|
def initialize(args = {})
|
38
39
|
update_all_attributes args
|
39
40
|
end
|
40
|
-
|
41
41
|
end
|
42
|
-
|
43
42
|
end
|
44
43
|
end
|
45
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'helpers/message_handler'
|
2
4
|
require_relative 'current_event'
|
3
5
|
|
@@ -11,7 +13,7 @@ module Sequent
|
|
11
13
|
begin
|
12
14
|
old_event = CurrentEvent.current
|
13
15
|
CurrentEvent.current = event
|
14
|
-
|
16
|
+
instance_exec(event, &block)
|
15
17
|
ensure
|
16
18
|
CurrentEvent.current = old_event
|
17
19
|
end
|
@@ -31,12 +33,12 @@ module Sequent
|
|
31
33
|
# jobs processor is not using the same database connection
|
32
34
|
# to enqueue jobs.
|
33
35
|
def after_commit(ignore_errors: false, &block)
|
34
|
-
Sequent.configuration.transaction_provider.after_commit
|
35
|
-
rescue StandardError =>
|
36
|
+
Sequent.configuration.transaction_provider.after_commit(&block)
|
37
|
+
rescue StandardError => e
|
36
38
|
if ignore_errors
|
37
|
-
Sequent.logger.warn("An exception was raised in an after_commit hook: #{
|
39
|
+
Sequent.logger.warn("An exception was raised in an after_commit hook: #{e}, #{e.inspect}")
|
38
40
|
else
|
39
|
-
raise
|
41
|
+
raise e
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'active_support'
|
3
5
|
require 'active_support/core_ext/string'
|
@@ -7,8 +9,6 @@ class TargetAlreadyExists < StandardError; end
|
|
7
9
|
module Sequent
|
8
10
|
module Generator
|
9
11
|
class Aggregate
|
10
|
-
attr_reader :name
|
11
|
-
|
12
12
|
def initialize(name)
|
13
13
|
@name = name
|
14
14
|
end
|
@@ -20,6 +20,10 @@ module Sequent
|
|
20
20
|
replace_template_aggregate
|
21
21
|
end
|
22
22
|
|
23
|
+
def name
|
24
|
+
@name ||= File.basename(path)
|
25
|
+
end
|
26
|
+
|
23
27
|
private
|
24
28
|
|
25
29
|
def copy_files
|
@@ -30,8 +34,14 @@ module Sequent
|
|
30
34
|
FileUtils.mv("#{path}/template_aggregate.rb", "#{path}/#{name_underscored}.rb")
|
31
35
|
FileUtils.mv("#{path}/template_aggregate", "#{path}/#{name_underscored}")
|
32
36
|
|
33
|
-
FileUtils.mv(
|
34
|
-
|
37
|
+
FileUtils.mv(
|
38
|
+
"#{path}/#{name_underscored}/template_aggregate_command_handler.rb",
|
39
|
+
"#{path}/#{name_underscored}/#{name_underscored}_command_handler.rb",
|
40
|
+
)
|
41
|
+
FileUtils.mv(
|
42
|
+
"#{path}/#{name_underscored}/template_aggregate.rb",
|
43
|
+
"#{path}/#{name_underscored}/#{name_underscored}.rb",
|
44
|
+
)
|
35
45
|
end
|
36
46
|
|
37
47
|
def replace_template_aggregate
|
@@ -46,11 +56,7 @@ module Sequent
|
|
46
56
|
end
|
47
57
|
|
48
58
|
def path
|
49
|
-
@path ||= File.expand_path(
|
50
|
-
end
|
51
|
-
|
52
|
-
def name
|
53
|
-
@name ||= File.basename(path)
|
59
|
+
@path ||= File.expand_path('lib')
|
54
60
|
end
|
55
61
|
|
56
62
|
def name_underscored
|
@@ -63,7 +69,7 @@ module Sequent
|
|
63
69
|
|
64
70
|
def ensure_not_used!
|
65
71
|
if File.directory?("#{path}/#{name_underscored}") || File.exist?("#{path}/#{name_underscored}.rb")
|
66
|
-
|
72
|
+
fail TargetAlreadyExists
|
67
73
|
end
|
68
74
|
end
|
69
75
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'active_support'
|
3
5
|
require 'active_support/core_ext/string'
|
@@ -9,12 +11,12 @@ class NoAggregateFound < StandardError; end
|
|
9
11
|
module Sequent
|
10
12
|
module Generator
|
11
13
|
class Command
|
12
|
-
attr_reader :
|
14
|
+
attr_reader :command, :attrs
|
13
15
|
|
14
16
|
def initialize(name, command, attrs)
|
15
17
|
@name = name
|
16
18
|
@command = command
|
17
|
-
@attrs = attrs.map{|a| a.split(':')}
|
19
|
+
@attrs = attrs.map { |a| a.split(':') }
|
18
20
|
end
|
19
21
|
|
20
22
|
def execute
|
@@ -22,32 +24,39 @@ module Sequent
|
|
22
24
|
add_command_to_aggregate
|
23
25
|
end
|
24
26
|
|
27
|
+
def name
|
28
|
+
@name ||= File.basename(path)
|
29
|
+
end
|
30
|
+
|
25
31
|
private
|
32
|
+
|
26
33
|
def append_command_handler
|
27
34
|
ast = Parser::CurrentRuby.parse(File.read("#{path_to_dir}/#{name_underscored}_command_handler.rb"))
|
28
35
|
target_cursor_position = find_target_cursor_position(ast)
|
29
|
-
|
36
|
+
|
30
37
|
File.open("#{path_to_dir}/#{name_underscored}_command_handler.rb", 'r+') do |f|
|
31
38
|
f.seek(target_cursor_position, IO::SEEK_SET)
|
32
39
|
lines_to_be_overwritten = f.read
|
33
40
|
f.seek(target_cursor_position, IO::SEEK_SET)
|
34
|
-
f << command_handler_template.result(binding).gsub(/^.+(\s)$/) { |x| x.gsub!(
|
41
|
+
f << command_handler_template.result(binding).gsub(/^.+(\s)$/) { |x| x.gsub!(Regexp.last_match(1), '') }
|
35
42
|
f << lines_to_be_overwritten
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
39
46
|
def find_target_cursor_position(ast)
|
40
47
|
return unless ast.children.any?
|
48
|
+
return if ast.children.any? { |c| c.class.to_s != 'Parser::AST::Node' }
|
49
|
+
if (child = ast.children.find { |c| c.type.to_s == 'block' })
|
50
|
+
return child.loc.expression.end_pos
|
51
|
+
end
|
41
52
|
|
42
|
-
ast.children.map do |
|
43
|
-
|
44
|
-
|
45
|
-
find_target_cursor_position(child)
|
46
|
-
end.flatten.compact.max
|
53
|
+
ast.children.map do |c|
|
54
|
+
find_target_cursor_position(c)
|
55
|
+
end&.flatten&.compact&.max
|
47
56
|
end
|
48
57
|
|
49
58
|
def append_command
|
50
|
-
File.open("#{path_to_dir}/commands.rb",
|
59
|
+
File.open("#{path_to_dir}/commands.rb", 'a') { |f| f << command_template.result(binding) }
|
51
60
|
end
|
52
61
|
|
53
62
|
def add_command_to_aggregate
|
@@ -56,11 +65,7 @@ module Sequent
|
|
56
65
|
end
|
57
66
|
|
58
67
|
def path
|
59
|
-
@path ||= File.expand_path(
|
60
|
-
end
|
61
|
-
|
62
|
-
def name
|
63
|
-
@name ||= File.basename(path)
|
68
|
+
@path ||= File.expand_path('lib')
|
64
69
|
end
|
65
70
|
|
66
71
|
def name_underscored
|
@@ -72,17 +77,19 @@ module Sequent
|
|
72
77
|
end
|
73
78
|
|
74
79
|
def ensure_existing_aggregate!
|
75
|
-
if !File.directory?(path_to_dir) ||
|
76
|
-
|
80
|
+
if !File.directory?(path_to_dir) ||
|
81
|
+
!File.exist?("#{path_to_dir}/#{name_underscored}_command_handler.rb") ||
|
82
|
+
!File.exist?("#{path_to_dir}/commands.rb")
|
83
|
+
fail NoAggregateFound
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
80
87
|
def command_template
|
81
|
-
ERB.new(File.read(File.join(
|
88
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'template_command.erb')))
|
82
89
|
end
|
83
90
|
|
84
91
|
def command_handler_template
|
85
|
-
ERB.new(File.read(File.join(
|
92
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'template_command_handler.erb')))
|
86
93
|
end
|
87
94
|
end
|
88
95
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'active_support'
|
3
5
|
require 'active_support/core_ext/string'
|
@@ -7,12 +9,16 @@ class NoAggregateFound < StandardError; end
|
|
7
9
|
module Sequent
|
8
10
|
module Generator
|
9
11
|
class Event
|
10
|
-
attr_reader :
|
12
|
+
attr_reader :event, :attrs
|
11
13
|
|
12
14
|
def initialize(name, event, attrs)
|
13
15
|
@name = name
|
14
16
|
@event = event
|
15
|
-
@attrs = attrs.map{|a| a.split(':')}
|
17
|
+
@attrs = attrs.map { |a| a.split(':') }
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
@name ||= File.basename(path)
|
16
22
|
end
|
17
23
|
|
18
24
|
def execute
|
@@ -23,29 +29,31 @@ module Sequent
|
|
23
29
|
private
|
24
30
|
|
25
31
|
def append_event
|
26
|
-
File.open("#{path_to_dir}/events.rb",
|
32
|
+
File.open("#{path_to_dir}/events.rb", 'a') { |f| f << event_template.result(binding) }
|
27
33
|
end
|
28
34
|
|
29
35
|
def append_event_to_domain
|
30
36
|
ast = Parser::CurrentRuby.parse(File.read("#{path_to_dir}/#{name_underscored}.rb"))
|
31
37
|
target_cursor_position = find_target_cursor_position(ast)
|
32
|
-
|
38
|
+
|
33
39
|
File.open("#{path_to_dir}/#{name_underscored}.rb", 'r+') do |f|
|
34
40
|
f.seek(target_cursor_position, IO::SEEK_SET)
|
35
41
|
lines_to_be_overwritten = f.read
|
36
42
|
f.seek(target_cursor_position, IO::SEEK_SET)
|
37
|
-
f << event_handler_template.result(binding).gsub(/^.+(\s)$/) { |x| x.gsub!(
|
43
|
+
f << event_handler_template.result(binding).gsub(/^.+(\s)$/) { |x| x.gsub!(Regexp.last_match(1), '') }
|
38
44
|
f << lines_to_be_overwritten
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def find_target_cursor_position(ast)
|
43
49
|
return unless ast.children.any?
|
50
|
+
return if ast.children.any? { |c| c.class.to_s != 'Parser::AST::Node' }
|
51
|
+
if (child = ast.children.find { |c| c.type.to_s == 'block' })
|
52
|
+
return child.loc.expression.end_pos
|
53
|
+
end
|
44
54
|
|
45
|
-
ast.children.reverse.map do |
|
46
|
-
|
47
|
-
return child.loc.expression.end_pos if child.type.to_s == 'block'
|
48
|
-
find_target_cursor_position(child)
|
55
|
+
ast.children.reverse.map do |c|
|
56
|
+
find_target_cursor_position(c)
|
49
57
|
end.flatten.compact.max
|
50
58
|
end
|
51
59
|
|
@@ -55,11 +63,7 @@ module Sequent
|
|
55
63
|
end
|
56
64
|
|
57
65
|
def path
|
58
|
-
@path ||= File.expand_path(
|
59
|
-
end
|
60
|
-
|
61
|
-
def name
|
62
|
-
@name ||= File.basename(path)
|
66
|
+
@path ||= File.expand_path('lib')
|
63
67
|
end
|
64
68
|
|
65
69
|
def name_underscored
|
@@ -71,9 +75,7 @@ module Sequent
|
|
71
75
|
end
|
72
76
|
|
73
77
|
def ensure_existing_aggregate!
|
74
|
-
if !File.directory?(path_to_dir) || !File.exist?("#{path_to_dir}/#{name_underscored}.rb")
|
75
|
-
raise NoAggregateFound
|
76
|
-
end
|
78
|
+
fail NoAggregateFound if !File.directory?(path_to_dir) || !File.exist?("#{path_to_dir}/#{name_underscored}.rb")
|
77
79
|
end
|
78
80
|
|
79
81
|
def event_template
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'active_support'
|
3
5
|
require 'active_support/core_ext/string'
|
@@ -54,7 +56,7 @@ module Sequent
|
|
54
56
|
end
|
55
57
|
|
56
58
|
def name_camelized
|
57
|
-
@name_camelized ||= name.camelize
|
59
|
+
@name_camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
data/lib/sequent/generator.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative './generator/
|
4
|
-
require_relative './generator/event'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './generator/generator'
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'sql'
|
2
4
|
|
3
5
|
module Sequent
|
4
6
|
module Migrations
|
5
|
-
|
6
7
|
##
|
7
8
|
# The executor is the implementation of the 3-phase deploy in Sequent.
|
8
9
|
# is responsible for executing the `Planner::Plan`.
|
@@ -21,10 +22,26 @@ module Sequent
|
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
25
|
+
def create_indexes_after_execute_online(plan)
|
26
|
+
plan.replay_tables.each do |migration|
|
27
|
+
table = migration.record_class
|
28
|
+
original_table_name = table.table_name.gsub("_#{migration.version}", '')
|
29
|
+
indexes_file_name = <<~EOS.chomp
|
30
|
+
#{Sequent.configuration.migration_sql_files_directory}/#{original_table_name}.indexes.sql
|
31
|
+
EOS
|
32
|
+
next unless File.exist?(indexes_file_name)
|
33
|
+
|
34
|
+
statements = sql_file_to_statements(indexes_file_name) do |raw_sql|
|
35
|
+
raw_sql.gsub('%SUFFIX%', "_#{migration.version}")
|
36
|
+
end
|
37
|
+
statements.each(&method(:exec_sql))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
24
41
|
def execute_offline(plan, current_version)
|
25
42
|
plan.replay_tables.each do |migration|
|
26
43
|
table = migration.record_class
|
27
|
-
current_table_name = table.table_name.gsub("_#{migration.version}",
|
44
|
+
current_table_name = table.table_name.gsub("_#{migration.version}", '')
|
28
45
|
# 2 Rename old table
|
29
46
|
exec_sql("ALTER TABLE IF EXISTS #{current_table_name} RENAME TO #{current_table_name}_#{current_version}")
|
30
47
|
# 3 Rename new table
|
@@ -36,7 +53,9 @@ module Sequent
|
|
36
53
|
|
37
54
|
plan.alter_tables.each do |migration|
|
38
55
|
table = migration.record_class
|
39
|
-
sql_file =
|
56
|
+
sql_file = <<~EOS.chomp
|
57
|
+
#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}_#{migration.version}.sql
|
58
|
+
EOS
|
40
59
|
statements = sql_file_to_statements(sql_file)
|
41
60
|
statements.each(&method(:exec_sql))
|
42
61
|
end
|
@@ -45,7 +64,7 @@ module Sequent
|
|
45
64
|
def reset_table_names(plan)
|
46
65
|
plan.replay_tables.each do |migration|
|
47
66
|
table = migration.record_class
|
48
|
-
table.table_name = table.table_name.gsub("_#{migration.version}",
|
67
|
+
table.table_name = table.table_name.gsub("_#{migration.version}", '')
|
49
68
|
table.reset_column_information
|
50
69
|
end
|
51
70
|
end
|
@@ -53,14 +72,16 @@ module Sequent
|
|
53
72
|
def set_table_names_to_new_version(plan)
|
54
73
|
plan.replay_tables.each do |migration|
|
55
74
|
table = migration.record_class
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
75
|
+
next if table.table_name.end_with?("_#{migration.version}")
|
76
|
+
|
77
|
+
table.table_name = "#{table.table_name}_#{migration.version}"
|
78
|
+
table.reset_column_information
|
79
|
+
unless table.table_exists?
|
80
|
+
fail MigrationError,
|
81
|
+
"Table #{table.table_name} does not exist. Did you run ViewSchema.migrate_online first?"
|
60
82
|
end
|
61
83
|
end
|
62
84
|
end
|
63
|
-
|
64
85
|
end
|
65
86
|
end
|
66
87
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sequent
|
2
4
|
module Migrations
|
3
5
|
class Migration
|
4
|
-
|
5
6
|
module ClassMethods
|
6
7
|
def create(record_class, version)
|
7
8
|
migration = new(record_class)
|
@@ -11,6 +12,7 @@ module Sequent
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def self.inherited(child_class)
|
15
|
+
super
|
14
16
|
class << child_class
|
15
17
|
include ClassMethods
|
16
18
|
end
|
@@ -35,11 +37,11 @@ module Sequent
|
|
35
37
|
def ==(other)
|
36
38
|
return false unless other.class == self.class
|
37
39
|
|
38
|
-
|
40
|
+
table_name == other.table_name && version == other.version
|
39
41
|
end
|
40
42
|
|
41
43
|
def hash
|
42
|
-
|
44
|
+
table_name.hash + (version&.hash || 0)
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
@@ -48,7 +50,6 @@ module Sequent
|
|
48
50
|
class ReplayTable < Migration; end
|
49
51
|
|
50
52
|
module Functions
|
51
|
-
|
52
53
|
module ClassMethods
|
53
54
|
def alter_table(name)
|
54
55
|
AlterTable.new(name)
|
@@ -62,13 +63,11 @@ module Sequent
|
|
62
63
|
def all_projectors
|
63
64
|
Sequent::Core::Migratable.all
|
64
65
|
end
|
65
|
-
|
66
66
|
end
|
67
67
|
|
68
68
|
def self.included(base)
|
69
69
|
base.extend(ClassMethods)
|
70
70
|
end
|
71
|
-
|
72
71
|
end
|
73
72
|
|
74
73
|
include Functions
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
##
|
2
4
|
# When you need to upgrade the event store based on information of the previous schema version
|
3
5
|
# this is the place you need to implement a migration.
|
@@ -20,11 +22,12 @@
|
|
20
22
|
module Sequent
|
21
23
|
module Migrations
|
22
24
|
class MigrateEvents
|
23
|
-
|
24
25
|
##
|
25
26
|
# @param env The string representing the current environment. E.g. "development", "production"
|
26
27
|
def initialize(env)
|
27
|
-
warn
|
28
|
+
warn <<~EOS
|
29
|
+
[DEPRECATED] Use of MigrateEvents is deprecated and will be removed from future version. Please use Sequent::Migrations::ViewSchema instead. See the changelog on how to update.
|
30
|
+
EOS
|
28
31
|
@env = env
|
29
32
|
end
|
30
33
|
|
@@ -32,9 +35,10 @@ module Sequent
|
|
32
35
|
#
|
33
36
|
# @param current_version The current version of the application. E.g. 10
|
34
37
|
# @param new_version The version to migrate to. E.g. 11
|
35
|
-
# @param &after_migration_block an optional block (with the current upgrade version as param)
|
38
|
+
# @param &after_migration_block an optional block (with the current upgrade version as param)
|
39
|
+
# to run after the migrations run. E.g. close resources
|
36
40
|
#
|
37
|
-
def execute_migrations(current_version, new_version
|
41
|
+
def execute_migrations(current_version, new_version)
|
38
42
|
migrations(current_version, new_version).each do |migration_class|
|
39
43
|
migration = migration_class.new(@env)
|
40
44
|
begin
|
@@ -47,12 +51,11 @@ module Sequent
|
|
47
51
|
|
48
52
|
def migrations(current_version, new_version)
|
49
53
|
return [] if current_version == 0
|
54
|
+
|
50
55
|
((current_version + 1)..new_version).map do |upgrade_to_version|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
nil
|
55
|
-
end
|
56
|
+
Class.const_get("Database::MigrateToVersion#{upgrade_to_version}")
|
57
|
+
rescue NameError
|
58
|
+
nil
|
56
59
|
end.compact
|
57
60
|
end
|
58
61
|
|