synapse-core 0.5.1 → 0.5.2

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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/lib/synapse.rb +1 -1
  3. data/lib/synapse/command.rb +1 -1
  4. data/lib/synapse/command/command_handler.rb +1 -1
  5. data/lib/synapse/command/mapping.rb +71 -0
  6. data/lib/synapse/command/message.rb +0 -16
  7. data/lib/synapse/command/simple_command_bus.rb +5 -2
  8. data/lib/synapse/common/message.rb +16 -0
  9. data/lib/synapse/configuration.rb +1 -18
  10. data/lib/synapse/configuration/component/command_bus.rb +7 -24
  11. data/lib/synapse/configuration/component/command_bus/simple_command_bus.rb +31 -7
  12. data/lib/synapse/configuration/component/event_bus.rb +3 -8
  13. data/lib/synapse/configuration/component/event_sourcing.rb +11 -8
  14. data/lib/synapse/configuration/component/event_sourcing/aggregate_snapshot_taker.rb +48 -0
  15. data/lib/synapse/configuration/component/event_sourcing/interval_snapshot_policy.rb +33 -0
  16. data/lib/synapse/configuration/component/event_sourcing/repository.rb +36 -1
  17. data/lib/synapse/configuration/component/repository.rb +4 -8
  18. data/lib/synapse/configuration/component/serialization.rb +5 -16
  19. data/lib/synapse/configuration/component/uow.rb +3 -8
  20. data/lib/synapse/configuration/component/upcasting.rb +3 -8
  21. data/lib/synapse/configuration/container_builder.rb +29 -2
  22. data/lib/synapse/configuration/definition_builder.rb +47 -23
  23. data/lib/synapse/domain/message.rb +0 -16
  24. data/lib/synapse/event_bus.rb +1 -1
  25. data/lib/synapse/event_bus/event_listener.rb +1 -1
  26. data/lib/synapse/event_bus/mapping.rb +47 -0
  27. data/lib/synapse/event_sourcing.rb +3 -2
  28. data/lib/synapse/event_sourcing/aggregate_factory.rb +4 -3
  29. data/lib/synapse/event_sourcing/aggregate_root.rb +17 -0
  30. data/lib/synapse/event_sourcing/conflict_resolver.rb +3 -0
  31. data/lib/synapse/event_sourcing/member.rb +34 -6
  32. data/lib/synapse/event_sourcing/repository.rb +17 -0
  33. data/lib/synapse/event_sourcing/snapshot/aggregate_taker.rb +38 -0
  34. data/lib/synapse/event_sourcing/snapshot/policy.rb +27 -0
  35. data/lib/synapse/event_sourcing/snapshot/taker.rb +2 -37
  36. data/lib/synapse/event_sourcing/snapshot/unit_listener.rb +26 -0
  37. data/lib/synapse/event_sourcing/stream_decorator.rb +8 -6
  38. data/lib/synapse/event_store/errors.rb +2 -2
  39. data/lib/synapse/mapping.rb +2 -0
  40. data/lib/synapse/mapping/mapper.rb +75 -0
  41. data/lib/synapse/{wiring/wire.rb → mapping/mapping.rb} +8 -8
  42. data/lib/synapse/process_manager.rb +2 -2
  43. data/lib/synapse/process_manager/mapping/process.rb +44 -0
  44. data/lib/synapse/process_manager/{wiring → mapping}/process_manager.rb +13 -13
  45. data/lib/synapse/process_manager/process.rb +3 -3
  46. data/lib/synapse/repository/locking.rb +14 -8
  47. data/lib/synapse/upcasting/upcaster_chain.rb +2 -2
  48. data/lib/synapse/version.rb +1 -1
  49. data/test/command/{wiring_test.rb → mapping_test.rb} +11 -11
  50. data/test/configuration/component/command_bus/simple_command_bus_test.rb +30 -0
  51. data/test/configuration/component/event_bus/simple_event_bus_test.rb +2 -2
  52. data/test/configuration/component/event_sourcing/repository_test.rb +71 -0
  53. data/test/configuration/component/repository/simple_repository_test.rb +35 -0
  54. data/test/configuration/component/upcasting/upcaster_chain_test.rb +29 -0
  55. data/test/configuration/container_builder_test.rb +4 -6
  56. data/test/event_bus/{wiring_test.rb → mapping_test.rb} +6 -6
  57. data/test/event_sourcing/aggregate_factory_test.rb +5 -1
  58. data/test/event_sourcing/aggregate_root_test.rb +1 -0
  59. data/test/event_sourcing/fixtures.rb +21 -21
  60. data/test/event_sourcing/repository_test.rb +10 -0
  61. data/test/event_sourcing/snapshot/aggregate_taker_test.rb +1 -1
  62. data/test/event_sourcing/snapshot/interval_policy_test.rb +24 -0
  63. data/test/process_manager/{wiring → mapping}/fixtures.rb +7 -8
  64. data/test/process_manager/{wiring → mapping}/process_manager_test.rb +6 -6
  65. data/test/process_manager/{wiring → mapping}/process_test.rb +3 -3
  66. data/test/serialization/converter/chain_test.rb +2 -2
  67. data/test/serialization/converter/factory_test.rb +2 -2
  68. data/test/serialization/converter/identity_test.rb +1 -1
  69. data/test/serialization/converter/json_test.rb +2 -2
  70. data/test/serialization/converter/ox_test.rb +2 -2
  71. data/test/serialization/lazy_object_test.rb +1 -1
  72. data/test/serialization/message/metadata_test.rb +1 -1
  73. data/test/serialization/message/serialization_aware_message_test.rb +5 -5
  74. data/test/serialization/message/serialized_message_builder_test.rb +1 -1
  75. data/test/serialization/message/serialized_message_test.rb +5 -5
  76. data/test/serialization/message/serializer_test.rb +2 -2
  77. data/test/serialization/revision_resolver_test.rb +1 -1
  78. data/test/serialization/serialized_object_test.rb +2 -2
  79. data/test/serialization/serialized_type_test.rb +2 -2
  80. data/test/serialization/serializer/marshal_test.rb +1 -1
  81. data/test/serialization/serializer/oj_test.rb +1 -1
  82. data/test/serialization/serializer/ox_test.rb +2 -2
  83. data/test/serialization/serializer_test.rb +1 -1
  84. data/test/uow/factory_test.rb +1 -1
  85. data/test/uow/outer_commit_listener_test.rb +4 -4
  86. data/test/uow/provider_test.rb +5 -5
  87. data/test/uow/uow_test.rb +19 -17
  88. data/test/upcasting/chain_test.rb +1 -1
  89. data/test/upcasting/data_test.rb +3 -1
  90. metadata +30 -37
  91. data/lib/synapse/command/wiring.rb +0 -47
  92. data/lib/synapse/event_bus/wiring.rb +0 -20
  93. data/lib/synapse/event_sourcing/snapshot/count_stream.rb +0 -86
  94. data/lib/synapse/event_sourcing/snapshot/count_trigger.rb +0 -91
  95. data/lib/synapse/process_manager/wiring/process.rb +0 -27
  96. data/lib/synapse/wiring.rb +0 -3
  97. data/lib/synapse/wiring/message_wiring.rb +0 -76
  98. data/lib/synapse/wiring/wire_registry.rb +0 -61
  99. data/test/event_sourcing/snapshot/integration_test.rb +0 -65
  100. data/test/wiring/wire_registry_test.rb +0 -60
  101. data/test/wiring/wire_test.rb +0 -51
