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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequent +31 -25
  3. data/lib/notices.rb +6 -0
  4. data/lib/sequent/application_record.rb +2 -0
  5. data/lib/sequent/configuration.rb +29 -29
  6. data/lib/sequent/core/aggregate_repository.rb +24 -14
  7. data/lib/sequent/core/aggregate_root.rb +16 -7
  8. data/lib/sequent/core/aggregate_roots.rb +24 -0
  9. data/lib/sequent/core/aggregate_snapshotter.rb +8 -5
  10. data/lib/sequent/core/base_command_handler.rb +4 -2
  11. data/lib/sequent/core/command.rb +30 -11
  12. data/lib/sequent/core/command_record.rb +12 -4
  13. data/lib/sequent/core/command_service.rb +41 -25
  14. data/lib/sequent/core/core.rb +2 -0
  15. data/lib/sequent/core/current_event.rb +2 -0
  16. data/lib/sequent/core/event.rb +16 -11
  17. data/lib/sequent/core/event_publisher.rb +20 -15
  18. data/lib/sequent/core/event_record.rb +7 -7
  19. data/lib/sequent/core/event_store.rb +75 -49
  20. data/lib/sequent/core/ext/ext.rb +9 -1
  21. data/lib/sequent/core/helpers/array_with_type.rb +4 -1
  22. data/lib/sequent/core/helpers/association_validator.rb +9 -7
  23. data/lib/sequent/core/helpers/attribute_support.rb +64 -33
  24. data/lib/sequent/core/helpers/autoset_attributes.rb +4 -4
  25. data/lib/sequent/core/helpers/boolean_validator.rb +6 -1
  26. data/lib/sequent/core/helpers/copyable.rb +2 -2
  27. data/lib/sequent/core/helpers/date_time_validator.rb +4 -1
  28. data/lib/sequent/core/helpers/date_validator.rb +6 -1
  29. data/lib/sequent/core/helpers/default_validators.rb +12 -10
  30. data/lib/sequent/core/helpers/equal_support.rb +8 -6
  31. data/lib/sequent/core/helpers/helpers.rb +2 -0
  32. data/lib/sequent/core/helpers/mergable.rb +6 -4
  33. data/lib/sequent/core/helpers/message_handler.rb +3 -1
  34. data/lib/sequent/core/helpers/param_support.rb +19 -15
  35. data/lib/sequent/core/helpers/secret.rb +14 -12
  36. data/lib/sequent/core/helpers/string_support.rb +5 -4
  37. data/lib/sequent/core/helpers/string_to_value_parsers.rb +7 -2
  38. data/lib/sequent/core/helpers/string_validator.rb +6 -1
  39. data/lib/sequent/core/helpers/type_conversion_support.rb +5 -3
  40. data/lib/sequent/core/helpers/uuid_helper.rb +5 -2
  41. data/lib/sequent/core/helpers/value_validators.rb +23 -9
  42. data/lib/sequent/core/persistors/active_record_persistor.rb +19 -9
  43. data/lib/sequent/core/persistors/persistor.rb +16 -14
  44. data/lib/sequent/core/persistors/persistors.rb +2 -0
  45. data/lib/sequent/core/persistors/replay_optimized_postgres_persistor.rb +70 -47
  46. data/lib/sequent/core/projector.rb +25 -22
  47. data/lib/sequent/core/random_uuid_generator.rb +2 -0
  48. data/lib/sequent/core/sequent_oj.rb +2 -0
  49. data/lib/sequent/core/stream_record.rb +9 -3
  50. data/lib/sequent/core/transactions/active_record_transaction_provider.rb +7 -9
  51. data/lib/sequent/core/transactions/no_transactions.rb +2 -1
  52. data/lib/sequent/core/transactions/transactions.rb +2 -0
  53. data/lib/sequent/core/value_object.rb +8 -10
  54. data/lib/sequent/core/workflow.rb +7 -5
  55. data/lib/sequent/generator/aggregate.rb +16 -10
  56. data/lib/sequent/generator/command.rb +26 -19
  57. data/lib/sequent/generator/event.rb +19 -17
  58. data/lib/sequent/generator/generator.rb +6 -0
  59. data/lib/sequent/generator/project.rb +3 -1
  60. data/lib/sequent/generator/template_project/Gemfile +1 -1
  61. data/lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb +1 -1
  62. data/lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb +1 -1
  63. data/lib/sequent/generator.rb +3 -4
  64. data/lib/sequent/migrations/executor.rb +30 -9
  65. data/lib/sequent/migrations/functions.rb +5 -6
  66. data/lib/sequent/migrations/migrate_events.rb +12 -9
  67. data/lib/sequent/migrations/migrations.rb +2 -1
  68. data/lib/sequent/migrations/planner.rb +33 -23
  69. data/lib/sequent/migrations/projectors.rb +4 -3
  70. data/lib/sequent/migrations/sql.rb +2 -0
  71. data/lib/sequent/migrations/view_schema.rb +93 -44
  72. data/lib/sequent/rake/migration_tasks.rb +59 -23
  73. data/lib/sequent/rake/tasks.rb +5 -2
  74. data/lib/sequent/sequent.rb +6 -1
  75. data/lib/sequent/support/database.rb +39 -17
  76. data/lib/sequent/support/view_projection.rb +6 -3
  77. data/lib/sequent/support/view_schema.rb +2 -0
  78. data/lib/sequent/support.rb +2 -0
  79. data/lib/sequent/test/command_handler_helpers.rb +39 -17
  80. data/lib/sequent/test/event_handler_helpers.rb +10 -4
  81. data/lib/sequent/test/event_stream_helpers.rb +7 -3
  82. data/lib/sequent/test/time_comparison.rb +12 -5
  83. data/lib/sequent/test.rb +2 -0
  84. data/lib/sequent/util/dry_run.rb +194 -0
  85. data/lib/sequent/util/printer.rb +6 -5
  86. data/lib/sequent/util/skip_if_already_processing.rb +21 -5
  87. data/lib/sequent/util/timer.rb +2 -0
  88. data/lib/sequent/util/util.rb +3 -0
  89. data/lib/sequent.rb +4 -0
  90. data/lib/version.rb +3 -1
  91. metadata +110 -59
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'oj'
2
4
 
