synapse-core 0.5.1 → 0.5.2

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