@@ -1,17 +1,17 @@
1
1
  module Synapse
2
- module Wiring
2
+ module Mapping
3
3
  # Represents a mapping between a payload type and a handler method or block
4
4
  #
5
- # Wires are ordered by the depth of the payload type that they handle. Wires that are
6
- # for a more specific class are preferred over wires for an abstract class.
7
- class Wire
8
- # @return [Class] The type of payload that a handler is being wired to
5
+ # Mappings are ordered by the depth of the payload type that they handle. Mappings that are
6
+ # for a more specific class are preferred over mappings for an abstract class.
7
+ class Mapping
8
+ # @return [Class] The type of payload that a handler is being mapped to
9
9
  attr_reader :type
10
10
 
11
11
  # @return [Object] Either a method symbol or block
12
12
  attr_reader :handler
13
13
 
14
- # @return [Hash] Options specific to the component being wired
14
+ # @return [Hash] Options specific to the component being mapped
15
15
  attr_reader :options
16
16
 
17
17
  # @param [Class] type
@@ -35,13 +35,13 @@ module Synapse
35
35
  end
36
36
  end
37
37
 
38
- # @param [Wire] other
38
+ # @param [Mapping] other
39
39
  # @return [Integer]
40
40
  def <=>(other)
41
41
  (@type <=> other.type) or 0
