synapse-core 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/synapse/command/async_command_bus.rb +3 -5
- data/lib/synapse/common.rb +0 -1
- data/lib/synapse/configuration/component/command_bus/async_command_bus.rb +3 -2
- data/lib/synapse/configuration/component/{mixin → shared}/thread_pool.rb +10 -8
- data/lib/synapse/configuration/dependent.rb +2 -2
- data/lib/synapse/configuration/ext.rb +58 -29
- data/lib/synapse/configuration.rb +1 -1
- data/lib/synapse/domain/aggregate_root.rb +43 -19
- data/lib/synapse/domain/errors.rb +9 -0
- data/lib/synapse/domain/event_container.rb +3 -3
- data/lib/synapse/domain/message.rb +2 -2
- data/lib/synapse/domain/message_builder.rb +2 -2
- data/lib/synapse/domain/simple_stream.rb +39 -0
- data/lib/synapse/domain/stream.rb +2 -41
- data/lib/synapse/domain.rb +3 -0
- data/lib/synapse/event_sourcing/aggregate_root.rb +102 -2
- data/lib/synapse/event_sourcing/caching.rb +1 -1
- data/lib/synapse/event_sourcing/entity.rb +2 -2
- data/lib/synapse/event_sourcing/member.rb +3 -13
- data/lib/synapse/event_sourcing/repository.rb +9 -2
- data/lib/synapse/event_sourcing/snapshot/taker.rb +2 -2
- data/lib/synapse/mapping/mapping.rb +2 -2
- data/lib/synapse/process_manager/simple_process_manager.rb +1 -0
- data/lib/synapse/rails/injection_helper.rb +23 -0
- data/lib/synapse/railtie.rb +17 -0
- data/lib/synapse/repository/lock_manager.rb +3 -3
- data/lib/synapse/uow/listener.rb +2 -2
- data/lib/synapse/uow/listener_collection.rb +7 -51
- data/lib/synapse/version.rb +1 -1
- data/lib/synapse-core.rb +1 -0
- data/lib/synapse.rb +3 -0
- data/test/command/async_command_bus_test.rb +8 -11
- data/test/configuration/component/command_bus/async_command_bus_test.rb +7 -6
- data/test/configuration/component/serialization/serializer_test.rb +2 -2
- data/test/configuration/fixtures/dependent.rb +1 -1
- data/test/rails/injection_helper_test.rb +27 -0
- data/test/serialization/converter/ox_test.rb +2 -2
- data/test/serialization/serializer/oj_test.rb +1 -1
- data/test/serialization/serializer/ox_test.rb +1 -1
- data/test/test_helper.rb +8 -9
- data/test/uow/uow_test.rb +2 -2
- metadata +221 -222
- data/lib/synapse/common/concurrency/executor.rb +0 -13
- data/test/support/countdown_latch.rb +0 -18
@@ -62,7 +62,7 @@ module Synapse
|
|
62
62
|
aggregate.initialize_from_stream stream
|
63
63
|
|
64
64
|
if aggregate.deleted?
|
65
|
-
raise AggregateDeletedError
|
65
|
+
raise AggregateDeletedError.new type_identifier, aggregate_id
|
66
66
|
end
|
67
67
|
|
68
68
|
if expected_version and @conflict_resolver.nil?
|
@@ -138,6 +138,13 @@ module Synapse
|
|
138
138
|
end
|
139
139
|
|
140
140
|
# Raised when an aggregate has been found but it was marked for deletion
|
141
|
-
class AggregateDeletedError < Repository::AggregateNotFoundError
|
141
|
+
class AggregateDeletedError < Repository::AggregateNotFoundError
|
142
|
+
# @param [String] type_identifier
|
143
|
+
# @param [Object] aggregate_id
|
144
|
+
# @return [undefined]
|
145
|
+
def initialize(type_identifier, aggregate_id)
|
146
|
+
super 'Aggregate marked for deletion [%s] [%s]' % [type_identifier, aggregate_id]
|
147
|
+
end
|
148
|
+
end
|
142
149
|
end
|
143
150
|
end
|
@@ -10,12 +10,12 @@ module Synapse
|
|
10
10
|
# @return [SnapshotEventStore]
|
11
11
|
attr_accessor :event_store
|
12
12
|
|
13
|
-
# @return [Executor]
|
13
|
+
# @return [Contender::Executor]
|
14
14
|
attr_accessor :executor
|
15
15
|
|
16
16
|
# @return [undefined]
|
17
17
|
def initialize
|
18
|
-
@executor = DirectExecutor.new
|
18
|
+
@executor = Contender::DirectExecutor.new
|
19
19
|
end
|
20
20
|
|
21
21
|
# Schedules a snapshot to be taken for an aggregate of the given type and with the given
|
@@ -4,6 +4,7 @@ module Synapse
|
|
4
4
|
class SimpleProcessManager < ProcessManager
|
5
5
|
# @return [Array] Types of events that will always result in the creation of a process
|
6
6
|
attr_accessor :always_create_events
|
7
|
+
|
7
8
|
# @return [Array] Types of events that will result in the creation of a process if one
|
8
9
|
# doesn't already exist
|
9
10
|
attr_accessor :optionally_create_events
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Synapse
|
2
|
+
module Rails
|
3
|
+
# Mixin for an action controller in Rails that adds dependency injection
|
4
|
+
module InjectionHelper
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_filter :inject_dependencies
|
9
|
+
end
|
10
|
+
|
11
|
+
# Performs one-time dependency injection before an action is called
|
12
|
+
# @return [undefined]
|
13
|
+
def inject_dependencies
|
14
|
+
return if @_dependencies_injected
|
15
|
+
|
16
|
+
container = Synapse.container
|
17
|
+
container.inject_into self
|
18
|
+
|
19
|
+
@_dependencies_injected = true
|
20
|
+
end
|
21
|
+
end # InjectionHelper
|
22
|
+
end # Rails
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Synapse
|
2
|
+
# Simple integration between the Synapse framework and Rails 3.2+
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
# Set the name of the Railtie
|
5
|
+
railtie_name :synapse
|
6
|
+
|
7
|
+
# Controllers will get dependencies injected automatically
|
8
|
+
initializer 'synapse.include_controller_mixins' do
|
9
|
+
ActionController::Base.class_eval do
|
10
|
+
include Synapse::Configuration::Dependent
|
11
|
+
include Synapse::Rails::InjectionHelper
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end # Railtie
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'synapse/rails/injection_helper'
|
@@ -26,7 +26,7 @@ module Synapse
|
|
26
26
|
# @param [Object] aggregate_id
|
27
27
|
# @return [undefined]
|
28
28
|
def release_lock(aggregate_id); end
|
29
|
-
end
|
29
|
+
end # LockManager
|
30
30
|
|
31
31
|
# Implementation of a lock manager that does no locking
|
32
32
|
class NullLockManager < LockManager
|
@@ -35,6 +35,6 @@ module Synapse
|
|
35
35
|
def validate_lock(aggregate)
|
36
36
|
true
|
37
37
|
end
|
38
|
-
end
|
39
|
-
end
|
38
|
+
end # NullLockManager
|
39
|
+
end # Repository
|
40
40
|
end
|
data/lib/synapse/uow/listener.rb
CHANGED
@@ -22,10 +22,7 @@ module Synapse
|
|
22
22
|
# @param [UnitOfWorkListener] listener
|
23
23
|
# @return [undefined]
|
24
24
|
def push(listener)
|
25
|
-
|
26
|
-
@logger.debug 'Registering listener [%s]' % listener.class
|
27
|
-
end
|
28
|
-
|
25
|
+
@logger.debug 'Registering listener [%s]' % listener.class
|
29
26
|
@listeners.push listener
|
30
27
|
end
|
31
28
|
|
@@ -34,17 +31,10 @@ module Synapse
|
|
34
31
|
# @param [UnitOfWork] unit
|
35
32
|
# @return [undefined]
|
36
33
|
def on_start(unit)
|
37
|
-
@logger.debug 'Notifying listeners that unit of work is starting'
|
38
|
-
|
39
34
|
@listeners.each do |listener|
|
40
|
-
|
41
|
-
@logger.debug 'Notifying [%s] of start' % listener.class
|
42
|
-
end
|
43
|
-
|
35
|
+
@logger.debug 'Notifying [%s] of start' % listener.class
|
44
36
|
listener.on_start unit
|
45
37
|
end
|
46
|
-
|
47
|
-
@logger.debug 'Listeners successfully notified'
|
48
38
|
end
|
49
39
|
|
50
40
|
# @param [UnitOfWork] unit
|
@@ -63,78 +53,46 @@ module Synapse
|
|
63
53
|
# @param [Hash<EventBus, Array>] events
|
64
54
|
# @return [undefined]
|
65
55
|
def on_prepare_commit(unit, aggregates, events)
|
66
|
-
@logger.debug 'Notifying listeners that commit was requested'
|
67
|
-
|
68
56
|
@listeners.each do |listener|
|
69
|
-
|
70
|
-
@logger.debug 'Notifying [%s] of commit' % listener.class
|
71
|
-
end
|
72
|
-
|
57
|
+
@logger.debug 'Notifying [%s] of commit' % listener.class
|
73
58
|
listener.on_prepare_commit unit, aggregates, events
|
74
59
|
end
|
75
|
-
|
76
|
-
@logger.debug 'Listeners successfully notified'
|
77
60
|
end
|
78
61
|
|
79
62
|
# @param [UnitOfWork] unit
|
80
63
|
# @param [Object] transaction
|
81
64
|
# @return [undefined]
|
82
65
|
def on_prepare_transaction_commit(unit, transaction)
|
83
|
-
@logger.debug 'Notifying listeners that transactional commit was requested'
|
84
|
-
|
85
66
|
@listeners.each do |listener|
|
86
|
-
|
87
|
-
@logger.debug 'Notifying [%s] of transactional commit' % listener.class
|
88
|
-
end
|
89
|
-
|
67
|
+
@logger.debug 'Notifying [%s] of transactional commit' % listener.class
|
90
68
|
listener.on_prepare_transaction_commit unit, transaction
|
91
69
|
end
|
92
|
-
|
93
|
-
@logger.debug 'Listeners successfully notified'
|
94
70
|
end
|
95
71
|
|
96
72
|
# @param [UnitOfWork] unit
|
97
73
|
# @return [undefined]
|
98
74
|
def after_commit(unit)
|
99
|
-
@logger.debug 'Notifying listeners that commit has finished'
|
100
|
-
|
101
75
|
@listeners.reverse_each do |listener|
|
102
|
-
|
103
|
-
@logger.debug 'Notifying [%s] of finished commit' % listener.class
|
104
|
-
end
|
105
|
-
|
76
|
+
@logger.debug 'Notifying [%s] of finished commit' % listener.class
|
106
77
|
listener.after_commit unit
|
107
78
|
end
|
108
|
-
|
109
|
-
@logger.debug 'Listeners successfully notified'
|
110
79
|
end
|
111
80
|
|
112
81
|
# @param [UnitOfWork] unit
|
113
82
|
# @param [Error] cause
|
114
83
|
# @return [undefined]
|
115
84
|
def on_rollback(unit, cause = nil)
|
116
|
-
@logger.debug 'Notifying listeners of rollback'
|
117
|
-
|
118
85
|
@listeners.reverse_each do |listener|
|
119
|
-
|
120
|
-
@logger.debug 'Notifying [%s] of rollback' % listener.class
|
121
|
-
end
|
122
|
-
|
86
|
+
@logger.debug 'Notifying [%s] of rollback' % listener.class
|
123
87
|
listener.on_rollback unit, cause
|
124
88
|
end
|
125
|
-
|
126
|
-
@logger.debug 'Listeners successfully notified'
|
127
89
|
end
|
128
90
|
|
129
91
|
# @param [UnitOfWork] unit
|
130
92
|
# @return [undefined]
|
131
93
|
def on_cleanup(unit)
|
132
|
-
@logger.debug 'Notifying listeners of cleanup'
|
133
|
-
|
134
94
|
@listeners.reverse_each do |listener|
|
135
|
-
|
136
|
-
@logger.debug 'Notifying [%s] of cleanup' % listener.class
|
137
|
-
end
|
95
|
+
@logger.debug 'Notifying [%s] of cleanup' % listener.class
|
138
96
|
|
139
97
|
begin
|
140
98
|
listener.on_cleanup unit
|
@@ -143,8 +101,6 @@ module Synapse
|
|
143
101
|
@logger.warn 'Listener raised an exception during cleanup: %s' % exception.inspect
|
144
102
|
end
|
145
103
|
end
|
146
|
-
|
147
|
-
@logger.debug 'Listeners successfully notified'
|
148
104
|
end
|
149
105
|
end # UnitOfWorkListenerCollection
|
150
106
|
end # UnitOfWork
|
data/lib/synapse/version.rb
CHANGED
data/lib/synapse-core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'synapse'
|
data/lib/synapse.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
require 'active_support/core_ext'
|
3
|
+
require 'contender'
|
3
4
|
require 'forwardable'
|
4
5
|
require 'logging'
|
5
6
|
require 'set'
|
@@ -29,3 +30,5 @@ module Synapse
|
|
29
30
|
autoload :ProcessManager
|
30
31
|
autoload :Upcasting
|
31
32
|
end
|
33
|
+
|
34
|
+
require 'synapse/railtie' if defined? Rails
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'support/countdown_latch'
|
3
2
|
|
4
3
|
module Synapse
|
5
4
|
module Command
|
@@ -9,14 +8,16 @@ module Synapse
|
|
9
8
|
unit_factory = UnitOfWork::UnitOfWorkFactory.new unit_provider
|
10
9
|
|
11
10
|
@bus = AsynchronousCommandBus.new unit_factory
|
12
|
-
@bus.thread_pool =
|
11
|
+
@bus.thread_pool = Contender::Pool::ThreadPoolExecutor.new
|
12
|
+
@bus.thread_pool.start
|
13
13
|
end
|
14
14
|
|
15
15
|
should 'be able to dispatch commands asynchronously using a thread pool' do
|
16
16
|
x = 5 # Number of commands to dispatch
|
17
17
|
|
18
18
|
command = CommandMessage.as_message TestCommand.new
|
19
|
-
|
19
|
+
latch = Contender::CountdownLatch.new x
|
20
|
+
handler = TestAsyncHandler.new latch
|
20
21
|
|
21
22
|
@bus.subscribe TestCommand, handler
|
22
23
|
|
@@ -24,23 +25,19 @@ module Synapse
|
|
24
25
|
@bus.dispatch command
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
handler.latch.count == 0
|
29
|
-
end
|
28
|
+
assert latch.await 5
|
30
29
|
|
31
30
|
@bus.shutdown
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
34
|
class TestAsyncHandler
|
36
|
-
|
37
|
-
|
38
|
-
def initialize(x)
|
39
|
-
@latch = CountdownLatch.new x
|
35
|
+
def initialize(latch)
|
36
|
+
@latch = latch
|
40
37
|
end
|
41
38
|
|
42
39
|
def handle(command, unit)
|
43
|
-
@latch.countdown
|
40
|
+
@latch.countdown
|
44
41
|
end
|
45
42
|
end
|
46
43
|
|
@@ -16,20 +16,21 @@ module Synapse
|
|
16
16
|
assert command_bus.is_a? Command::AsynchronousCommandBus
|
17
17
|
|
18
18
|
thread_pool = command_bus.thread_pool
|
19
|
-
|
20
|
-
|
19
|
+
assert_instance_of Contender::Pool::ThreadPoolExecutor, thread_pool
|
20
|
+
assert thread_pool.active?
|
21
|
+
thread_pool.shutdown
|
21
22
|
end
|
22
23
|
|
23
|
-
should 'build with a custom thread pool
|
24
|
+
should 'build with a custom thread pool options' do
|
24
25
|
@builder.async_command_bus do
|
25
|
-
|
26
|
+
use_pool_options size: 4, non_block: true
|
26
27
|
end
|
27
28
|
|
28
29
|
command_bus = @container.resolve :command_bus
|
29
30
|
|
30
31
|
thread_pool = command_bus.thread_pool
|
31
|
-
|
32
|
-
|
32
|
+
assert thread_pool.active?
|
33
|
+
thread_pool.shutdown
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -40,7 +40,7 @@ module Synapse
|
|
40
40
|
end
|
41
41
|
|
42
42
|
should 'build with OxSerializer' do
|
43
|
-
|
43
|
+
omit 'Ox not supported on JRuby' if defined? JRUBY_VERSION
|
44
44
|
|
45
45
|
serialize_options = { :circular => true }
|
46
46
|
|
@@ -56,7 +56,7 @@ module Synapse
|
|
56
56
|
end
|
57
57
|
|
58
58
|
should 'build with OjSerializer' do
|
59
|
-
|
59
|
+
omit 'Oj not supported on JRuby' if defined? JRUBY_VERSION
|
60
60
|
|
61
61
|
serialize_options = { :indent => 2, :circular => true }
|
62
62
|
deserialize_options = { :symbol_keys => true }
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'synapse/railtie'
|
5
|
+
|
6
|
+
module Synapse
|
7
|
+
module Rails
|
8
|
+
class InjectionHelperTest < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller_class = Class.new
|
12
|
+
@controller = @controller_class.new
|
13
|
+
mock(@controller_class).before_filter(:inject_dependencies)
|
14
|
+
@controller_class.send :include, InjectionHelper
|
15
|
+
end
|
16
|
+
|
17
|
+
should 'inject dependencies only once' do
|
18
|
+
container_mock = mock(Synapse).container.mock!
|
19
|
+
container_mock.inject_into(@controller)
|
20
|
+
|
21
|
+
@controller.inject_dependencies
|
22
|
+
@controller.inject_dependencies
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -4,7 +4,7 @@ module Synapse
|
|
4
4
|
module Serialization
|
5
5
|
class OxDocumentToXmlConverterTest < Test::Unit::TestCase
|
6
6
|
def setup
|
7
|
-
|
7
|
+
omit 'Ox not supported on JRuby' if defined? JRUBY_VERSION
|
8
8
|
end
|
9
9
|
|
10
10
|
should 'convert an Ox document to an XML string' do
|
@@ -22,7 +22,7 @@ module Synapse
|
|
22
22
|
|
23
23
|
class XmlToOxDocumentConverterTest < Test::Unit::TestCase
|
24
24
|
def setup
|
25
|
-
|
25
|
+
omit 'Ox not supported on JRuby' if defined? JRUBY_VERSION
|
26
26
|
end
|
27
27
|
|
28
28
|
should 'convert an XML string to an Ox document' do
|
@@ -6,7 +6,7 @@ module Synapse
|
|
6
6
|
|
7
7
|
class OjSerializerTest < Test::Unit::TestCase
|
8
8
|
def setup
|
9
|
-
|
9
|
+
omit 'Oj not supported on JRuby' if defined? JRUBY_VERSION
|
10
10
|
end
|
11
11
|
|
12
12
|
should 'support serializing and deserializing content' do
|
data/test/test_helper.rb
CHANGED
@@ -8,19 +8,18 @@ else
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
# Need this for Contender, since we get it from GitHub for now
|
12
|
+
require 'bundler/setup'
|
13
|
+
|
12
14
|
require 'synapse'
|
15
|
+
|
16
|
+
require 'pp'
|
13
17
|
require 'test/unit'
|
14
|
-
require '
|
15
|
-
|
18
|
+
require 'test/unit/rr'
|
19
|
+
|
16
20
|
require 'timecop'
|
21
|
+
require 'shoulda/context'
|
17
22
|
|
18
23
|
require 'test_ext'
|
19
24
|
|
20
|
-
# I guess RR broke
|
21
|
-
# http://stackoverflow.com/questions/3657972
|
22
|
-
unless defined? Test::Unit::AssertionFailedError
|
23
|
-
Test::Unit::AssertionFailedError = ActiveSupport::TestCase::Assertion
|
24
|
-
end
|
25
|
-
|
26
25
|
ActiveSupport::Autoload.eager_autoload!
|
data/test/uow/uow_test.rb
CHANGED
@@ -159,8 +159,8 @@ module Synapse
|
|
159
159
|
|
160
160
|
should 'rollback if an aggregate storage callback raises an exception' do
|
161
161
|
aggregate_root = Object.new
|
162
|
-
|
163
|
-
|
162
|
+
stub(aggregate_root).add_registration_listener
|
163
|
+
stub(aggregate_root).id
|
164
164
|
|
165
165
|
event_bus = Object.new
|
166
166
|
cause = TestError.new
|