sequent 4.0.0 → 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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequent +31 -25
  3. data/lib/notices.rb +2 -0
  4. data/lib/sequent/application_record.rb +2 -0
  5. data/lib/sequent/configuration.rb +24 -31
  6. data/lib/sequent/core/aggregate_repository.rb +17 -13
  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 +17 -9
  12. data/lib/sequent/core/command_record.rb +8 -3
  13. data/lib/sequent/core/command_service.rb +18 -18
  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 +16 -15
  18. data/lib/sequent/core/event_record.rb +7 -7
  19. data/lib/sequent/core/event_store.rb +57 -50
  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 +45 -28
  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 -5
  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 +5 -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 +2 -0
  59. data/lib/sequent/generator/project.rb +2 -0
  60. data/lib/sequent/generator/template_project/Gemfile +1 -1
  61. data/lib/sequent/generator.rb +2 -0
  62. data/lib/sequent/migrations/executor.rb +22 -13
  63. data/lib/sequent/migrations/functions.rb +5 -6
  64. data/lib/sequent/migrations/migrate_events.rb +12 -9
  65. data/lib/sequent/migrations/migrations.rb +2 -1
  66. data/lib/sequent/migrations/planner.rb +33 -23
  67. data/lib/sequent/migrations/projectors.rb +4 -3
  68. data/lib/sequent/migrations/sql.rb +2 -0
  69. data/lib/sequent/migrations/view_schema.rb +84 -45
  70. data/lib/sequent/rake/migration_tasks.rb +58 -22
  71. data/lib/sequent/rake/tasks.rb +5 -2
  72. data/lib/sequent/sequent.rb +2 -0
  73. data/lib/sequent/support/database.rb +30 -15
  74. data/lib/sequent/support/view_projection.rb +6 -3
  75. data/lib/sequent/support/view_schema.rb +2 -0
  76. data/lib/sequent/support.rb +2 -0
  77. data/lib/sequent/test/command_handler_helpers.rb +35 -17
  78. data/lib/sequent/test/event_handler_helpers.rb +10 -4
  79. data/lib/sequent/test/event_stream_helpers.rb +7 -3
  80. data/lib/sequent/test/time_comparison.rb +12 -5
  81. data/lib/sequent/test.rb +2 -0
  82. data/lib/sequent/util/dry_run.rb +11 -8
  83. data/lib/sequent/util/printer.rb +6 -5
  84. data/lib/sequent/util/skip_if_already_processing.rb +3 -1
  85. data/lib/sequent/util/timer.rb +2 -0
  86. data/lib/sequent/util/util.rb +2 -0
  87. data/lib/sequent.rb +2 -0
  88. data/lib/version.rb +3 -1
  89. metadata +81 -66
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3322a4b950e847a5818555b2718df70e2b81a8e398074309a0b58c2a8d332ce5
4
- data.tar.gz: 6136697a8a9596e999fabf3814509428b06188a0ac577fa3443a80ec190cbdd7
3
+ metadata.gz: 5e0c606e57bb36fdcaeeb102904dd450a0ff9fc2a84fdd5aff7f365a914c45d3
4
+ data.tar.gz: ea03e8a0c7ab524ff8c73fded97a726edf3dff240b95db62496496d5a6a6d580
5
5
  SHA512:
6
- metadata.gz: f8ce675ae0a16274630066192086fb8c46bb0306e9280fd4b8901500af4a7af56844c5d6c40cd0f45a87342c33a4faeb2eee48f0dc0fb05a0a09046a2dea7414
7
- data.tar.gz: e750e54d72de1c8641a513839c675adeb32fbeaa3435528a8aca755a951a7572d696e9348b7594e104f044978a0e9780f8e080ff1ad5e4ea9b7cc203fac6fee2
6
+ metadata.gz: 10f78e12826549dcd0ea3677940b5b2cdbde26fb9ecdf2f5a1bca67d5dd8405447409417b6cd277bd554c3590a2a7a3814a0918ae79ceec2b6da9510d8d1fa3f
7
+ data.tar.gz: abde6abb5638e8ad3f4f2081eb1e9eada6588d4d74994a5a62a4ef761b9737277981a5c270e75297a5e508cc611031a2e779df43b3a70b3d5a9bb0b77c81ec34
data/bin/sequent CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require_relative '../lib/sequent/generator'
3
5
 