42
42
  end
43
43
 
44
- # @param [Wire] other
44
+ # @param [Mapping] other
45
45
  # @return [Boolean]
46
46
  def ==(other)
47
47
  self.class === other and
@@ -12,7 +12,7 @@ require 'synapse/process_manager/resource_injector'
12
12
  require 'synapse/process_manager/container_resource_injector'
13
13
  require 'synapse/process_manager/simple_process_manager'
14
14
 
15
- require 'synapse/process_manager/wiring/process'
16
- require 'synapse/process_manager/wiring/process_manager'
15
+ require 'synapse/process_manager/mapping/process'
16
+ require 'synapse/process_manager/mapping/process_manager'
17
17
 
18
18
  require 'synapse/process_manager/repository/in_memory'
@@ -0,0 +1,44 @@
1
+ module Synapse
2
+ module ProcessManager
3
+ # Process that has the mapping DSL built-in
4
+ #
5
+ # @example
6
+ # class OrderProcess < MappingProcess
7
+ # map_event OrderCreatedEvent, correlate: :order_id, start: true do |event|
8
+ # # ...
9
+ # end
10
+ #
11
+ # map_event OrderFinishedEvent, correlate: :order_id, finish: true, to: :on_finish
12
+ # end
13
+ #
14
+ # @abstract
15
+ class MappingProcess < Process
16
+ # @return [Mapping::Mapper]
17
+ class_attribute :event_mapper
18
+
19
+ self.event_mapper = Mapping::Mapper.new true
20
+
21
+ # @see Mapper#map
22
+ # @param [Class] type
23
+ # @param [Object...] args
24
+ # @param [Proc] block
25
+ # @return [undefined]
26
+ def self.map_event(type, *args, &block)
27
+ event_mapper.map type, *args, &block
28
+ end
29
+
30
+ # @param [EventMessage] event
31
+ # @return [undefined]
32
+ def handle(event)
33
+ return unless @active
34
+
35
+ mapping = event_mapper.mapping_for event.payload_type
36
+
37
+ return unless mapping
38
+
39
+ mapping.invoke self, event.payload
40
+ finish if mapping.options[:finish]
41
+ end
42
+ end # MappingProcess
43
+ end # ProcessManager
44
+ end
@@ -1,9 +1,9 @@
1
1
  module Synapse
2
2
  module ProcessManager
3
- # Process manager that is aware of processes that use the wiring DSL
4
- # @see WiringProcess
5
- class WiringProcessManager < ProcessManager
6
- # @raise [ArgumentError] If a process type is given that doesn't support the wiring DSL
3
+ # Process manager that is aware of processes that use the mapping DSL
4
+ # @see MappingProcess
5
+ class MappingProcessManager < ProcessManager
6
+ # @raise [ArgumentError] If a process type is given that doesn't support the mapping DSL
7
7
  # @param [ProcessRepository] repository
8
8
  # @param [ProcessFactory] factory
9
9
  # @param [LockManager] lock_manager
@@ -13,7 +13,7 @@ module Synapse
13
13
  super
14
14
 
15
15
  @process_types.each do |process_type|
16
- unless process_type.respond_to? :wire_registry
16
+ unless process_type.respond_to? :event_mapper
17
17
  raise ArgumentError, 'Incompatible process type %s' % process_type
18
18
  end
19
19
  end
@@ -25,12 +25,12 @@ module Synapse
25
25
  # @param [EventMessage] event
