sequent 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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