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