26
26
  # @return [Symbol]
27
27
  def creation_policy_for(process_type, event)
28
- wire = process_type.wire_registry.wire_for event.payload_type
28
+ mapping = process_type.event_mapper.mapping_for event.payload_type
29
29
 
30
- if wire
31
- if !wire.options[:start]
30
+ if mapping
31
+ if !mapping.options[:start]
32
32
  :none
33
- elsif wire.options[:force_new]
33
+ elsif mapping.options[:force_new]
34
34
  :always
35
35
  else
36
36
  :if_none_found
@@ -42,11 +42,11 @@ module Synapse
42
42
  # @param [EventMessage] event
43
43
  # @return [Correlation] Returns nil if no correlation could be extracted
44
44
  def extract_correlation(process_type, event)
45
- wire = process_type.wire_registry.wire_for event.payload_type
45
+ mapping = process_type.event_mapper.mapping_for event.payload_type
46
46
 
47
- return unless wire
47
+ return unless mapping
48
48
 
49
- correlation_key = wire.options[:correlate]
49
+ correlation_key = mapping.options[:correlate]
50
50
  if correlation_key
51
51
  correlation_value event.payload, correlation_key
52
52
  end
@@ -67,6 +67,6 @@ module Synapse
67
67
  Correlation.new correlation_key, value
68
68
  end
69
69
  end
70
- end # WiringProcessManager
70
+ end # MappingProcessManager
71
71
  end # ProcessManager
72
72
  end
@@ -6,7 +6,7 @@ module Synapse
6
6
  # "maintain the state of the sequence and determine the next processing step based on
7
7
  # intermediate results" (Hohpe 279). Processes are also called sagas in some CQRS frameworks.
8
8
  #
9
- # Consider using the implementation of a process that uses message wiring.
9
+ # Consider using the implementation of a process that uses the mapping DSL.
10
10
  #
11
11
  # @abstract
12
12
  class Process
@@ -72,6 +72,6 @@ module Synapse
72
72
  def finish
73
73
  @active = false
74
74
  end
75
- end
76
- end
75
+ end # Process
76
+ end # ProcessManager
77
77
  end
@@ -10,7 +10,6 @@ module Synapse
10
10
  # @return [undefined]
11
11
  def initialize(lock_manager)
12
12
  @lock_manager = lock_manager
13
- @logger = Logging.logger[self.class]
14
13
  end
15
14
 
16
15
  # @api public
@@ -27,12 +26,13 @@ module Synapse
27
26
  begin
28
27
  aggregate = perform_load aggregate_id, expected_version
29
28
 
30
- register_aggregate(aggregate).tap do
31
- register_listener LockCleaningUnitOfWorkListener.new aggregate_id, @lock_manager
32
- end
33
- rescue
34
- @logger.debug 'Excepton raised while loading an aggregate, releasing lock'
29
+ register_aggregate aggregate
30
+ register_listener LockCleaningUnitOfWorkListener.new aggregate_id, @lock_manager
31
+
32
+ post_registration aggregate
35
33
 
34
+ aggregate
35
+ rescue
36
36
  @lock_manager.release_lock aggregate_id
37
37
  raise
38
38
  end
@@ -50,9 +50,9 @@ module Synapse
50
50
 
51
51
  register_aggregate aggregate
52
52
  register_listener LockCleaningUnitOfWorkListener.new aggregate.id, @lock_manager
53
- rescue
54
- @logger.debug 'Exception raised while adding an aggregate, releasing lock'
55
53
 
54
+ post_registration aggregate
55
+ rescue
56
56
  @lock_manager.release_lock aggregate.id
57
57
  raise
58
58
  end
@@ -71,6 +71,12 @@ module Synapse
71
71
  # @param [Integer] expected_version
72
72
  # @return [AggregateRoot]
73
73
  def perform_load(aggregate_id, expected_version); end
74
+
75
+ # Hook that is called after an aggregate is registered to the current unit of work
76
+ #
77
+ # @param [AggregateRoot] aggregate
78
+ # @return [undefined]
79
+ def post_registration(aggregate); end
74
80
  end # LockingRepository
