sequent 4.1.0 → 4.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e0c606e57bb36fdcaeeb102904dd450a0ff9fc2a84fdd5aff7f365a914c45d3
4
- data.tar.gz: ea03e8a0c7ab524ff8c73fded97a726edf3dff240b95db62496496d5a6a6d580
3
+ metadata.gz: b7e291ad7f19e869e7606e8dc49282a545db07d4a656f5ee44d71ed5c2e33170
4
+ data.tar.gz: fb73e4b00b0f0e9ef94cab2152922c280b51d3568f5f9ecb7a9cdaa00afed97e
5
5
  SHA512:
6
- metadata.gz: 10f78e12826549dcd0ea3677940b5b2cdbde26fb9ecdf2f5a1bca67d5dd8405447409417b6cd277bd554c3590a2a7a3814a0918ae79ceec2b6da9510d8d1fa3f
7
- data.tar.gz: abde6abb5638e8ad3f4f2081eb1e9eada6588d4d74994a5a62a4ef761b9737277981a5c270e75297a5e508cc611031a2e779df43b3a70b3d5a9bb0b77c81ec34
6
+ metadata.gz: df076f1efbe41c17c75c99c5331d7f1e23ff8c52607c9a0e709a9dd46504a2b6e78d471ed247dff4e5913809de28bc328a820ce00779d0a97fb64f669a10670e
7
+ data.tar.gz: 552dca913ac052facd09d2602c08a38fa33c66e3d4c092d38a6fcd018dabca2683ef93d5f3ddef8b105fa043c6d99bf765be38ad2f69171a08e5af63df3783ad
data/bin/sequent CHANGED
@@ -20,10 +20,11 @@ def new_project(args)
20
20
  Success!
21
21
 
22
22
  Your brand spanking new sequent app is waiting for you in:
23
- #{File.expand_path(name, __dir__)}
23
+ #{File.expand_path(name, Dir.pwd)}
24
24
 
25
25
  To finish setting up your app:
26
26
  cd #{name}
27
+ bundle install
27
28
  bundle exec rake sequent:db:create
28
29
  bundle exec rake sequent:db:create_view_schema
29
30
  bundle exec rake sequent:migrate:online
@@ -92,6 +92,11 @@ module Sequent
92
92
  @persistor = persistor
93
93
  end
94
94
 
95
+ def self.inherited(subclass)
96
+ super
97
+ Projectors << subclass
98
+ end
99
+
95
100
  def self.replay_persistor
96
101
  nil
97
102
  end
@@ -125,5 +130,28 @@ module Sequent
125
130
  end
126
131
  end
127
132
  end
133
+
134
+ #
135
+ # Utility class containing all subclasses of Projector
136
+ #
137
+ class Projectors
138
+ class << self
139
+ def projectors
140
+ @projectors ||= []
141
+ end
142
+
143
+ def all
144
+ projectors
145
+ end
146
+
147
+ def <<(projector)
148
+ projectors << projector
149
+ end
150
+
151
+ def find(projector_name)
152
+ projectors.find { |c| c.name == projector_name }
153
+ end
154
+ end
155
+ end
128
156
  end
129
157
  end
@@ -3,6 +3,31 @@
3
3
  module Sequent
4
4
  module Core
5
5
  module Transactions
6
+ ##
7
+ # Always require a new transaction.
8
+ #
9
+ # Read:
10
+ # http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
11
+ #
12
+ # Without this change, there is a potential bug:
13
+ #
14
+ # ```ruby
15
+ # ActiveRecord::Base.transaction do
16
+ # Sequent.configuration.command_service.execute_commands command
17
+ # end
18
+ #
19
+ # on Command do
20
+ # do.some.things
21
+ # fail ActiveRecord::Rollback
22
+ # end
23
+ # ```
24
+ #
25
+ # In this example, you might be surprised to find that `do.some.things`
26
+ # does not get rolled back! This is because AR doesn't automatically make
27
+ # a "savepoint" for us when we call `.transaction` in a nested manner. In
28
+ # order to enable this behaviour, we have to call `.transaction` like
29
+ # this: `.transaction(requires_new: true)`.
30
+ #
6
31
  class ActiveRecordTransactionProvider
7
32
  def transactional(&block)