4
6
  command = ARGV[0].to_s.strip
@@ -8,8 +10,8 @@ abort('Please specify a command. i.e. `sequent new myapp`') if ARGV[1..-1].empty
8
10
  args = ARGV[1..-1].map(&:to_s).map(&:strip)
9
11
 
10
12
  def new_project(args)
11
- _args = args.dup
12
- name = _args.shift
13
+ arguments = args.dup
14
+ name = arguments.shift
13
15
  abort('Please specify a directory name. i.e. `sequent new myapp`') if name.empty?
14
16
 
15
17
  Sequent::Generator::Project.new(name).execute
@@ -43,8 +45,8 @@ def new_project(args)
43
45
  end
44
46
 
45
47
  def generate_aggregate(args)
46
- _args = args.dup
47
- aggregate_name = _args.shift
48
+ arguments = args.dup
49
+ aggregate_name = arguments.shift
48
50
  abort('Please specify an aggregate name. i.e. `sequent g aggregate user`') unless args_valid?(aggregate_name)
49
51
 
50
52
  Sequent::Generator::Aggregate.new(aggregate_name).execute
@@ -52,41 +54,45 @@ def generate_aggregate(args)
52
54
  end
53
55
 
54
56
  def generate_command(args)
55
- _args = args.dup
56
- aggregate_name = _args.shift
57
- command_name = _args.shift
58
- attrs = _args
57
+ arguments = args.dup
58
+ aggregate_name = arguments.shift
59
+ command_name = arguments.shift
60
+ attrs = arguments
59
61
 
60
- abort('Please specify an aggregate name and command name. i.e. `sequent g command user AddUser`') unless args_valid?(aggregate_name, command_name)
62
+ unless args_valid?(aggregate_name, command_name)
63
+ abort('Please specify an aggregate name and command name. i.e. `sequent g command user AddUser`')
64
+ end
61
65
  Sequent::Generator::Command.new(aggregate_name, command_name, attrs).execute
62
66
  puts "#{command_name} command has been added to #{aggregate_name}"
63
67
  end
64
68
 
65
69
  def generate_event(args)
66
- _args = args.dup
67
- aggregate_name = _args.shift
68
- event_name = _args.shift
69
- attrs = _args
70
-
71
- abort('Please specify an aggregate name and event name. i.e. `sequent g event user AddUser`') unless args_valid?(aggregate_name, event_name)
70
+ arguments = args.dup
71
+ aggregate_name = arguments.shift
72
+ event_name = arguments.shift
73
+ attrs = arguments
74
+
75
+ abort('Please specify an aggregate name and event name. i.e. `sequent g event user AddUser`') unless args_valid?(
76
+ aggregate_name, event_name
77
+ )
72
78
  Sequent::Generator::Event.new(aggregate_name, event_name, attrs).execute
73
79
  puts "#{event_name} event has been added to #{aggregate_name}"
74
80
  end
75
81
 
76
82
  def generate(args)
77
- _args = args.dup
78
- entity = _args.shift
83
+ arguments = args.dup
84
+ entity = arguments.shift
79
85
  abort('Please specify a command. i.e. `sequent g aggregate user`') if entity.empty?
80
86
 
81
87
  case entity
82
- when 'aggregate'
83
- generate_aggregate(_args)
84
- when 'command'
85
- generate_command(_args)
86
- when 'event'
87
- generate_event(_args)
88
- else
89
- abort("Unknown argument #{entity} for `generate`. Try `sequent g aggregate user`")
88
+ when 'aggregate'
89
+ generate_aggregate(arguments)
90
+ when 'command'
91
+ generate_command(arguments)
92
+ when 'event'
93
+ generate_event(arguments)
94
+ else
95
+ abort("Unknown argument #{entity} for `generate`. Try `sequent g aggregate user`")
90
96
  end
91
97
  end
92
98
 
data/lib/notices.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is for any notices such as deprecation warnings, which should appear
2
4
  # in the logs during app boot. Adding such warnings in other places causes
3
5
  # lots of noise with duplicated messages, whereas this file is only
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
 
