sequent 5.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/sequent +1 -1
- data/db/sequent_schema.rb +3 -3
- data/lib/sequent/configuration.rb +19 -1
- data/lib/sequent/core/aggregate_root.rb +2 -6
- data/lib/sequent/core/aggregate_roots.rb +2 -6
- data/lib/sequent/core/command.rb +8 -12
- data/lib/sequent/core/command_service.rb +13 -2
- data/lib/sequent/core/core.rb +1 -0
- data/lib/sequent/core/event.rb +2 -2
- data/lib/sequent/core/event_store.rb +15 -2
- data/lib/sequent/core/ext/ext.rb +17 -0
- data/lib/sequent/core/helpers/attribute_support.rb +1 -0
- data/lib/sequent/core/helpers/default_validators.rb +3 -0
- data/lib/sequent/core/helpers/param_support.rb +2 -0
- data/lib/sequent/core/helpers/string_to_value_parsers.rb +5 -0
- data/lib/sequent/core/helpers/time_validator.rb +23 -0
- data/lib/sequent/core/helpers/value_validators.rb +11 -0
- data/lib/sequent/core/middleware/chain.rb +37 -0
- data/lib/sequent/core/middleware/middleware.rb +3 -0
- data/lib/sequent/core/projector.rb +3 -11
- data/lib/sequent/core/workflow.rb +3 -11
- data/lib/sequent/generator/template_project/Rakefile +2 -2
- data/lib/sequent/generator/template_project/db/sequent_schema.rb +3 -3
- data/lib/sequent/generator/template_project/spec/spec_helper.rb +1 -1
- data/lib/sequent/migrations/migrations.rb +1 -0
- data/lib/sequent/migrations/projectors.rb +2 -2
- data/lib/sequent/migrations/sequent_schema.rb +40 -0
- data/lib/sequent/migrations/view_schema.rb +39 -3
- data/lib/sequent/rake/migration_tasks.rb +36 -33
- data/lib/sequent/support/database.rb +29 -13
- data/lib/sequent/test/command_handler_helpers.rb +1 -1
- data/lib/sequent/test/database_helpers.rb +20 -0
- data/lib/sequent/test/time_comparison.rb +2 -5
- data/lib/sequent/test/{event_handler_helpers.rb → workflow_helpers.rb} +24 -10
- data/lib/sequent/test.rb +2 -1
- data/lib/sequent/util/dry_run.rb +1 -1
- data/lib/version.rb +1 -1
- metadata +22 -12
- data/lib/sequent/rake/tasks.rb +0 -121
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e420a9289f17d8552364afd49977cdb8cdbc0b37f39445a0a7ce310f9c1a180f
|
4
|
+
data.tar.gz: 116144ee36558de52bc381b8e99e13d44aad3bedda6d531b380d93b3d7b96445
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 434eb99e05dda79479a8c8a6529a0d2b3bfa2fc3e02c7143ad314f27a2140d33c6a01f1d3d1a147892b1dafefcd899bed8bde9cbe3b0c76520f3561b5dfa2b05
|
7
|
+
data.tar.gz: 6fd8a9df8cac32aaad084fd2b472caab478c13840da563b8d3a8e8c9e1d86c32bfc3d43a7e8d7031386a36a127c9be6648d3baaa241dcfb45d92f3d7721a9d4d
|
data/bin/sequent
CHANGED
@@ -31,7 +31,7 @@ def new_project(args)
|
|
31
31
|
bundle exec rake sequent:migrate:offline
|
32
32
|
|
33
33
|
Run the example specs:
|
34
|
-
|
34
|
+
SEQUENT_ENV=test bundle exec rake sequent:db:create
|
35
35
|
bundle exec rspec spec
|
36
36
|
|
37
37
|
To generate new aggregates use:
|
data/db/sequent_schema.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
ActiveRecord::Schema.define do
|
2
2
|
|
3
3
|
create_table "event_records", :force => true do |t|
|
4
|
-
t.
|
4
|
+
t.uuid "aggregate_id", :null => false
|
5
5
|
t.integer "sequence_number", :null => false
|
6
6
|
t.datetime "created_at", :null => false
|
7
7
|
t.string "event_type", :null => false
|
@@ -27,7 +27,7 @@ CREATE INDEX snapshot_events ON event_records (aggregate_id, sequence_number DES
|
|
27
27
|
|
28
28
|
create_table "command_records", :force => true do |t|
|
29
29
|
t.string "user_id"
|
30
|
-
t.
|
30
|
+
t.uuid "aggregate_id"
|
31
31
|
t.string "command_type", :null => false
|
32
32
|
t.string "event_aggregate_id"
|
33
33
|
t.integer "event_sequence_number"
|
@@ -40,7 +40,7 @@ CREATE INDEX snapshot_events ON event_records (aggregate_id, sequence_number DES
|
|
40
40
|
create_table "stream_records", :force => true do |t|
|
41
41
|
t.datetime "created_at", :null => false
|
42
42
|
t.string "aggregate_type", :null => false
|
43
|
-
t.
|
43
|
+
t.uuid "aggregate_id", :null => false
|
44
44
|
t.integer "snapshot_threshold"
|
45
45
|
end
|
46
46
|
|
@@ -32,6 +32,8 @@ module Sequent
|
|
32
32
|
|
33
33
|
DEFAULT_ERROR_LOCALE_RESOLVER = -> { I18n.locale || :en }
|
34
34
|
|
35
|
+
DEFAULT_TIME_PRECISION = ActiveSupport::JSON::Encoding.time_precision
|
36
|
+
|
35
37
|
attr_accessor :aggregate_repository,
|
36
38
|
:event_store,
|
37
39
|
:command_service,
|
@@ -43,6 +45,7 @@ module Sequent
|
|
43
45
|
:event_record_hooks_class,
|
44
46
|
:command_handlers,
|
45
47
|
:command_filters,
|
48
|
+
:command_middleware,
|
46
49
|
:event_handlers,
|
47
50
|
:uuid_generator,
|
48
51
|
:disable_event_handlers,
|
@@ -56,7 +59,11 @@ module Sequent
|
|
56
59
|
:database_config_directory,
|
57
60
|
:database_schema_directory,
|
58
61
|
:event_store_schema_name,
|
59
|
-
:strict_check_attributes_on_apply_events
|
62
|
+
:strict_check_attributes_on_apply_events,
|
63
|
+
:enable_multiple_database_support,
|
64
|
+
:primary_database_role,
|
65
|
+
:primary_database_key,
|
66
|
+
:time_precision
|
60
67
|
|
61
68
|
attr_reader :migrations_class_name,
|
62
69
|
:versions_table_name,
|
@@ -78,6 +85,7 @@ module Sequent
|
|
78
85
|
self.command_handlers = []
|
79
86
|
self.command_filters = []
|
80
87
|
self.event_handlers = []
|
88
|
+
self.command_middleware = Sequent::Core::Middleware::Chain.new
|
81
89
|
|
82
90
|
self.aggregate_repository = Sequent::Core::AggregateRepository.new
|
83
91
|
self.event_store = Sequent::Core::EventStore.new
|
@@ -107,6 +115,16 @@ module Sequent
|
|
107
115
|
|
108
116
|
self.logger = Logger.new(STDOUT).tap { |l| l.level = Logger::INFO }
|
109
117
|
self.error_locale_resolver = DEFAULT_ERROR_LOCALE_RESOLVER
|
118
|
+
|
119
|
+
self.enable_multiple_database_support = false
|
120
|
+
self.primary_database_role = :writing
|
121
|
+
self.primary_database_key = :primary
|
122
|
+
|
123
|
+
self.time_precision = DEFAULT_TIME_PRECISION
|
124
|
+
end
|
125
|
+
|
126
|
+
def can_use_multiple_databases?
|
127
|
+
enable_multiple_database_support && ActiveRecord.version > Gem::Version.new('6.1.0')
|
110
128
|
end
|
111
129
|
|
112
130
|
def replayed_ids_table_name=(table_name)
|
@@ -39,14 +39,10 @@ module Sequent
|
|
39
39
|
include Helpers::MessageHandler
|
40
40
|
include Helpers::AutosetAttributes
|
41
41
|
include SnapshotConfiguration
|
42
|
+
extend ActiveSupport::DescendantsTracker
|
42
43
|
|
43
44
|
attr_reader :id, :uncommitted_events, :sequence_number, :event_stream
|
44
45
|
|
45
|
-
def self.inherited(subclass)
|
46
|
-
super
|
47
|
-
AggregateRoots << subclass
|
48
|
-
end
|
49
|
-
|
50
46
|
def self.load_from_history(stream, events)
|
51
47
|
first, *rest = events
|
52
48
|
if first.is_a? SnapshotEvent
|
@@ -127,7 +123,7 @@ module Sequent
|
|
127
123
|
# Provide subclasses nice DSL to 'apply' events via:
|
128
124
|
#
|
129
125
|
# def send_invoice
|
130
|
-
# apply InvoiceSentEvent, send_date:
|
126
|
+
# apply InvoiceSentEvent, send_date: Time.now
|
131
127
|
# end
|
132
128
|
#
|
133
129
|
def apply(event, params = {})
|
@@ -3,21 +3,17 @@
|
|
3
3
|
module Sequent
|
4
4
|
module Core
|
5
5
|
#
|
6
|
-
# Utility class containing all subclasses of AggregateRoot
|
6
|
+
# Utility class containing all subclasses of AggregateRoot.
|
7
7
|
#
|
8
8
|
class AggregateRoots
|
9
9
|
class << self
|
10
10
|
def aggregate_roots
|
11
|
-
|
11
|
+
Sequent::AggregateRoot.descendants
|
12
12
|
end
|
13
13
|
|
14
14
|
def all
|
15
15
|
aggregate_roots
|
16
16
|
end
|
17
|
-
|
18
|
-
def <<(aggregate_root)
|
19
|
-
aggregate_roots << aggregate_root
|
20
|
-
end
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
data/lib/sequent/core/command.rb
CHANGED
@@ -28,17 +28,17 @@ module Sequent
|
|
28
28
|
include ActiveModel::Validations
|
29
29
|
include ActiveModel::Validations::Callbacks
|
30
30
|
include Sequent::Core::Helpers::TypeConversionSupport
|
31
|
+
extend ActiveSupport::DescendantsTracker
|
31
32
|
|
32
|
-
attrs created_at:
|
33
|
+
attrs created_at: Time
|
34
|
+
|
35
|
+
define_model_callbacks :initialize, only: :after
|
33
36
|
|
34
37
|
def initialize(args = {})
|
35
38
|
update_all_attributes args
|
36
|
-
@created_at =
|
37
|
-
end
|
39
|
+
@created_at = Time.now
|
38
40
|
|
39
|
-
|
40
|
-
super
|
41
|
-
Commands << subclass
|
41
|
+
_run_initialize_callbacks
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -56,22 +56,18 @@ module Sequent
|
|
56
56
|
end
|
57
57
|
|
58
58
|
#
|
59
|
-
# Utility class containing all subclasses of BaseCommand
|
59
|
+
# Utility class containing all subclasses of BaseCommand.
|
60
60
|
#
|
61
61
|
class Commands
|
62
62
|
class << self
|
63
63
|
def commands
|
64
|
-
|
64
|
+
Sequent::Core::BaseCommand.descendants
|
65
65
|
end
|
66
66
|
|
67
67
|
def all
|
68
68
|
commands
|
69
69
|
end
|
70
70
|
|
71
|
-
def <<(command)
|
72
|
-
commands << command
|
73
|
-
end
|
74
|
-
|
75
71
|
def find(command_name)
|
76
72
|
commands.find { |c| c.name == command_name }
|
77
73
|
end
|
@@ -50,7 +50,12 @@ module Sequent
|
|
50
50
|
def process_commands
|
51
51
|
Sequent::Util.skip_if_already_processing(:command_service_process_commands) do
|
52
52
|
transaction_provider.transactional do
|
53
|
-
|
53
|
+
until command_queue.empty?
|
54
|
+
command = command_queue.pop
|
55
|
+
command_middleware.invoke(command) do
|
56
|
+
process_command(command)
|
57
|
+
end
|
58
|
+
end
|
54
59
|
Sequent::Util.done_processing(:command_service_process_commands)
|
55
60
|
end
|
56
61
|
ensure
|
@@ -66,7 +71,9 @@ module Sequent
|
|
66
71
|
|
67
72
|
filters.each { |filter| filter.execute(command) }
|
68
73
|
|
69
|
-
|
74
|
+
I18n.with_locale(Sequent.configuration.error_locale_resolver.call) do
|
75
|
+
fail CommandNotValid, command unless command.valid?
|
76
|
+
end
|
70
77
|
|
71
78
|
parsed_command = command.parse_attrs_to_correct_types
|
72
79
|
command_handlers.select do |h|
|
@@ -98,6 +105,10 @@ module Sequent
|
|
98
105
|
def command_handlers
|
99
106
|
Sequent.configuration.command_handlers
|
100
107
|
end
|
108
|
+
|
109
|
+
def command_middleware
|
110
|
+
Sequent.configuration.command_middleware
|
111
|
+
end
|
101
112
|
end
|
102
113
|
|
103
114
|
# Raised when BaseCommand.valid? returns false
|
data/lib/sequent/core/core.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative 'sequent_oj'
|
|
4
4
|
require_relative 'helpers/helpers'
|
5
5
|
require_relative 'persistors/persistors'
|
6
6
|
require_relative 'transactions/transactions'
|
7
|
+
require_relative 'middleware/middleware'
|
7
8
|
require_relative 'event'
|
8
9
|
require_relative 'aggregate_repository'
|
9
10
|
require_relative 'aggregate_root'
|
data/lib/sequent/core/event.rb
CHANGED
@@ -13,14 +13,14 @@ module Sequent
|
|
13
13
|
include Sequent::Core::Helpers::AttributeSupport
|
14
14
|
include Sequent::Core::Helpers::EqualSupport
|
15
15
|
include Sequent::Core::Helpers::StringSupport
|
16
|
-
attrs aggregate_id: String, sequence_number: Integer, created_at:
|
16
|
+
attrs aggregate_id: String, sequence_number: Integer, created_at: Time
|
17
17
|
|
18
18
|
def initialize(args = {})
|
19
19
|
update_all_attributes args
|
20
20
|
fail 'Missing aggregate_id' unless @aggregate_id
|
21
21
|
fail 'Missing sequence_number' unless @sequence_number
|
22
22
|
|
23
|
-
@created_at ||=
|
23
|
+
@created_at ||= Time.now
|
24
24
|
end
|
25
25
|
|
26
26
|
def payload
|
@@ -26,8 +26,21 @@ module Sequent
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
##
|
30
|
+
# Disables event type caching (ie. for in development).
|
31
|
+
#
|
32
|
+
class NoEventTypesCache
|
33
|
+
def fetch_or_store(event_type)
|
34
|
+
yield(event_type)
|
35
|
+
end
|
36
|
+
end
|
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
|
31
44
|
end
|
32
45
|
|
33
46
|
##
|
data/lib/sequent/core/ext/ext.rb
CHANGED
@@ -68,6 +68,23 @@ class DateTime
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
class Time
|
72
|
+
def self.from_params(value)
|
73
|
+
value.blank? ? nil : Time.iso8601(value.dup)
|
74
|
+
rescue ArgumentError
|
75
|
+
value
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.deserialize_from_json(value)
|
79
|
+
value.blank? ? nil : Time.iso8601(value.dup)
|
80
|
+
rescue ArgumentError => e
|
81
|
+
return Time.parse(value.dup) if e.message =~ /invalid xmlschema format/ # ruby >= 3
|
82
|
+
return Time.parse(value.dup) if e.message =~ /invalid date:/ # ruby 2.7
|
83
|
+
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
71
88
|
class Array
|
72
89
|
def self.deserialize_from_json(value)
|
73
90
|
value
|
@@ -17,6 +17,9 @@ module Sequent
|
|
17
17
|
Date => ->(klass, field) do
|
18
18
|
klass.validates field, 'sequent::Core::Helpers::Date' => true
|
19
19
|
end,
|
20
|
+
Time => ->(klass, field) do
|
21
|
+
klass.validates field, 'sequent::Core::Helpers::Time' => true
|
22
|
+
end,
|
20
23
|
DateTime => ->(klass, field) do
|
21
24
|
klass.validates field, 'sequent::Core::Helpers::DateTime' => true
|
22
25
|
end,
|
@@ -16,6 +16,7 @@ module Sequent
|
|
16
16
|
::Boolean => ->(value) { parse_to_bool(value) },
|
17
17
|
::Date => ->(value) { parse_to_date(value) },
|
18
18
|
::DateTime => ->(value) { parse_to_date_time(value) },
|
19
|
+
::Time => ->(value) { parse_to_time(value) },
|
19
20
|
::Sequent::Core::Helpers::ArrayWithType => ->(values, type_in_array) { parse_array(values, type_in_array) },
|
20
21
|
::Sequent::Core::Helpers::Secret => ->(value) { Sequent::Core::Helpers::Secret.new(value).encrypt },
|
21
22
|
}.freeze
|
@@ -52,6 +53,10 @@ module Sequent
|
|
52
53
|
value.is_a?(DateTime) ? value : DateTime.deserialize_from_json(value)
|
53
54
|
end
|
54
55
|
|
56
|
+
def self.parse_to_time(value)
|
57
|
+
value.is_a?(Time) ? value : Time.deserialize_from_json(value)
|
58
|
+
end
|
59
|
+
|
55
60
|
def self.parse_array(values, type_in_array)
|
56
61
|
fail "invalid value for array(): \"#{values}\"" unless values.is_a?(Array)
|
57
62
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
module Sequent
|
6
|
+
module Core
|
7
|
+
module Helpers
|
8
|
+
# Validates Time
|
9
|
+
# Automatically included when using a
|
10
|
+
#
|
11
|
+
# attrs value: Time
|
12
|
+
class TimeValidator < ActiveModel::EachValidator
|
13
|
+
def validate_each(subject, attribute, value)
|
14
|
+
return if value.is_a?(Time)
|
15
|
+
|
16
|
+
Time.deserialize_from_json(value)
|
17
|
+
rescue StandardError
|
18
|
+
subject.errors.add attribute, :invalid_time
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -16,6 +16,7 @@ module Sequent
|
|
16
16
|
::Integer => ->(value) { valid_integer?(value) },
|
17
17
|
::Boolean => ->(value) { valid_bool?(value) },
|
18
18
|
::Date => ->(value) { valid_date?(value) },
|
19
|
+
::Time => ->(value) { valid_time?(value) },
|
19
20
|
::DateTime => ->(value) { valid_date_time?(value) },
|
20
21
|
}.freeze
|
21
22
|
|
@@ -53,6 +54,16 @@ module Sequent
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
def self.valid_time?(value)
|
58
|
+
return true if value.blank?
|
59
|
+
|
60
|
+
begin
|
61
|
+
value.is_a?(Time) || !!Time.iso8601(value.dup)
|
62
|
+
rescue StandardError
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
56
67
|
def self.valid_string?(value)
|
57
68
|
return true if value.nil?
|
58
69
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sequent
|
4
|
+
module Core
|
5
|
+
module Middleware
|
6
|
+
class Chain
|
7
|
+
attr_reader :entries
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
clear
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(middleware)
|
14
|
+
@entries.push(middleware)
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear
|
18
|
+
@entries = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def invoke(*args, &invoker)
|
22
|
+
chain = @entries.dup
|
23
|
+
|
24
|
+
traverse_chain = -> do
|
25
|
+
if chain.empty?
|
26
|
+
invoker.call
|
27
|
+
else
|
28
|
+
chain.shift.call(*args, &traverse_chain)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
traverse_chain.call
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -86,17 +86,13 @@ module Sequent
|
|
86
86
|
extend Forwardable
|
87
87
|
include Helpers::MessageHandler
|
88
88
|
include Migratable
|
89
|
+
extend ActiveSupport::DescendantsTracker
|
89
90
|
|
90
91
|
def initialize(persistor = Sequent::Core::Persistors::ActiveRecordPersistor.new)
|
91
92
|
ensure_valid!
|
92
93
|
@persistor = persistor
|
93
94
|
end
|
94
95
|
|
95
|
-
def self.inherited(subclass)
|
96
|
-
super
|
97
|
-
Projectors << subclass
|
98
|
-
end
|
99
|
-
|
100
96
|
def self.replay_persistor
|
101
97
|
nil
|
102
98
|
end
|
@@ -132,22 +128,18 @@ module Sequent
|
|
132
128
|
end
|
133
129
|
|
134
130
|
#
|
135
|
-
# Utility class containing all subclasses of Projector
|
131
|
+
# Utility class containing all subclasses of Projector.
|
136
132
|
#
|
137
133
|
class Projectors
|
138
134
|
class << self
|
139
135
|
def projectors
|
140
|
-
|
136
|
+
Sequent::Projector.descendants
|
141
137
|
end
|
142
138
|
|
143
139
|
def all
|
144
140
|
projectors
|
145
141
|
end
|
146
142
|
|
147
|
-
def <<(projector)
|
148
|
-
projectors << projector
|
149
|
-
end
|
150
|
-
|
151
143
|
def find(projector_name)
|
152
144
|
projectors.find { |c| c.name == projector_name }
|
153
145
|
end
|
@@ -7,11 +7,7 @@ module Sequent
|
|
7
7
|
module Core
|
8
8
|
class Workflow
|
9
9
|
include Helpers::MessageHandler
|
10
|
-
|
11
|
-
def self.inherited(subclass)
|
12
|
-
super
|
13
|
-
Workflows << subclass
|
14
|
-
end
|
10
|
+
extend ActiveSupport::DescendantsTracker
|
15
11
|
|
16
12
|
def self.on(*args, **opts, &block)
|
17
13
|
decorated_block = ->(event) do
|
@@ -49,22 +45,18 @@ module Sequent
|
|
49
45
|
end
|
50
46
|
|
51
47
|
#
|
52
|
-
# Utility class containing all subclasses of Workflow
|
48
|
+
# Utility class containing all subclasses of Workflow.
|
53
49
|
#
|
54
50
|
class Workflows
|
55
51
|
class << self
|
56
52
|
def workflows
|
57
|
-
|
53
|
+
Sequent::Workflow.descendants
|
58
54
|
end
|
59
55
|
|
60
56
|
def all
|
61
57
|
workflows
|
62
58
|
end
|
63
59
|
|
64
|
-
def <<(workflow)
|
65
|
-
workflows << workflow
|
66
|
-
end
|
67
|
-
|
68
60
|
def find(workflow_name)
|
69
61
|
workflows.find { |c| c.name == workflow_name }
|
70
62
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
ENV['
|
1
|
+
ENV['SEQUENT_ENV'] ||= 'development'
|
2
2
|
|
3
3
|
require './my_app'
|
4
4
|
require 'sequent/rake/migration_tasks'
|
@@ -8,5 +8,5 @@ Sequent::Rake::MigrationTasks.new.register_tasks!
|
|
8
8
|
task "sequent:migrate:init" => [:db_connect]
|
9
9
|
|
10
10
|
task "db_connect" do
|
11
|
-
Sequent::Support::Database.connect!(ENV['
|
11
|
+
Sequent::Support::Database.connect!(ENV['SEQUENT_ENV'])
|
12
12
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
ActiveRecord::Schema.define do
|
2
2
|
|
3
3
|
create_table "event_records", :force => true do |t|
|
4
|
-
t.
|
4
|
+
t.uuid "aggregate_id", :null => false
|
5
5
|
t.integer "sequence_number", :null => false
|
6
6
|
t.datetime "created_at", :null => false
|
7
7
|
t.string "event_type", :null => false
|
@@ -27,7 +27,7 @@ CREATE INDEX snapshot_events ON event_records (aggregate_id, sequence_number DES
|
|
27
27
|
|
28
28
|
create_table "command_records", :force => true do |t|
|
29
29
|
t.string "user_id"
|
30
|
-
t.
|
30
|
+
t.uuid "aggregate_id"
|
31
31
|
t.string "command_type", :null => false
|
32
32
|
t.text "command_json", :null => false
|
33
33
|
t.datetime "created_at", :null => false
|
@@ -36,7 +36,7 @@ CREATE INDEX snapshot_events ON event_records (aggregate_id, sequence_number DES
|
|
36
36
|
create_table "stream_records", :force => true do |t|
|
37
37
|
t.datetime "created_at", :null => false
|
38
38
|
t.string "aggregate_type", :null => false
|
39
|
-
t.
|
39
|
+
t.uuid "aggregate_id", :null => false
|
40
40
|
t.integer "snapshot_threshold"
|
41
41
|
end
|
42
42
|
|
@@ -5,11 +5,11 @@ module Sequent
|
|
5
5
|
module Migrations
|
6
6
|
class Projectors
|
7
7
|
def self.versions
|
8
|
-
fail
|
8
|
+
fail "Define your own #{name} class that extends this class and implements this method"
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.version
|
12
|
-
fail
|
12
|
+
fail "Define your own #{name} class that extends this class and implements this method"
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.migrations_between(old, new)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sequent
|
4
|
+
module Migrations
|
5
|
+
class SequentSchema
|
6
|
+
FAIL_IF_EXISTS = ->(schema_name) { fail "Schema #{schema_name} already exists in the database" }
|
7
|
+
|
8
|
+
class << self
|
9
|
+
#
|
10
|
+
# Creates the sequent schema if it does not exist yet
|
11
|
+
#
|
12
|
+
# @param env [String] The environment used to setup database connection
|
13
|
+
# @param fail_if_exists [Boolean] When true fails if the schema exists, otherwise just return.
|
14
|
+
def create_sequent_schema_if_not_exists(env:, fail_if_exists: true)
|
15
|
+
fail ArgumentError, 'env is required' if env.blank?
|
16
|
+
|
17
|
+
db_config = Sequent::Support::Database.read_config(env)
|
18
|
+
|
19
|
+
Sequent::Support::Database.establish_connection(db_config)
|
20
|
+
|
21
|
+
event_store_schema = Sequent.configuration.event_store_schema_name
|
22
|
+
schema_exists = Sequent::Support::Database.schema_exists?(event_store_schema)
|
23
|
+
|
24
|
+
FAIL_IF_EXISTS.call(event_store_schema) if schema_exists && fail_if_exists
|
25
|
+
return if schema_exists
|
26
|
+
|
27
|
+
sequent_schema = File.join(Sequent.configuration.database_schema_directory, "#{event_store_schema}.rb")
|
28
|
+
unless File.exist?(sequent_schema)
|
29
|
+
fail "File '#{sequent_schema}' does not exist. Check your Sequent configuration."
|
30
|
+
end
|
31
|
+
|
32
|
+
Sequent::Support::Database.create_schema(event_store_schema)
|
33
|
+
Sequent::Support::Database.with_schema_search_path(event_store_schema, db_config, env) do
|
34
|
+
load(sequent_schema)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|