8
33
  Sequent::ApplicationRecord.transaction(requires_new: true, &block)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequent
4
+ module Core
5
+ module Transactions
6
+ class ReadOnlyActiveRecordTransactionProvider
7
+ def initialize(transaction_provider)
8
+ @transaction_provider = transaction_provider
9
+ end
10
+
11
+ def transactional(&block)
12
+ register_call
13
+ @transaction_provider.transactional do
14
+ Sequent::ApplicationRecord.connection.execute('SET TRANSACTION READ ONLY')
15
+ block.call
16
+ rescue ActiveRecord::StatementInvalid
17
+ @skip_set_transaction = true
18
+ raise
19
+ ensure
20
+ deregister_call
21
+ reset_stack_size if stack_size == 0
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def stack_size
28
+ Thread.current[:read_only_active_record_transaction_provider_calls]
29
+ end
30
+
31
+ def register_call
32
+ Thread.current[:read_only_active_record_transaction_provider_calls] ||= 0
33
+ Thread.current[:read_only_active_record_transaction_provider_calls] += 1
34
+ end
35
+
36
+ def deregister_call
37
+ Thread.current[:read_only_active_record_transaction_provider_calls] -= 1
38
+ end
39
+
40
+ def reset_stack_size
41
+ Thread.current[:read_only_active_record_transaction_provider_calls] = nil
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -2,3 +2,4 @@
2
2
 
3
3
  require_relative 'active_record_transaction_provider'
4
4
  require_relative 'no_transactions'
5
+ require_relative 'read_only_active_record_transaction_provider'
@@ -8,6 +8,11 @@ module Sequent
8
8
  class Workflow
9
9
  include Helpers::MessageHandler
10
10
 
11
+ def self.inherited(subclass)
12
+ super
13
+ Workflows << subclass
14
+ end
15
+
11
16
  def self.on(*message_classes, &block)
12
17
  decorated_block = ->(event) do
13
18
  begin
@@ -42,5 +47,28 @@ module Sequent
42
47
  end
43
48
  end
44
49
  end
50
+
51
+ #
52
+ # Utility class containing all subclasses of Workflow
53
+ #
54
+ class Workflows
55
+ class << self
56
+ def workflows
57
+ @workflows ||= []
58
+ end
59
+
60
+ def all
61
+ workflows
62
+ end
63
+
64
+ def <<(workflow)
65
+ workflows << workflow
66
+ end
67
+
68
+ def find(workflow_name)
69
+ workflows.find { |c| c.name == workflow_name }
70
+ end
71
+ end
72
+ end
45
73
  end
46
74
  end
@@ -14,6 +14,7 @@ module Sequent
14
14
  def execute
15
15
  make_directory
16
16
  copy_files
17
+ rename_ruby_version
17
18
  rename_app_file
18
19
  replace_app_name
19
20
  end
@@ -28,6 +29,12 @@ module Sequent
28
29
  FileUtils.copy_entry(File.expand_path('template_project', __dir__), path)
29
30
  end
30
31
 
32
+ # Hidden files are by default excluded from gem build.
33
+ # Therefor we need to rename the ruby-version to .ruby-version.
34
+ def rename_ruby_version
35
+ FileUtils.mv("#{path}/ruby-version", "#{path}/.ruby-version")
36
+ end
37
+
31
38
  def rename_app_file
32
39
  FileUtils.mv("#{path}/my_app.rb", "#{path}/#{name_underscored}.rb")
33
40
  end
@@ -36,18 +36,18 @@ module Sequent
36
36
 
37
37
  delegate :load_events_for_aggregates,
38
38
  :load_events,
39
- :publish_events,
40
39
  :stream_exists?,
40
+ :events_exists?,
41
41
  to: :event_store
42
42
 
43
- def initialize(result)
44
- @event_store = Sequent::Test::CommandHandlerHelpers::FakeEventStore.new
43
+ def initialize(result, event_store)
44
+ @event_store = event_store
45
45
  @command_with_events = {}
46
46
  @result = result
47
47
  end
48
48
 
49
49
  def commit_events(command, streams_with_events)
50
- event_store.commit_events(command, streams_with_events)
50
+ Sequent.configuration.event_publisher.publish_events(streams_with_events.flat_map { |_, events| events })
51
51
 