3
5
  module Sequent
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'core/event_store'
2
4
  require_relative 'core/command_service'
3
5
  require_relative 'core/transactions/no_transactions'
@@ -7,7 +9,6 @@ require 'logger'
7
9
 
8
10
  module Sequent
9
11
  class Configuration
10
-
11
12
  DEFAULT_VERSIONS_TABLE_NAME = 'sequent_versions'
12
13
  DEFAULT_REPLAYED_IDS_TABLE_NAME = 'sequent_replayed_ids'
13
14
 
@@ -16,7 +17,7 @@ module Sequent
16
17
  DEFAULT_DATABASE_SCHEMA_DIRECTORY = 'db'
17
18
 
18
19
  DEFAULT_VIEW_SCHEMA_NAME = 'view_schema'
19
- DEFAULT_EVENT_STORE_SCHEMA_NAME= 'sequent_schema'
20
+ DEFAULT_EVENT_STORE_SCHEMA_NAME = 'sequent_schema'
20
21
 
21
22
  MIGRATIONS_CLASS_NAME = 'Sequent::Migrations::Projectors'
22
23
 
@@ -31,41 +32,31 @@ module Sequent
31
32
 
32
33
  DEFAULT_ERROR_LOCALE_RESOLVER = -> { I18n.locale || :en }
33
34
 
34
- attr_accessor :aggregate_repository
35
-
36
- attr_accessor :event_store,
35
+ attr_accessor :aggregate_repository,
36
+ :event_store,
37
37
  :command_service,
38
38
  :event_record_class,
39
39
  :stream_record_class,
40
40
  :snapshot_event_class,
41
41
  :transaction_provider,
42
- :event_publisher
43
-
44
- attr_accessor :event_record_hooks_class
45
-
46
- attr_accessor :command_handlers,
47
- :command_filters
48
-
49
- attr_accessor :event_handlers
50
-
51
- attr_accessor :uuid_generator
52
-
53
- attr_accessor :disable_event_handlers
54
-
55
- attr_accessor :logger
56
-
57
- attr_accessor :error_locale_resolver
58
-
59
- attr_accessor :migration_sql_files_directory,
42
+ :event_publisher,
43
+ :event_record_hooks_class,
44
+ :command_handlers,
45
+ :command_filters,
46
+ :event_handlers,
47
+ :uuid_generator,
48
+ :disable_event_handlers,
49
+ :logger,
50
+ :error_locale_resolver,
51
+ :migration_sql_files_directory,
60
52
  :view_schema_name,
61
53
  :offline_replay_persistor_class,
62
54
  :online_replay_persistor_class,
63
55
  :number_of_replay_processes,
64
56
  :database_config_directory,
65
57
  :database_schema_directory,
66
- :event_store_schema_name
67
-
68
- attr_accessor :strict_check_attributes_on_apply_events
58
+ :event_store_schema_name,
59
+ :strict_check_attributes_on_apply_events
69
60
 
70
61
  attr_reader :migrations_class_name,
71
62
  :versions_table_name,
@@ -114,19 +105,19 @@ module Sequent
114
105
  self.database_schema_directory = DEFAULT_DATABASE_SCHEMA_DIRECTORY
115
106
  self.strict_check_attributes_on_apply_events = DEFAULT_STRICT_CHECK_ATTRIBUTES_ON_APPLY_EVENTS
116
107
 
117
- self.logger = Logger.new(STDOUT).tap {|l| l.level = Logger::INFO }
108
+ self.logger = Logger.new(STDOUT).tap { |l| l.level = Logger::INFO }
118
109
  self.error_locale_resolver = DEFAULT_ERROR_LOCALE_RESOLVER
119
110
  end
120
111
 
121
112
  def replayed_ids_table_name=(table_name)
122
- fail ArgumentError.new('table_name can not be nil') unless table_name
113
+ fail ArgumentError, 'table_name can not be nil' unless table_name
123
114
 
124
115
  @replayed_ids_table_name = table_name
125
116
  Sequent::Migrations::ViewSchema::ReplayedIds.table_name = table_name
126
117
  end
127
118
 
128
119
  def versions_table_name=(table_name)
