sequent 6.0.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sequent/configuration.rb +57 -1
- data/lib/sequent/core/aggregate_repository.rb +2 -2
- data/lib/sequent/core/aggregate_snapshotter.rb +4 -0
- data/lib/sequent/core/base_command_handler.rb +5 -0
- data/lib/sequent/core/core.rb +1 -1
- data/lib/sequent/core/event.rb +2 -2
- data/lib/sequent/core/event_store.rb +16 -16
- data/lib/sequent/core/helpers/attribute_support.rb +7 -7
- data/lib/sequent/core/helpers/message_dispatcher.rb +4 -1
- data/lib/sequent/core/projector.rb +4 -0
- data/lib/sequent/core/transactions/active_record_transaction_provider.rb +2 -1
- data/lib/sequent/core/workflow.rb +4 -0
- data/lib/sequent/migrations/migrations.rb +0 -1
- data/lib/sequent/migrations/planner.rb +4 -4
- data/lib/sequent/migrations/view_schema.rb +2 -2
- data/lib/sequent/sequent.rb +4 -11
- data/lib/sequent/support/database.rb +3 -1
- data/lib/version.rb +1 -1
- metadata +6 -7
- data/lib/sequent/migrations/migrate_events.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2271f62c7221e3eb21eb7707ad2f7df52b9adeae3154c0856b860133af872457
|
4
|
+
data.tar.gz: dc3b99bc7c06957f98f5c45be5cff4082ae0d9cca493a9ea3431fc14eea67e08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 150cff9d3a13c1b230dfb71f6897f740c1c4c5ac3448dbb0fd334858229ae1bf3ff67e1bdad897145e5bc0a2a5cd70a31a430e93939857ba753f2f9895a84fa1
|
7
|
+
data.tar.gz: ae8ae17080b36ed4b60f361aefb3d9b816b12b037f9eb4022c00969c2b9ce2c78cdfe6f4c67358d02c376ec37479d5951ad10e92944ba4b3e6b056b3fd8c2b5e
|
@@ -36,6 +36,7 @@ module Sequent
|
|
36
36
|
|
37
37
|
attr_accessor :aggregate_repository,
|
38
38
|
:event_store,
|
39
|
+
:event_store_cache_event_types,
|
39
40
|
:command_service,
|
40
41
|
:event_record_class,
|
41
42
|
:stream_record_class,
|
@@ -63,7 +64,8 @@ module Sequent
|
|
63
64
|
:enable_multiple_database_support,
|
64
65
|
:primary_database_role,
|
65
66
|
:primary_database_key,
|
66
|
-
:time_precision
|
67
|
+
:time_precision,
|
68
|
+
:enable_autoregistration
|
67
69
|
|
68
70
|
attr_reader :migrations_class_name,
|
69
71
|
:versions_table_name,
|
@@ -73,10 +75,13 @@ module Sequent
|
|
73
75
|
@instance ||= new
|
74
76
|
end
|
75
77
|
|
78
|
+
# Create a new instance of Configuration
|
76
79
|
def self.reset
|
77
80
|
@instance = new
|
78
81
|
end
|
79
82
|
|
83
|
+
# Restore the given Configuration
|
84
|
+
# @param configuration [Sequent::Configuration]
|
80
85
|
def self.restore(configuration)
|
81
86
|
@instance = configuration
|
82
87
|
end
|
@@ -88,6 +93,7 @@ module Sequent
|
|
88
93
|
self.command_middleware = Sequent::Core::Middleware::Chain.new
|
89
94
|
|
90
95
|
self.aggregate_repository = Sequent::Core::AggregateRepository.new
|
96
|
+
self.event_store_cache_event_types = true
|
91
97
|
self.event_store = Sequent::Core::EventStore.new
|
92
98
|
self.command_service = Sequent::Core::CommandService.new
|
93
99
|
self.event_record_class = Sequent::Core::EventRecord
|
@@ -121,6 +127,8 @@ module Sequent
|
|
121
127
|
self.primary_database_key = :primary
|
122
128
|
|
123
129
|
self.time_precision = DEFAULT_TIME_PRECISION
|
130
|
+
|
131
|
+
self.enable_autoregistration = false
|
124
132
|
end
|
125
133
|
|
126
134
|
def can_use_multiple_databases?
|
@@ -149,5 +157,53 @@ module Sequent
|
|
149
157
|
|
150
158
|
@migrations_class_name = class_name
|
151
159
|
end
|
160
|
+
|
161
|
+
def autoregister!
|
162
|
+
return unless enable_autoregistration
|
163
|
+
|
164
|
+
# Only autoregister the AggregateSnapshotter if the autoregistration is enabled
|
165
|
+
Sequent::Core::AggregateSnapshotter.skip_autoregister = false
|
166
|
+
|
167
|
+
Rails.autoloaders.main.eager_load(force: true) if defined?(Rails)
|
168
|
+
|
169
|
+
self.class.instance.command_handlers ||= []
|
170
|
+
for_each_autoregisterable_descenant_of(Sequent::CommandHandler) do |command_handler_class|
|
171
|
+
Sequent.logger.debug("[Configuration] Autoregistering CommandHandler #{command_handler_class}")
|
172
|
+
self.class.instance.command_handlers << command_handler_class.new
|
173
|
+
end
|
174
|
+
|
175
|
+
self.class.instance.event_handlers ||= []
|
176
|
+
for_each_autoregisterable_descenant_of(Sequent::Projector) do |projector_class|
|
177
|
+
Sequent.logger.debug("[Configuration] Autoregistering Projector #{projector_class}")
|
178
|
+
self.class.instance.event_handlers << projector_class.new
|
179
|
+
end
|
180
|
+
|
181
|
+
for_each_autoregisterable_descenant_of(Sequent::Workflow) do |workflow_class|
|
182
|
+
Sequent.logger.debug("[Configuration] Autoregistering Workflow #{workflow_class}")
|
183
|
+
self.class.instance.event_handlers << workflow_class.new
|
184
|
+
end
|
185
|
+
|
186
|
+
self.class.instance.command_handlers.map(&:class).tally.each do |(clazz, count)|
|
187
|
+
if count > 1
|
188
|
+
fail "CommandHandler #{clazz} is registered #{count} times. A CommandHandler can only be registered once"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
self.class.instance.event_handlers.map(&:class).tally.each do |(clazz, count)|
|
193
|
+
if count > 1
|
194
|
+
fail "EventHandler #{clazz} is registered #{count} times. An EventHandler can only be registered once"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def for_each_autoregisterable_descenant_of(clazz, &block)
|
202
|
+
clazz
|
203
|
+
.descendants
|
204
|
+
.reject(&:abstract_class)
|
205
|
+
.reject(&:skip_autoregister)
|
206
|
+
.each(&block)
|
207
|
+
end
|
152
208
|
end
|
153
209
|
end
|
@@ -79,8 +79,8 @@ module Sequent
|
|
79
79
|
.configuration
|
80
80
|
.event_store
|
81
81
|
.stream_events_for_aggregate(aggregate_id, load_until: load_until) do |event_stream|
|
82
|
-
|
83
|
-
|
82
|
+
aggregate.stream_from_history(event_stream)
|
83
|
+
end
|
84
84
|
|
85
85
|
if clazz
|
86
86
|
fail TypeError, "#{aggregate.class} is not a #{clazz}" unless aggregate.class <= clazz
|
@@ -15,6 +15,10 @@ module Sequent
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class AggregateSnapshotter < BaseCommandHandler
|
18
|
+
# By default skip autoregistering this CommandHandler.
|
19
|
+
# The AggregateSnapshotter is only autoregistered if autoregistration is enabled.
|
20
|
+
self.skip_autoregister = true
|
21
|
+
|
18
22
|
on SnapshotCommand do |command|
|
19
23
|
aggregate_ids = Sequent.configuration.event_store.aggregates_that_need_snapshots(
|
20
24
|
@last_aggregate_id,
|
@@ -21,6 +21,11 @@ module Sequent
|
|
21
21
|
class BaseCommandHandler
|
22
22
|
include Sequent::Core::Helpers::UuidHelper
|
23
23
|
include Sequent::Core::Helpers::MessageHandler
|
24
|
+
extend ActiveSupport::DescendantsTracker
|
25
|
+
|
26
|
+
class << self
|
27
|
+
attr_accessor :abstract_class, :skip_autoregister
|
28
|
+
end
|
24
29
|
|
25
30
|
protected
|
26
31
|
|
data/lib/sequent/core/core.rb
CHANGED
@@ -16,7 +16,7 @@ require_relative 'projector'
|
|
16
16
|
require_relative 'event_store'
|
17
17
|
require_relative 'event_record'
|
18
18
|
require_relative 'command_record'
|
19
|
-
require_relative 'aggregate_snapshotter'
|
20
19
|
require_relative 'workflow'
|
21
20
|
require_relative 'random_uuid_generator'
|
22
21
|
require_relative 'event_publisher'
|
22
|
+
require_relative 'aggregate_snapshotter'
|
data/lib/sequent/core/event.rb
CHANGED
@@ -29,8 +29,8 @@ module Sequent
|
|
29
29
|
.reject { |k| payload_variables.include?(k) }
|
30
30
|
.select { |k| self.class.types.keys.include?(to_attribute_name(k)) }
|
31
31
|
.each do |k|
|
32
|
-
|
33
|
-
|
32
|
+
result[k.to_s[1..-1].to_sym] = instance_variable_get(k)
|
33
|
+
end
|
34
34
|
result
|
35
35
|
end
|
36
36
|
|
@@ -35,14 +35,6 @@ module Sequent
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def initialize(cache_event_types: true)
|
39
|
-
@event_types = if cache_event_types
|
40
|
-
ThreadSafe::Cache.new
|
41
|
-
else
|
42
|
-
NoEventTypesCache.new
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
38
|
##
|
47
39
|
# Stores the events in the EventStore and publishes the events
|
48
40
|
# to the registered event_handlers.
|
@@ -114,13 +106,13 @@ module Sequent
|
|
114
106
|
events
|
115
107
|
.group_by(&:aggregate_id)
|
116
108
|
.map do |aggregate_id, es|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
109
|
+
[
|
110
|
+
streams.find do |stream_record|
|
111
|
+
stream_record.aggregate_id == aggregate_id
|
112
|
+
end.event_stream,
|
113
|
+
es,
|
114
|
+
]
|
115
|
+
end
|
124
116
|
end
|
125
117
|
|
126
118
|
def aggregate_query(aggregate_id)
|
@@ -217,6 +209,14 @@ module Sequent
|
|
217
209
|
|
218
210
|
private
|
219
211
|
|
212
|
+
def event_types
|
213
|
+
@event_types = if Sequent.configuration.event_store_cache_event_types
|
214
|
+
ThreadSafe::Cache.new
|
215
|
+
else
|
216
|
+
NoEventTypesCache.new
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
220
|
def column_names
|
221
221
|
@column_names ||= Sequent
|
222
222
|
.configuration
|
@@ -238,7 +238,7 @@ module Sequent
|
|
238
238
|
end
|
239
239
|
|
240
240
|
def resolve_event_type(event_type)
|
241
|
-
|
241
|
+
event_types.fetch_or_store(event_type) { |k| Class.const_get(k) }
|
242
242
|
end
|
243
243
|
|
244
244
|
def publish_events(events)
|
@@ -79,8 +79,8 @@ module Sequent
|
|
79
79
|
super if defined?(super)
|
80
80
|
ensure_known_attributes(attrs)
|
81
81
|
#{@types.map do |attribute, _|
|
82
|
-
|
83
|
-
|
82
|
+
"@#{attribute} = attrs[:#{attribute}]"
|
83
|
+
end.join("\n ")}
|
84
84
|
self
|
85
85
|
end
|
86
86
|
EOS
|
@@ -89,8 +89,8 @@ EOS
|
|
89
89
|
def update_all_attributes_from_json(attrs)
|
90
90
|
super if defined?(super)
|
91
91
|
#{@types.map do |attribute, type|
|
92
|
-
|
93
|
-
|
92
|
+
"@#{attribute} = #{type}.deserialize_from_json(attrs['#{attribute}'])"
|
93
|
+
end.join("\n ")}
|
94
94
|
end
|
95
95
|
EOS
|
96
96
|
end
|
@@ -206,10 +206,10 @@ EOS
|
|
206
206
|
value
|
207
207
|
.select { |val| val.respond_to?(:validation_errors) }
|
208
208
|
.each_with_index do |val, index|
|
209
|
-
|
210
|
-
|
209
|
+
val.validation_errors.each do |k, v|
|
210
|
+
result["#{field[0]}_#{index}_#{k}".to_sym] = v
|
211
|
+
end
|
211
212
|
end
|
212
|
-
end
|
213
213
|
end
|
214
214
|
end
|
215
215
|
prefix ? HashWithIndifferentAccess[result.map { |k, v| ["#{prefix}_#{k}", v] }] : result
|
@@ -12,7 +12,10 @@ module Sequent
|
|
12
12
|
def dispatch_message(message)
|
13
13
|
@message_router
|
14
14
|
.match_message(message)
|
15
|
-
.each
|
15
|
+
.each do |handler|
|
16
|
+
Sequent.logger.debug("[MessageDispatcher] Handler #{@context.class} handling #{message.class}")
|
17
|
+
@context.instance_exec(message, &handler)
|
18
|
+
end
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -88,6 +88,10 @@ module Sequent
|
|
88
88
|
include Migratable
|
89
89
|
extend ActiveSupport::DescendantsTracker
|
90
90
|
|
91
|
+
class << self
|
92
|
+
attr_accessor :abstract_class, :skip_autoregister
|
93
|
+
end
|
94
|
+
|
91
95
|
def initialize(persistor = Sequent::Core::Persistors::ActiveRecordPersistor.new)
|
92
96
|
ensure_valid!
|
93
97
|
@persistor = persistor
|
@@ -30,8 +30,9 @@ module Sequent
|
|
30
30
|
#
|
31
31
|
class ActiveRecordTransactionProvider
|
32
32
|
def transactional(&block)
|
33
|
-
Sequent::ApplicationRecord.transaction(requires_new: true, &block)
|
33
|
+
result = Sequent::ApplicationRecord.transaction(requires_new: true, &block)
|
34
34
|
after_commit_queue.pop.call until after_commit_queue.empty?
|
35
|
+
result
|
35
36
|
ensure
|
36
37
|
clear_after_commit_queue
|
37
38
|
end
|
@@ -69,10 +69,10 @@ module Sequent
|
|
69
69
|
.each_with_index
|
70
70
|
.select { |migration, _index| migration.instance_of?(AlterTable) }
|
71
71
|
.select do |migration, index|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
migrations
|
73
|
+
.slice((index + 1)..-1)
|
74
|
+
.find { |m| m.instance_of?(ReplayTable) && m.record_class == migration.record_class }
|
75
|
+
end.map(&:first)
|
76
76
|
end
|
77
77
|
|
78
78
|
def remove_redundancy(grouped_migrations)
|
@@ -387,8 +387,8 @@ module Sequent
|
|
387
387
|
unless ids.empty?
|
388
388
|
exec_sql(
|
389
389
|
"insert into #{ReplayedIds.table_name} (event_id) values #{ids.map do |id|
|
390
|
-
|
391
|
-
|
390
|
+
"(#{id})"
|
391
|
+
end.join(',')}",
|
392
392
|
)
|
393
393
|
end
|
394
394
|
Sequent::Core::EventStore::PRINT_PROGRESS[progress, done, ids] if progress > 0
|
data/lib/sequent/sequent.rb
CHANGED
@@ -22,21 +22,14 @@ module Sequent
|
|
22
22
|
# A minimal setup could look like this:
|
23
23
|
#
|
24
24
|
# Sequent.configure do |config|
|
25
|
-
# config.
|
26
|
-
# MyProjector.new,
|
27
|
-
# AnotherProjector.new,
|
28
|
-
# MyWorkflow.new,
|
29
|
-
# ]
|
30
|
-
#
|
31
|
-
# config.command_handlers = [
|
32
|
-
# MyCommandHandler.new,
|
33
|
-
# ]
|
34
|
-
#
|
25
|
+
# config.enable_autoregistration = true
|
35
26
|
# end
|
36
27
|
#
|
37
|
-
#
|
28
|
+
# Calling configure a second time will create a new configuration
|
38
29
|
def self.configure
|
30
|
+
Configuration.reset
|
39
31
|
yield Configuration.instance
|
32
|
+
Configuration.instance.autoregister!
|
40
33
|
end
|
41
34
|
|
42
35
|
def self.configuration
|
@@ -53,7 +53,9 @@ module Sequent
|
|
53
53
|
db_config = db_config.deep_merge(
|
54
54
|
Sequent.configuration.primary_database_key => db_config_overrides,
|
55
55
|
).stringify_keys
|
56
|
-
|
56
|
+
if Gem.loaded_specs['activerecord'].version < Gem::Version.create('7.1.0')
|
57
|
+
ActiveRecord.legacy_connection_handling = false
|
58
|
+
end
|
57
59
|
ActiveRecord::Base.configurations = db_config.stringify_keys
|
58
60
|
ActiveRecord::Base.connects_to database: {
|
59
61
|
Sequent.configuration.primary_database_role => Sequent.configuration.primary_database_key,
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Vonk
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2023-
|
15
|
+
date: 2023-11-02 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activemodel
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: '5.0'
|
24
24
|
- - "<"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '7.
|
26
|
+
version: '7.2'
|
27
27
|
type: :runtime
|
28
28
|
prerelease: false
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: '5.0'
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '7.
|
36
|
+
version: '7.2'
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: activerecord
|
39
39
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '5.0'
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '7.
|
46
|
+
version: '7.2'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
version: '5.0'
|
54
54
|
- - "<"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '7.
|
56
|
+
version: '7.2'
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: bcrypt
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -430,7 +430,6 @@ files:
|
|
430
430
|
- lib/sequent/generator/template_project/spec/spec_helper.rb
|
431
431
|
- lib/sequent/migrations/executor.rb
|
432
432
|
- lib/sequent/migrations/functions.rb
|
433
|
-
- lib/sequent/migrations/migrate_events.rb
|
434
433
|
- lib/sequent/migrations/migrations.rb
|
435
434
|
- lib/sequent/migrations/planner.rb
|
436
435
|
- lib/sequent/migrations/projectors.rb
|
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
##
|
4
|
-
# When you need to upgrade the event store based on information of the previous schema version
|
5
|
-
# this is the place you need to implement a migration.
|
6
|
-
# Examples are: corrupt events (due to insufficient testing for instance...)
|
7
|
-
# or adding extra events to the event stream if a new concept is introduced.
|
8
|
-
#
|
9
|
-
# To implement a migration you should create a class according to the following contract:
|
10
|
-
# module Database
|
11
|
-
# class MigrateToVersionXXX
|
12
|
-
# def initialize(env)
|
13
|
-
# @env = env
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# def migrate
|
17
|
-
# # your migration code here...
|
18
|
-
# end
|
19
|
-
# end
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
module Sequent
|
23
|
-
module Migrations
|
24
|
-
class MigrateEvents
|
25
|
-
##
|
26
|
-
# @param env The string representing the current environment. E.g. "development", "production"
|
27
|
-
def initialize(env)
|
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
|
31
|
-
@env = env
|
32
|
-
end
|
33
|
-
|
34
|
-
##
|
35
|
-
#
|
36
|
-
# @param current_version The current version of the application. E.g. 10
|
37
|
-
# @param new_version The version to migrate to. E.g. 11
|
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
|
40
|
-
#
|
41
|
-
def execute_migrations(current_version, new_version)
|
42
|
-
migrations(current_version, new_version).each do |migration_class|
|
43
|
-
migration = migration_class.new(@env)
|
44
|
-
begin
|
45
|
-
migration.migrate
|
46
|
-
ensure
|
47
|
-
yield(migration.version) if block_given?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def migrations(current_version, new_version)
|
53
|
-
return [] if current_version == 0
|
54
|
-
|
55
|
-
((current_version + 1)..new_version).map do |upgrade_to_version|
|
56
|
-
Class.const_get("Database::MigrateToVersion#{upgrade_to_version}")
|
57
|
-
rescue NameError
|
58
|
-
nil
|
59
|
-
end.compact
|
60
|
-
end
|
61
|
-
|
62
|
-
def has_migrations?(current_version, new_version)
|
63
|
-
migrations(current_version, new_version).any?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|