3
5
  module Sequent
@@ -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(aggregate_type: aggregate_type, aggregate_id: aggregate_id, snapshot_threshold: snapshot_threshold, stream_record_id: id)
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) do
8
- yield
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
- Thread.current[:after_commit_queue] = []
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
  module Sequent
2
4
  module Core
3
5
  module Transactions
@@ -11,7 +13,6 @@ module Sequent
11
13
  yield
12
14
  end
13
15
  end
14
-
15
16
  end
16
17
  end
17
18
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'active_record_transaction_provider'
2
4
  require_relative 'no_transactions'
@@ -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 Sequent::Core::Helpers::StringSupport,
30
- Sequent::Core::Helpers::EqualSupport,
31
- Sequent::Core::Helpers::Copyable,
32
- Sequent::Core::Helpers::AttributeSupport,
33
- Sequent::Core::Helpers::ParamSupport,
34
- ActiveModel::Validations
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
- self.instance_exec(event, &block)
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 &block
35
- rescue StandardError => error
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: #{error}, #{error.inspect}")
39
+ Sequent.logger.warn("An exception was raised in an after_commit hook: #{e}, #{e.inspect}")
38
40
  else
39
- raise error
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("#{path}/#{name_underscored}/template_aggregate_command_handler.rb", "#{path}/#{name_underscored}/#{name_underscored}_command_handler.rb")
34
- FileUtils.mv("#{path}/#{name_underscored}/template_aggregate.rb", "#{path}/#{name_underscored}/#{name_underscored}.rb")
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("lib")
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
- raise TargetAlreadyExists
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 :name, :command, :attrs
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!($1, '')}
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 |child|
43
- return if child.class.to_s != "Parser::AST::Node"
44
- return child.loc.expression.end_pos if child.type.to_s == 'block'
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", "a") { |f| f << command_template.result(binding) }
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("lib")
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) || !File.exist?("#{path_to_dir}/#{name_underscored}_command_handler.rb") || !File.exist?("#{path_to_dir}/commands.rb")
76
- raise NoAggregateFound
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( File.dirname(__FILE__), 'template_command.erb' )))
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( File.dirname(__FILE__), 'template_command_handler.erb' )))
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 :name, :event, :attrs
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", "a") { |f| f << event_template.result(binding) }
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!($1, '')}
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 |child|
46
- return if child.class.to_s != "Parser::AST::Node"
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("lib")
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
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'aggregate'
4
+ require_relative 'command'
5
+ require_relative 'project'
6
+ require_relative 'event'
@@ -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
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
- ruby "2.5.1"
2
+ ruby "3.0.0"
3
3
 
4
4
  gem 'rake'
5
5
  # let's use the latest and greatest
@@ -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
@@ -1,4 +1,3 @@
1
- require_relative './generator/project'
2
- require_relative './generator/aggregate'
3
- require_relative './generator/command'
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 = "#{Sequent.configuration.migration_sql_files_directory}/#{table.table_name}_#{migration.version}.sql"
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
- unless table.table_name.end_with?("_#{migration.version}")
57
- table.table_name = "#{table.table_name}_#{migration.version}"
58
- table.reset_column_information
59
- fail MigrationError.new("Table #{table.table_name} does not exist. Did you run ViewSchema.migrate_online first?") unless table.table_exists?
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
- self.table_name == other.table_name && version == other.version
40
+ table_name == other.table_name && version == other.version
39
41
  end
40
42
 
41
43
  def hash
42
- self.table_name.hash + (version&.hash || 0)
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 '[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.'
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) to run after the migrations run. E.g. close resources
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, &after_migration_block)
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
- begin
52
- Class.const_get("Database::MigrateToVersion#{upgrade_to_version}")
53
- rescue NameError
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
 
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Migrations
3
-
4
5
  end
5
6
  end
6
7