129
- fail ArgumentError.new('table_name can not be nil') unless table_name
120
+ fail ArgumentError, 'table_name can not be nil' unless table_name
130
121
 
131
122
  @versions_table_name = table_name
132
123
  Sequent::Migrations::ViewSchema::Versions.table_name = table_name
@@ -134,9 +125,11 @@ module Sequent
134
125
 
135
126
  def migrations_class_name=(class_name)
136
127
  migration_class = Class.const_get(class_name)
137
- fail ArgumentError.new("#{migration_class} must extend Sequent::Migrations::Projectors") unless migration_class <= Sequent::Migrations::Projectors
128
+ unless migration_class <= Sequent::Migrations::Projectors
129
+ fail ArgumentError, "#{migration_class} must extend Sequent::Migrations::Projectors"
130
+ end
131
+
138
132
  @migrations_class_name = class_name
139
133
  end
140
-
141
134
  end
142
135
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  # Repository for aggregates.
@@ -38,7 +40,7 @@ module Sequent
38
40
  def add_aggregate(aggregate)
39
41
  existing = aggregates[aggregate.id]
40
42
  if existing && !existing.equal?(aggregate)
41
- raise NonUniqueAggregateId.new(aggregate, aggregates[aggregate.id])
43
+ fail NonUniqueAggregateId.new(aggregate, aggregates[aggregate.id])
42
44
  else
43
45
  aggregates[aggregate.id] = aggregate
44
46
  end
@@ -69,30 +71,30 @@ module Sequent
69
71
  # +aggregate_ids+ The ids of the aggregates to be loaded
70
72
  # +clazz+ Optional argument that checks if all aggregates are of type +clazz+
71
73
  def load_aggregates(aggregate_ids, clazz = nil)
72
- fail ArgumentError.new('aggregate_ids is required') unless aggregate_ids
74
+ fail ArgumentError, 'aggregate_ids is required' unless aggregate_ids
73
75
  return [] if aggregate_ids.empty?
74
76
 
75
- _aggregate_ids = aggregate_ids.uniq
76
- _aggregates = aggregates.values_at(*_aggregate_ids).compact
77
- _query_ids = _aggregate_ids - _aggregates.map(&:id)
77
+ unique_ids = aggregate_ids.uniq
78
+ result = aggregates.values_at(*unique_ids).compact
79
+ query_ids = unique_ids - result.map(&:id)
78
80
 
79
- _aggregates += Sequent.configuration.event_store.load_events_for_aggregates(_query_ids).map do |stream, events|
81
+ result += Sequent.configuration.event_store.load_events_for_aggregates(query_ids).map do |stream, events|
80
82
  aggregate_class = Class.const_get(stream.aggregate_type)
81
83
  aggregate_class.load_from_history(stream, events)
82
84
  end
83
85
 
84
- if _aggregates.count != _aggregate_ids.count
85
- missing_aggregate_ids = _aggregate_ids - _aggregates.map(&:id)
86
- raise AggregateNotFound.new(missing_aggregate_ids)
86
+ if result.count != unique_ids.count
87
+ missing_aggregate_ids = unique_ids - result.map(&:id)
88
+ fail AggregateNotFound, missing_aggregate_ids
87
89
  end
88
90
 
89
91
  if clazz
90
- _aggregates.each do |aggregate|
91
- raise TypeError, "#{aggregate.class} is not a #{clazz}" if !(aggregate.class <= clazz)
92
+ result.each do |aggregate|
93
+ fail TypeError, "#{aggregate.class} is not a #{clazz}" unless aggregate.class <= clazz
92
94
  end
93
95
  end
94
96
 
95
- _aggregates.map do |aggregate|
97
+ result.map do |aggregate|
96
98
  aggregates[aggregate.id] = aggregate
97
99
  end
98
100
  end
@@ -119,8 +121,9 @@ module Sequent
119
121
  def commit(command)
120
122
  updated_aggregates = aggregates.values.reject { |x| x.uncommitted_events.empty? }
121
123
  return if updated_aggregates.empty?
124
+
122
125
  streams_with_events = updated_aggregates.map do |aggregate|
123
- [ aggregate.event_stream, aggregate.uncommitted_events ]
126
+ [aggregate.event_stream, aggregate.uncommitted_events]
124
127
  end