75
81
 
76
82
  # Unit of work listener that releases the lock on an aggregate when the unit of work
@@ -2,10 +2,10 @@ module Synapse
2
2
  module Upcasting
3
3
  class UpcasterChain
4
4
  # @return [ConverterFactory]
5
- attr_accessor :converter_factory
5
+ attr_reader :converter_factory
6
6
 
7
7
  # @return [Array<Upcaster>]
8
- attr_accessor :upcasters
8
+ attr_reader :upcasters
9
9
 
10
10
  # @param [ConverterFactory] converter_factory
11
11
  # @return [undefined]
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = '0.5.1'
2
+ VERSION = '0.5.2'
3
3
  end
@@ -3,9 +3,9 @@ require 'test_helper'
3
3
  module Synapse
4
4
  module Command
5
5
 
6
- class WiringCommandHandlerTest < Test::Unit::TestCase
7
- should 'pass the command to the correct wire' do
8
- handler = ExampleWiringCommandHandler.new
6
+ class MappingCommandHandlerTest < Test::Unit::TestCase
7
+ should 'pass the command to the correct mapped handler' do
8
+ handler = ExampleMappingCommandHandler.new
9
9
  unit = Object.new
10
10
 
11
11
  command = CommandMessage.build do |builder|
@@ -31,8 +31,8 @@ module Synapse
31
31
  end
32
32
  end
33
33
 
34
- should 'subscribe handler to the command bus for each wired command type' do
35
- handler = ExampleWiringCommandHandler.new
34
+ should 'subscribe handler to the command bus for each mapped command type' do
35
+ handler = ExampleMappingCommandHandler.new
36
36
  bus = Object.new
37
37
 
38
38
  mock(bus).subscribe(TestSubCommand, handler)
@@ -41,8 +41,8 @@ module Synapse
41
41
  handler.subscribe bus
42
42
  end
43
43
 
44
- should 'unsubscribe handler from the command bus for each wired command type' do
45
- handler = ExampleWiringCommandHandler.new
44
+ should 'unsubscribe handler from the command bus for each mapped command type' do
45
+ handler = ExampleMappingCommandHandler.new
46
46
  bus = Object.new
47
47
 
48
48
  mock(bus).unsubscribe(TestSubCommand, handler)
@@ -55,16 +55,16 @@ module Synapse
55
55
  class TestCommand; end
56
56
  class TestSubCommand; end
57
57
 
58
- class ExampleWiringCommandHandler
59
- include WiringCommandHandler
58
+ class ExampleMappingCommandHandler
59
+ include MappingCommandHandler
60
60
 
61
61
  attr_accessor :handled, :sub_handled
62
62
 
63
- wire TestCommand do |command|
63
+ map_command TestCommand do |command|
64
64
  @handled = true
65
65
  end
66
66
 
67
- wire TestSubCommand do |command|
67
+ map_command TestSubCommand do |command|
68
68
  @sub_handled = true
69
69
  end
70
70
  end
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  module Synapse
4
4
  module Configuration
5
5
  class SimpleCommandBusDefinitionFactoryTest < Test::Unit::TestCase
6
+
6
7
  def setup
7
8
  @container = Container.new
8
9
  @builder = ContainerBuilder.new @container
@@ -52,6 +53,35 @@ module Synapse
52
53
  mock(handler_b).subscribe(is_a(Command::SimpleCommandBus))
53
54
  command_bus = @container.resolve :alt_command_bus
54
55
  end
56
+
57
+ should 'build and register tagged command interceptors' do
58
+ @builder.factory :serialization_interceptor, :tag => :dispatch_interceptor do
59
+ Command::SerializationOptimizingInterceptor.new
60
+ end
61
+
62
+ @builder.unit_factory
63
+ @builder.simple_command_bus
64
+
65
+ command_bus = @container.resolve :command_bus
66
+ serialization_interceptor = @container.resolve :serialization_interceptor
67
+
68
+ assert_include command_bus.interceptors, serialization_interceptor
69
+ end
70
+
71
+ should 'build and register tagged command filters' do
72
+ @builder.factory :validation_filter, :tag => :command_filter do
73
+ Command::ActiveModelValidationFilter.new
74
+ end
75
+
76
+ @builder.unit_factory
77
+ @builder.simple_command_bus
78
+
79
+ command_bus = @container.resolve :command_bus
80
+ validation_filter = @container.resolve :validation_filter
81
+
82
+ assert_include command_bus.filters, validation_filter
83
+ end
84
+
55
85
  end