52
52
  new_events = streams_with_events.flat_map { |_, events| events }
53
53
  @result.published_command_with_events(command, new_events)
@@ -66,18 +66,18 @@ module Sequent
66
66
  end
67
67
 
68
68
  def process_event(event)
69
- Sequent.configuration.event_handlers.each do |handler|
70
- next unless handler.class.handles_message?(event)
69
+ [*Sequent::Core::Workflows.all, *Sequent::Core::Projectors.all].each do |handler_class|
70
+ next unless handler_class.handles_message?(event)
71
71
 
72
- if handler.is_a?(Sequent::Workflow)
73
- @result.invoked_workflow(EventInvokedHandler.new(event, handler.class))
74
- elsif handler.is_a?(Sequent::Projector)
75
- @result.invoked_projector(EventInvokedHandler.new(event, handler.class))
72
+ if handler_class < Sequent::Workflow
73
+ @result.invoked_workflow(EventInvokedHandler.new(event, handler_class))
74
+ elsif handler_class < Sequent::Projector
75
+ @result.invoked_projector(EventInvokedHandler.new(event, handler_class))
76
76
  else
77
- fail "Unrecognized event_handler #{handler.class} called for event #{event.class}"
77
+ fail "Unrecognized event_handler #{handler_class} called for event #{event.class}"
78
78
  end
79
79
  rescue StandardError
80
- raise PublishEventError.new(handler.class, event)
80
+ raise PublishEventError.new(handler_class, event)
81
81
  end
82
82
  end
83
83
  end
@@ -177,10 +177,14 @@ module Sequent
177
177
  def self.these_commands(commands)
178
178
  current_event_store = Sequent.configuration.event_store
179
179
  current_event_publisher = Sequent.configuration.event_publisher
180
+ current_transaction_provider = Sequent.configuration.transaction_provider
181
+
180
182
  result = Result.new
181
183
 
182
- Sequent.configuration.event_store = EventStoreProxy.new(result)
184
+ Sequent.configuration.event_store = EventStoreProxy.new(result, current_event_store)
183
185
  Sequent.configuration.event_publisher = RecordingEventPublisher.new(result)
186
+ Sequent.configuration.transaction_provider =
187
+ Sequent::Core::Transactions::ReadOnlyActiveRecordTransactionProvider.new(current_transaction_provider)
184
188
 
185
189
  Sequent.command_service.execute_commands(*commands)
186
190
 
@@ -188,6 +192,7 @@ module Sequent
188
192
  ensure
189
193
  Sequent.configuration.event_store = current_event_store
190
194
  Sequent.configuration.event_publisher = current_event_publisher
195
+ Sequent.configuration.transaction_provider = current_transaction_provider
191
196
  end
192
197
  end
193
198
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sequent
4
- VERSION = '4.1.0'
4
+ VERSION = '4.2.0'
5
5
  end
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.1.0
4
+ version: 4.2.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: 2021-12-21 00:00:00.000000000 Z
15
+ date: 2022-01-30 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: 6.1.4
26
+ version: 6.1.4.4
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: 6.1.4
36
+ version: 6.1.4.4
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: 6.1.4
46
+ version: 6.1.4.4
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: 6.1.4
56
+ version: 6.1.4.4
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: bcrypt
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -362,6 +362,7 @@ files:
362
362
  - lib/sequent/core/stream_record.rb
363
363
  - lib/sequent/core/transactions/active_record_transaction_provider.rb
364
364
  - lib/sequent/core/transactions/no_transactions.rb
365
+ - lib/sequent/core/transactions/read_only_active_record_transaction_provider.rb
365
366
  - lib/sequent/core/transactions/transactions.rb
366
367
  - lib/sequent/core/value_object.rb
367
368
  - lib/sequent/core/workflow.rb
@@ -393,6 +394,7 @@ files:
393
394
  - lib/sequent/generator/template_project/lib/post/post.rb
394
395
  - lib/sequent/generator/template_project/lib/post/post_command_handler.rb
395
396
  - lib/sequent/generator/template_project/my_app.rb
397
+ - lib/sequent/generator/template_project/ruby-version
396
398
  - lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb
397
399
  - lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb
398
400
  - lib/sequent/generator/template_project/spec/spec_helper.rb