125
128
  updated_aggregates.each(&:clear_events)
126
129
  store_events command, streams_with_events
@@ -136,6 +139,7 @@ module Sequent
136
139
  # A +HasUncommittedEvents+ is raised when there are uncommitted_events in the Unit of Work.
137
140
  def clear!
138
141
  fail HasUncommittedEvents if aggregates.values.any? { |x| !x.uncommitted_events.empty? }
142
+
139
143
  clear
140
144
  end
141
145
 
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require_relative 'helpers/message_handler'
3
5
  require_relative 'helpers/autoset_attributes'
4
6
  require_relative 'stream_record'
7
+ require_relative 'aggregate_roots'
5
8
 
6
9
  module Sequent
7
10
  module Core
8
-
9
11
  module SnapshotConfiguration
10
12
  module ClassMethods
11
13
  ##
@@ -40,13 +42,20 @@ module Sequent
40
42
 
41
43
  attr_reader :id, :uncommitted_events, :sequence_number, :event_stream
42
44
 
45
+ def self.inherited(subclass)
46
+ super
47
+ AggregateRoots << subclass
48
+ end
49
+
43
50
  def self.load_from_history(stream, events)
44
51
  first, *rest = events
45
52
  if first.is_a? SnapshotEvent
53
+ # rubocop:disable Security/MarshalLoad
46
54
  aggregate_root = Marshal.load(Base64.decode64(first.data))
55
+ # rubocop:enable Security/MarshalLoad
47
56
  rest.each { |x| aggregate_root.apply_event(x) }
48
57
  else
49
- aggregate_root = allocate() # allocate without calling new
58
+ aggregate_root = allocate # allocate without calling new
50
59
  aggregate_root.load_from_history(stream, events)
51
60
  end
52
61
  aggregate_root
@@ -62,7 +71,8 @@ module Sequent
62
71
  end
63
72
 
64
73
  def load_from_history(stream, events)
65
- raise "Empty history" if events.empty?
74
+ fail 'Empty history' if events.empty?
75
+
66
76
  @id = events.first.aggregate_id
67
77
  @uncommitted_events = []
68
78
  @sequence_number = 1
@@ -100,7 +110,7 @@ module Sequent
100
110
  # apply InvoiceSentEvent, send_date: DateTime.now
101
111
  # end
102
112
  #
103
- def apply(event, params={})
113
+ def apply(event, params = {})
104
114
  event = build_event(event, params) if event.is_a?(Class)
105
115
  apply_event(event)
106
116
  @uncommitted_events << event
@@ -123,12 +133,11 @@ module Sequent
123
133
  if args.empty?
124
134
  apply event_class
125
135
  elsif self.class
126
- .event_attribute_keys(event_class)
127
- .any? { |k| instance_variable_get(:"@#{k.to_s}") != args[k.to_sym] }
136
+ .event_attribute_keys(event_class)
137
+ .any? { |k| instance_variable_get(:"@#{k}") != args[k.to_sym] }
128
138
  apply event_class, args
129
139
  end
130
140
  end
131
-
132
141
  end
133
142
  end
134
143
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequent
4
+ module Core
5
+ #
6
+ # Utility class containing all subclasses of AggregateRoot
7
+ #
8
+ class AggregateRoots
9
+ class << self
10
+ def aggregate_roots
11
+ @aggregate_roots ||= []
12
+ end
13
+
14
+ def all
15
+ aggregate_roots
16
+ end
17
+
18
+ def <<(aggregate_root)
19
+ aggregate_roots << aggregate_root
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
-
4
5
  ##
5
6
  # Take up to `limit` snapshots when needed. Throws `:done` when done.
6
7
  #
7
- class SnapshotCommand < Sequent::Core::BaseCommand
8
+ class SnapshotCommand < Sequent::Core::BaseCommand
8
9
  attrs limit: Integer
9
10
  end
10
11
 
@@ -14,9 +15,11 @@ module Sequent
14
15
  end
15
16
 
16
17
  class AggregateSnapshotter < BaseCommandHandler
17
-
18
18
  on SnapshotCommand do |command|