56
86
  end
57
87
  end
@@ -49,10 +49,10 @@ module Synapse
49
49
  end
50
50
 
51
51
  class TestEventListener
52
- include EventBus::WiringEventListener
52
+ include EventBus::MappingEventListener
53
53
  end
54
54
  class TestAltEventListener
55
- include EventBus::WiringEventListener
55
+ include EventBus::MappingEventListener
56
56
  end
57
57
  end
58
58
  end
@@ -0,0 +1,71 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Configuration
5
+ class EventSourcingRepositoryDefinitionBuilderTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @container = Container.new
9
+ @builder = ContainerBuilder.new @container
10
+ end
11
+
12
+ should 'build with sensible defaults' do
13
+ # Repository needs unit of work provider (initialized by default)
14
+ # Repository needs event bus
15
+ @builder.simple_event_bus
16
+
17
+ # LockingRepository needs a locking manager (pessimistic by default)
18
+ # EventSourcingRepository needs an event store
19
+ @builder.factory :event_store do
20
+ Object.new
21
+ end
22
+
23
+ # EventSourcingRepository needs an aggregate factory
24
+ @builder.es_repository :account_repository do
25
+ use_aggregate_type Object
26
+ end
27
+
28
+ repository = @container.resolve :account_repository
29
+
30
+ event_bus = @container.resolve :event_bus
31
+ event_store = @container.resolve :event_store
32
+ unit_provider = @container.resolve :unit_provider
33
+
34
+ assert_same event_bus, repository.event_bus
35
+ assert_same event_store, repository.event_store
36
+ assert_same unit_provider, repository.unit_provider
37
+
38
+ assert_instance_of Repository::PessimisticLockManager, repository.lock_manager
39
+ end
40
+
41
+ should 'build with optional components' do
42
+ @builder.simple_event_bus
43
+ @builder.factory :event_store do
44
+ Object.new
45
+ end
46
+
47
+ @builder.aggregate_snapshot_taker
48
+ @builder.interval_snapshot_policy
49
+
50
+ @builder.factory :conflict_resolver do
51
+ EventSourcing::ConflictResolver.new
52
+ end
53
+
54
+ @builder.es_repository :account_repository do
55
+ use_aggregate_type Object
56
+ end
57
+
58
+ repository = @container.resolve :account_repository
59
+
60
+ conflict_resolver = @container.resolve :conflict_resolver
61
+ snapshot_policy = @container.resolve :snapshot_policy
62
+ snapshot_taker = @container.resolve :snapshot_taker
63
+
64
+ assert_same conflict_resolver, repository.conflict_resolver
65
+ assert_same snapshot_policy, repository.snapshot_policy
66
+ assert_same snapshot_taker, repository.snapshot_taker
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Configuration
5
+ class SimpleRepositoryDefinitionBuilderTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @container = Container.new
9
+ @builder = ContainerBuilder.new @container
10
+ end
11
+
12
+ should 'build with sensible defaults' do
13
+ # Repository needs unit of work provider (initialized by default)
14
+ # Repository needs event bus
15
+ @builder.simple_event_bus
16
+
17
+ # SimpleRepository needs an aggregate type
18
+ @builder.simple_repository :account_repository do
19
+ use_aggregate_type Object
20
+ end
21
+
22
+ repository = @container.resolve :account_repository
23
+
24
+ event_bus = @container.resolve :event_bus
25
+ unit_provider = @container.resolve :unit_provider
26
+
27
+ assert_same event_bus, repository.event_bus
28
+ assert_same unit_provider, repository.unit_provider
29
+
30
+ assert_instance_of Repository::PessimisticLockManager, repository.lock_manager
31
+ end
32
+
33
+ end
34
+ end
35
+ end