synapse-core 0.5.4 → 0.5.5

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.
Files changed (44) hide show
  1. data/lib/synapse/command/async_command_bus.rb +3 -5
  2. data/lib/synapse/common.rb +0 -1
  3. data/lib/synapse/configuration/component/command_bus/async_command_bus.rb +3 -2
  4. data/lib/synapse/configuration/component/{mixin → shared}/thread_pool.rb +10 -8
  5. data/lib/synapse/configuration/dependent.rb +2 -2
  6. data/lib/synapse/configuration/ext.rb +58 -29
  7. data/lib/synapse/configuration.rb +1 -1
  8. data/lib/synapse/domain/aggregate_root.rb +43 -19
  9. data/lib/synapse/domain/errors.rb +9 -0
  10. data/lib/synapse/domain/event_container.rb +3 -3
  11. data/lib/synapse/domain/message.rb +2 -2
  12. data/lib/synapse/domain/message_builder.rb +2 -2
  13. data/lib/synapse/domain/simple_stream.rb +39 -0
  14. data/lib/synapse/domain/stream.rb +2 -41
  15. data/lib/synapse/domain.rb +3 -0
  16. data/lib/synapse/event_sourcing/aggregate_root.rb +102 -2
  17. data/lib/synapse/event_sourcing/caching.rb +1 -1
  18. data/lib/synapse/event_sourcing/entity.rb +2 -2
  19. data/lib/synapse/event_sourcing/member.rb +3 -13
  20. data/lib/synapse/event_sourcing/repository.rb +9 -2
  21. data/lib/synapse/event_sourcing/snapshot/taker.rb +2 -2
  22. data/lib/synapse/mapping/mapping.rb +2 -2
  23. data/lib/synapse/process_manager/simple_process_manager.rb +1 -0
  24. data/lib/synapse/rails/injection_helper.rb +23 -0
  25. data/lib/synapse/railtie.rb +17 -0
  26. data/lib/synapse/repository/lock_manager.rb +3 -3
  27. data/lib/synapse/uow/listener.rb +2 -2
  28. data/lib/synapse/uow/listener_collection.rb +7 -51
  29. data/lib/synapse/version.rb +1 -1
  30. data/lib/synapse-core.rb +1 -0
  31. data/lib/synapse.rb +3 -0
  32. data/test/command/async_command_bus_test.rb +8 -11
  33. data/test/configuration/component/command_bus/async_command_bus_test.rb +7 -6
  34. data/test/configuration/component/serialization/serializer_test.rb +2 -2
  35. data/test/configuration/fixtures/dependent.rb +1 -1
  36. data/test/rails/injection_helper_test.rb +27 -0
  37. data/test/serialization/converter/ox_test.rb +2 -2
  38. data/test/serialization/serializer/oj_test.rb +1 -1
  39. data/test/serialization/serializer/ox_test.rb +1 -1
  40. data/test/test_helper.rb +8 -9
  41. data/test/uow/uow_test.rb +2 -2
  42. metadata +221 -222
  43. data/lib/synapse/common/concurrency/executor.rb +0 -13
  44. 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; end
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
@@ -55,6 +55,6 @@ module Synapse
55
55
  def hash
56
56
  @type.hash
57
57
  end
58
- end
59
- end
58
+ end # Mapping
59
+ end # Mapping
60
60
  end
@@ -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
@@ -74,6 +74,6 @@ module Synapse
74
74
  # @param [UnitOfWork] unit
75
75
  # @return [undefined]
76
76
  def on_cleanup(unit); end
77
- end
78
- end
77
+ end # UnitOfWorkListener
78
+ end # UnitOfWork
79
79
  end
@@ -22,10 +22,7 @@ module Synapse
22
22
  # @param [UnitOfWorkListener] listener
23
23
  # @return [undefined]
24
24
  def push(listener)
25
- if @logger.debug?
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
- if @logger.debug?
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
- if @logger.debug?
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
- if @logger.debug?
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
- if @logger.debug?
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
- if @logger.debug?
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
- if @logger.debug?
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
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = '0.5.4'
2
+ VERSION = '0.5.5'
3
3
  end
@@ -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 = Thread.pool 2
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
- handler = TestAsyncHandler.new x
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
- wait_until do
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
- attr_reader :latch
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
- assert_equal 4, thread_pool.min
20
- assert_equal 4, thread_pool.max
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 size' do
24
+ should 'build with a custom thread pool options' do
24
25
  @builder.async_command_bus do
25
- use_threads 2, 8
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
- assert_equal 2, thread_pool.min
32
- assert_equal 8, thread_pool.max
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
- skip 'Ox not supported on JRuby' if defined? JRUBY_VERSION
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
- skip 'Oj not supported on JRuby' if defined? JRUBY_VERSION
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 }
@@ -4,7 +4,7 @@ module Synapse
4
4
  include Dependent
5
5
 
6
6
  depends_on :service_a
7
- depends_on :service_b, :attribute => :some_service
7
+ depends_on :service_b, :as => :some_service
8
8
  end
9
9
  end
10
10
  end
@@ -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
- skip 'Ox not supported on JRuby' if defined? JRUBY_VERSION
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
- skip 'Ox not supported on JRuby' if defined? JRUBY_VERSION
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
- skip 'Oj not supported on JRuby' if defined? JRUBY_VERSION
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
@@ -6,7 +6,7 @@ module Synapse
6
6
 
7
7
  class OxSerializerTest < Test::Unit::TestCase
8
8
  def setup
9
- skip 'Ox not supported on JRuby' if defined? JRUBY_VERSION
9
+ omit 'Ox not supported on JRuby' if defined? JRUBY_VERSION
10
10
 
11
11
  @serializer = OxSerializer.new ConverterFactory.new
12
12
  end
data/test/test_helper.rb CHANGED
@@ -8,19 +8,18 @@ else
8
8
  end
9
9
  end
10
10
 
11
- require 'pp'
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 'shoulda/context'
15
- require 'rr'
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
- mock(aggregate_root).add_registration_listener
163
- mock(aggregate_root).id
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