19
- aggregate_ids = repository.event_store.aggregates_that_need_snapshots(@last_aggregate_id, command.limit)
19
+ aggregate_ids = Sequent.configuration.event_store.aggregates_that_need_snapshots(
20
+ @last_aggregate_id,
21
+ command.limit,
22
+ )
20
23
  aggregate_ids.each do |aggregate_id|
21
24
  take_snapshot!(aggregate_id)
22
25
  end
@@ -32,7 +35,7 @@ module Sequent
32
35
  aggregate = repository.load_aggregate(aggregate_id)
33
36
  Sequent.logger.info "Taking snapshot for aggregate #{aggregate}"
34
37
  aggregate.take_snapshot!
35
- rescue => e
38
+ rescue StandardError => e
36
39
  Sequent.logger.error("Failed to take snapshot for aggregate #{aggregate_id}: #{e}, #{e.inspect}")
37
40
  end
38
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'helpers/message_handler'
2
4
  require_relative 'helpers/uuid_helper'
3
5
 
@@ -17,8 +19,8 @@ module Sequent
17
19
  # end
18
20
  # end
19
21
  class BaseCommandHandler
20
- include Sequent::Core::Helpers::MessageHandler,
21
- Sequent::Core::Helpers::UuidHelper
22
+ include Sequent::Core::Helpers::UuidHelper
23
+ include Sequent::Core::Helpers::MessageHandler
22
24
 
23
25
  protected
24
26
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'helpers/copyable'
2
4
  require_relative 'helpers/attribute_support'
3
5
  require_relative 'helpers/uuid_helper'
@@ -17,13 +19,13 @@ module Sequent
17
19
  # BaseCommand uses `ActiveModel::Validations` for
18
20
  # validations
19
21
  class BaseCommand
20
- include ActiveModel::Validations,
21
- Sequent::Core::Helpers::Copyable,
22
- Sequent::Core::Helpers::AttributeSupport,
23
- Sequent::Core::Helpers::UuidHelper,
24
- Sequent::Core::Helpers::EqualSupport,
25
- Sequent::Core::Helpers::ParamSupport,
26
- Sequent::Core::Helpers::Mergable
22
+ include Sequent::Core::Helpers::Mergable
23
+ include Sequent::Core::Helpers::ParamSupport
24
+ include Sequent::Core::Helpers::EqualSupport
25
+ include Sequent::Core::Helpers::UuidHelper
26
+ include Sequent::Core::Helpers::AttributeSupport
27
+ include Sequent::Core::Helpers::Copyable
28
+ include ActiveModel::Validations
27
29
  include ActiveModel::Validations::Callbacks
28
30
  include Sequent::Core::Helpers::TypeConversionSupport
29
31
 
@@ -35,6 +37,7 @@ module Sequent
35
37
  end
36
38
 
37
39
  def self.inherited(subclass)
40
+ super
38
41
  Commands << subclass
39
42
  end
40
43
  end
@@ -44,7 +47,11 @@ module Sequent
44
47
  included do
45
48
  attrs sequence_number: Integer
46
49
  validates_presence_of :sequence_number
47
- validates_numericality_of :sequence_number, only_integer: true, allow_nil: true, allow_blank: true, greater_than: 0
50
+ validates_numericality_of :sequence_number,
51
+ only_integer: true,
52
+ allow_nil: true,
53
+ allow_blank: true,
54
+ greater_than: 0
48
55
  end
49
56
  end
50
57
 
@@ -85,7 +92,8 @@ module Sequent
85
92
  attrs aggregate_id: String, user_id: String, event_aggregate_id: String, event_sequence_number: Integer
86
93
 
87
94
  def initialize(args = {})
88
- raise ArgumentError, "Missing aggregate_id" if args[:aggregate_id].nil?
95
+ fail ArgumentError, 'Missing aggregate_id' if args[:aggregate_id].nil?
96
+
89
97
  super
90
98
  end
91
99
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
  require_relative 'sequent_oj'
3
5
 
4
6
  module Sequent
5
7
  module Core
6
-
7
8
  module SerializesCommand
8
9
  def command
9
10
  args = Sequent::Core::Oj.strict_load(command_json)
@@ -21,7 +22,10 @@ module Sequent
21
22
  # this should be moved to a configurable CommandSerializer
22
23
  self.organization_id = command.organization_id if serialize_attribute?(command, :organization_id)
23
24
  self.event_aggregate_id = command.event_aggregate_id if serialize_attribute?(command, :event_aggregate_id)
24
- self.event_sequence_number = command.event_sequence_number if serialize_attribute?(command, :event_sequence_number)
25
+ self.event_sequence_number = command.event_sequence_number if serialize_attribute?(
26
+ command,
27
+ :event_sequence_number,
28
+ )
25
29
  end
26
30
 
27
31
  private
@@ -35,7 +39,7 @@ module Sequent
35
39
  class CommandRecord < Sequent::ApplicationRecord
36
40
  include SerializesCommand
37
41
 
38
- self.table_name = "command_records"
42
+ self.table_name = 'command_records'
39
43
 
40
44
  has_many :event_records
41
45
 
@@ -58,6 +62,7 @@ module Sequent
58
62
 
59
63
  def find_origin(record)
60
64
  return find_origin(record.parent) if record.parent.present?
65
+
61
66
  record
62
67
  end
63
68
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'transactions/no_transactions'
2
4
  require_relative 'current_event'
3
5
 
@@ -39,7 +41,7 @@ module Sequent
39
41
  end
40
42
 
41
43
  def remove_event_handler(clazz)
42
- warn "[DEPRECATION] `remove_event_handler` is deprecated"
44
+ warn '[DEPRECATION] `remove_event_handler` is deprecated'
43
45
  event_store.remove_event_handler(clazz)
44
46
  end
45
47
 
@@ -47,17 +49,13 @@ module Sequent
47
49
 
48
50
  def process_commands
49
51
  Sequent::Util.skip_if_already_processing(:command_service_process_commands) do
50
- begin
51
- transaction_provider.transactional do
52
- while(!command_queue.empty?) do
53
- process_command(command_queue.pop)
54
- end
55
- Sequent::Util.done_processing(:command_service_process_commands)
56
- end
57
- ensure
58
- command_queue.clear
59
- repository.clear
52
+ transaction_provider.transactional do
53
+ process_command(command_queue.pop) until command_queue.empty?
54
+ Sequent::Util.done_processing(:command_service_process_commands)
60
55
  end
56
+ ensure
57
+ command_queue.clear
58
+ repository.clear
61
59
  end
62
60
  end
63
61
 
@@ -68,12 +66,12 @@ module Sequent
68
66
 
69
67
  filters.each { |filter| filter.execute(command) }
70
68
 
71
- I18n.with_locale(Sequent.configuration.error_locale_resolver.call) do
72
- raise CommandNotValid.new(command) unless command.valid?
73
- end
69
+ fail CommandNotValid, command unless command.valid?
74
70
 
75
71
  parsed_command = command.parse_attrs_to_correct_types
76
- command_handlers.select { |h| h.class.handles_message?(parsed_command) }.each { |h| h.handle_message parsed_command }
72
+ command_handlers.select do |h|
73
+ h.class.handles_message?(parsed_command)
74
+ end.each { |h| h.handle_message parsed_command }
77
75
  repository.commit(parsed_command)
78
76
  end
79
77
 
@@ -108,12 +106,14 @@ module Sequent
108
106
 
109
107
  def initialize(command)
110
108
  @command = command
111
- msg = @command.respond_to?(:aggregate_id) ? " #{@command.aggregate_id}" : ""
112
- super "Invalid command #{@command.class.to_s}#{msg}, errors: #{@command.validation_errors}"
109
+ msg = @command.respond_to?(:aggregate_id) ? " #{@command.aggregate_id}" : ''
110
+ super "Invalid command #{@command.class}#{msg}, errors: #{@command.validation_errors}"
113
111
  end
114
112
 
115
113
  def errors(prefix = nil)
116
- @command.validation_errors(prefix)
114
+ I18n.with_locale(Sequent.configuration.error_locale_resolver.call) do
115
+ @command.validation_errors(prefix)
116
+ end
117
117
  end
118
118
 
119
119
  def errors_with_command_prefix
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'sequent_oj'
2
4
  require_relative 'helpers/helpers'
3
5
  require_relative 'persistors/persistors'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  class CurrentEvent