synapse-core 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/lib/synapse.rb +351 -0
  2. data/lib/synapse/command/command_bus.rb +45 -0
  3. data/lib/synapse/command/command_callback.rb +18 -0
  4. data/lib/synapse/command/command_filter.rb +17 -0
  5. data/lib/synapse/command/command_handler.rb +13 -0
  6. data/lib/synapse/command/dispatch_interceptor.rb +16 -0
  7. data/lib/synapse/command/duplication.rb +43 -0
  8. data/lib/synapse/command/errors.rb +27 -0
  9. data/lib/synapse/command/filters/validation.rb +32 -0
  10. data/lib/synapse/command/gateway.rb +34 -0
  11. data/lib/synapse/command/interceptor_chain.rb +31 -0
  12. data/lib/synapse/command/interceptors/serialization.rb +35 -0
  13. data/lib/synapse/command/message.rb +19 -0
  14. data/lib/synapse/command/rollback_policy.rb +22 -0
  15. data/lib/synapse/command/simple_command_bus.rb +138 -0
  16. data/lib/synapse/command/wiring.rb +47 -0
  17. data/lib/synapse/domain/aggregate_root.rb +121 -0
  18. data/lib/synapse/domain/event_container.rb +127 -0
  19. data/lib/synapse/domain/message.rb +82 -0
  20. data/lib/synapse/domain/message_builder.rb +34 -0
  21. data/lib/synapse/domain/stream.rb +108 -0
  22. data/lib/synapse/duplication.rb +60 -0
  23. data/lib/synapse/errors.rb +13 -0
  24. data/lib/synapse/event_bus/event_bus.rb +40 -0
  25. data/lib/synapse/event_bus/event_listener.rb +16 -0
  26. data/lib/synapse/event_bus/event_listener_proxy.rb +12 -0
  27. data/lib/synapse/event_bus/simple_event_bus.rb +69 -0
  28. data/lib/synapse/event_bus/wiring.rb +23 -0
  29. data/lib/synapse/event_sourcing/aggregate_factory.rb +69 -0
  30. data/lib/synapse/event_sourcing/aggregate_root.rb +104 -0
  31. data/lib/synapse/event_sourcing/conflict_resolver.rb +80 -0
  32. data/lib/synapse/event_sourcing/entity.rb +64 -0
  33. data/lib/synapse/event_sourcing/member.rb +72 -0
  34. data/lib/synapse/event_sourcing/repository.rb +119 -0
  35. data/lib/synapse/event_sourcing/snapshot/count_stream.rb +86 -0
  36. data/lib/synapse/event_sourcing/snapshot/count_trigger.rb +91 -0
  37. data/lib/synapse/event_sourcing/snapshot/taker.rb +73 -0
  38. data/lib/synapse/event_sourcing/storage_listener.rb +34 -0
  39. data/lib/synapse/event_sourcing/stream_decorator.rb +25 -0
  40. data/lib/synapse/event_store/errors.rb +16 -0
  41. data/lib/synapse/event_store/event_store.rb +43 -0
  42. data/lib/synapse/event_store/in_memory.rb +59 -0
  43. data/lib/synapse/event_store/mongo/cursor_event_stream.rb +63 -0
  44. data/lib/synapse/event_store/mongo/event_store.rb +86 -0
  45. data/lib/synapse/event_store/mongo/per_commit_strategy.rb +253 -0
  46. data/lib/synapse/event_store/mongo/per_event_strategy.rb +143 -0
  47. data/lib/synapse/event_store/mongo/storage_strategy.rb +113 -0
  48. data/lib/synapse/event_store/mongo/template.rb +73 -0
  49. data/lib/synapse/identifier.rb +23 -0
  50. data/lib/synapse/message.rb +101 -0
  51. data/lib/synapse/message_builder.rb +38 -0
  52. data/lib/synapse/process_manager/correlation.rb +32 -0
  53. data/lib/synapse/process_manager/correlation_resolver.rb +14 -0
  54. data/lib/synapse/process_manager/correlation_set.rb +58 -0
  55. data/lib/synapse/process_manager/process.rb +71 -0
  56. data/lib/synapse/repository/errors.rb +26 -0
  57. data/lib/synapse/repository/lock_manager.rb +40 -0
  58. data/lib/synapse/repository/locking.rb +97 -0
  59. data/lib/synapse/repository/pessimistic_lock_manager.rb +61 -0
  60. data/lib/synapse/repository/repository.rb +109 -0
  61. data/lib/synapse/serialization/converter.rb +39 -0
  62. data/lib/synapse/serialization/converter/chain.rb +45 -0
  63. data/lib/synapse/serialization/converter/factory.rb +68 -0
  64. data/lib/synapse/serialization/converter/identity.rb +29 -0
  65. data/lib/synapse/serialization/converter/json.rb +31 -0
  66. data/lib/synapse/serialization/converter/ox.rb +31 -0
  67. data/lib/synapse/serialization/errors.rb +12 -0
  68. data/lib/synapse/serialization/lazy_object.rb +61 -0
  69. data/lib/synapse/serialization/message/data.rb +25 -0
  70. data/lib/synapse/serialization/message/metadata.rb +13 -0
  71. data/lib/synapse/serialization/message/serialization_aware.rb +17 -0
  72. data/lib/synapse/serialization/message/serialization_aware_message.rb +66 -0
  73. data/lib/synapse/serialization/message/serialized_message.rb +201 -0
  74. data/lib/synapse/serialization/message/serialized_message_builder.rb +64 -0
  75. data/lib/synapse/serialization/message/serialized_object_cache.rb +50 -0
  76. data/lib/synapse/serialization/message/serializer.rb +47 -0
  77. data/lib/synapse/serialization/revision_resolver.rb +30 -0
  78. data/lib/synapse/serialization/serialized_object.rb +37 -0
  79. data/lib/synapse/serialization/serialized_type.rb +31 -0
  80. data/lib/synapse/serialization/serializer.rb +98 -0
  81. data/lib/synapse/serialization/serializer/marshal.rb +32 -0
  82. data/lib/synapse/serialization/serializer/oj.rb +34 -0
  83. data/lib/synapse/serialization/serializer/ox.rb +31 -0
  84. data/lib/synapse/uow/factory.rb +28 -0
  85. data/lib/synapse/uow/listener.rb +79 -0
  86. data/lib/synapse/uow/listener_collection.rb +93 -0
  87. data/lib/synapse/uow/nesting.rb +262 -0
  88. data/lib/synapse/uow/provider.rb +71 -0
  89. data/lib/synapse/uow/storage_listener.rb +14 -0
  90. data/lib/synapse/uow/transaction_manager.rb +27 -0
  91. data/lib/synapse/uow/uow.rb +178 -0
  92. data/lib/synapse/upcasting/chain.rb +78 -0
  93. data/lib/synapse/upcasting/context.rb +58 -0
  94. data/lib/synapse/upcasting/data.rb +30 -0
  95. data/lib/synapse/upcasting/single_upcaster.rb +57 -0
  96. data/lib/synapse/upcasting/upcaster.rb +55 -0
  97. data/lib/synapse/version.rb +3 -0
  98. data/lib/synapse/wiring/message_wiring.rb +41 -0
  99. data/lib/synapse/wiring/wire.rb +55 -0
  100. data/lib/synapse/wiring/wire_registry.rb +61 -0
  101. data/test/command/duplication_test.rb +54 -0
  102. data/test/command/gateway_test.rb +25 -0
  103. data/test/command/interceptor_chain_test.rb +26 -0
  104. data/test/command/serialization_test.rb +37 -0
  105. data/test/command/simple_command_bus_test.rb +141 -0
  106. data/test/command/validation_test.rb +42 -0
  107. data/test/command/wiring_test.rb +73 -0
  108. data/test/domain/aggregate_root_test.rb +57 -0
  109. data/test/domain/fixtures.rb +31 -0
  110. data/test/domain/message_test.rb +61 -0
  111. data/test/domain/stream_test.rb +35 -0
  112. data/test/duplication_test.rb +40 -0
  113. data/test/event_bus/wiring_test.rb +46 -0
  114. data/test/event_sourcing/aggregate_factory_test.rb +28 -0
  115. data/test/event_sourcing/aggregate_root_test.rb +76 -0
  116. data/test/event_sourcing/entity_test.rb +34 -0
  117. data/test/event_sourcing/fixtures.rb +85 -0
  118. data/test/event_sourcing/repository_test.rb +102 -0
  119. data/test/event_sourcing/snapshot/aggregate_taker_test.rb +39 -0
  120. data/test/event_sourcing/snapshot/deferred_taker_test.rb +19 -0
  121. data/test/event_sourcing/snapshot/integration_test.rb +65 -0
  122. data/test/event_sourcing/storage_listener_test.rb +77 -0
  123. data/test/event_store/in_memory_test.rb +47 -0
  124. data/test/process_manager/correlation_set_test.rb +49 -0
  125. data/test/process_manager/correlation_test.rb +24 -0
  126. data/test/process_manager/process_test.rb +52 -0
  127. data/test/repository/locking_test.rb +101 -0
  128. data/test/serialization/converter/factory_test.rb +33 -0
  129. data/test/serialization/converter/identity_test.rb +17 -0
  130. data/test/serialization/converter/json_test.rb +31 -0
  131. data/test/serialization/converter/ox_test.rb +40 -0
  132. data/test/serialization/fixtures.rb +17 -0
  133. data/test/serialization/lazy_object_test.rb +32 -0
  134. data/test/serialization/message/metadata_test.rb +19 -0
  135. data/test/serialization/message/serialization_aware_message_test.rb +88 -0
  136. data/test/serialization/message/serialized_message_builder_test.rb +41 -0
  137. data/test/serialization/message/serialized_message_test.rb +140 -0
  138. data/test/serialization/message/serializer_test.rb +50 -0
  139. data/test/serialization/revision_resolver_test.rb +12 -0
  140. data/test/serialization/serialized_object_test.rb +36 -0
  141. data/test/serialization/serialized_type_test.rb +27 -0
  142. data/test/serialization/serializer/marshal_test.rb +22 -0
  143. data/test/serialization/serializer/oj_test.rb +24 -0
  144. data/test/serialization/serializer/ox_test.rb +36 -0
  145. data/test/serialization/serializer_test.rb +20 -0
  146. data/test/test_helper.rb +19 -0
  147. data/test/uow/factory_test.rb +23 -0
  148. data/test/uow/outer_commit_listener_test.rb +50 -0
  149. data/test/uow/provider_test.rb +70 -0
  150. data/test/uow/uow_test.rb +337 -0
  151. data/test/upcasting/chain_test.rb +29 -0
  152. data/test/upcasting/fixtures.rb +66 -0
  153. data/test/wiring/wire_registry_test.rb +60 -0
  154. data/test/wiring/wire_test.rb +51 -0
  155. metadata +263 -0
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+ class DuplicationFilterTest < Test::Unit::TestCase
6
+ def test_filter
7
+ recorder = DuplicationRecorder.new
8
+ filter = DuplicationFilter.new recorder
9
+
10
+ command = CommandMessage.build
11
+
12
+ result = filter.filter command
13
+
14
+ assert_same command, result
15
+ assert recorder.recorded? command
16
+ end
17
+ end
18
+
19
+ class DuplicationCleanupInterceptorTest < Test::Unit::TestCase
20
+ def test_intercept
21
+ recorder = DuplicationRecorder.new
22
+ interceptor = DuplicationCleanupInterceptor.new recorder
23
+
24
+ command = CommandMessage.build
25
+ unit = Object.new
26
+
27
+ chain = Object.new
28
+ mock(chain).proceed(command) do
29
+ raise TransientError
30
+ end
31
+
32
+ recorder.record command
33
+
34
+ assert_raise TransientError do
35
+ interceptor.intercept command, unit, chain
36
+ end
37
+
38
+ refute recorder.recorded? command
39
+
40
+ mock(chain).proceed(command) do
41
+ raise ArgumentError
42
+ end
43
+
44
+ recorder.record command
45
+
46
+ assert_raise ArgumentError do
47
+ interceptor.intercept command, unit, chain
48
+ end
49
+
50
+ assert recorder.recorded? command
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+
6
+ class CommandGatewayTest < Test::Unit::TestCase
7
+ def test_send
8
+ command_bus = Object.new
9
+ gateway = CommandGateway.new command_bus
10
+
11
+ command = Object.new
12
+ command_message = CommandMessage.build do |builder|
13
+ builder.payload = command
14
+ end
15
+
16
+ mock(command_bus).dispatch(is_a(CommandMessage)).ordered
17
+ mock(command_bus).dispatch(command_message).ordered
18
+
19
+ gateway.send command
20
+ gateway.send command_message
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+
6
+ class InterceptorChainTest < Test::Unit::TestCase
7
+ def test_proceed
8
+ unit = Object.new
9
+ interceptor = Object.new
10
+ interceptors = Array.new << interceptor
11
+ handler = Object.new
12
+
13
+ command = Object.new
14
+
15
+ chain = InterceptorChain.new unit, interceptors, handler
16
+
17
+ mock(interceptor).intercept(command, unit, chain).ordered
18
+ mock(handler).handle(command, unit).ordered
19
+
20
+ chain.proceed command
21
+ chain.proceed command
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+
6
+ class SerializationOptimizingInterceptorTest < Test::Unit::TestCase
7
+ def test_intercept
8
+ interceptor = SerializationOptimizingInterceptor.new
9
+
10
+ command = CommandMessage.build
11
+ chain = Object.new
12
+ unit = Object.new
13
+
14
+ mock(chain).proceed(command)
15
+ mock(unit).register_listener(is_a(SerializationOptimizingListener))
16
+
17
+ interceptor.intercept(command, unit, chain)
18
+ end
19
+ end
20
+
21
+ class SerializationOptimizingListenerTest < Test::Unit::TestCase
22
+ def test_on_event_registered
23
+ listener = SerializationOptimizingListener.new
24
+ unit = Object.new
25
+
26
+ event = Domain::DomainEventMessage.build
27
+ decorated = listener.on_event_registered unit, event
28
+ assert decorated.is_a? Serialization::SerializationAwareDomainEventMessage
29
+
30
+ event = Domain::EventMessage.build
31
+ decorated = listener.on_event_registered unit, event
32
+ assert decorated.is_a? Serialization::SerializationAwareEventMessage
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,141 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+
6
+ class SimpleCommandBusTest < Test::Unit::TestCase
7
+ def setup
8
+ @unit_factory = Object.new
9
+ @unit = Object.new
10
+ @command_bus = SimpleCommandBus.new @unit_factory
11
+ @logger = Logging.logger[@command_bus.class]
12
+
13
+ mock(@unit_factory).create.any_times do
14
+ @unit
15
+ end
16
+ end
17
+
18
+ def test_dispatch
19
+ handler = Object.new
20
+ command = CommandMessage.build do |m|
21
+ m.payload = TestCommand.new
22
+ end
23
+
24
+ mock(handler).handle(command, @unit)
25
+ mock(@unit).commit
26
+
27
+ @command_bus.subscribe TestCommand, handler
28
+ @command_bus.dispatch command
29
+ end
30
+
31
+ def test_dispatch_result
32
+ handler = Object.new
33
+ callback = Object.new
34
+ command = CommandMessage.build do |m|
35
+ m.payload = TestCommand.new
36
+ end
37
+
38
+ result = 123
39
+
40
+ mock(handler).handle(command, @unit) do
41
+ result
42
+ end
43
+ mock(callback).on_success(result)
44
+ mock(@unit).commit
45
+
46
+ @command_bus.subscribe TestCommand, handler
47
+ @command_bus.dispatch_with_callback command, callback
48
+ end
49
+
50
+ def test_dispatch_no_handler
51
+ command = CommandMessage.build do |m|
52
+ m.payload = TestCommand.new
53
+ end
54
+
55
+ callback = Object.new
56
+ mock(callback).on_failure(is_a(NoHandlerError))
57
+
58
+ @command_bus.dispatch_with_callback command, callback
59
+ end
60
+
61
+ def test_dispatch_rollback_on_exception
62
+ handler = Object.new
63
+ command = CommandMessage.build do |m|
64
+ m.payload = TestCommand.new
65
+ end
66
+
67
+ exception = TypeError.new
68
+
69
+ mock(handler).handle(command, @unit) do
70
+ raise exception
71
+ end
72
+
73
+ mock(@logger).error(anything)
74
+ mock(@unit).rollback(exception)
75
+
76
+ @command_bus.subscribe TestCommand, handler
77
+
78
+ callback = Object.new
79
+ mock(callback).on_failure(is_a(CommandExecutionError))
80
+
81
+ @command_bus.dispatch_with_callback command, callback
82
+ end
83
+
84
+ def test_dispatch_commit_on_exception
85
+ handler = Object.new
86
+ command = CommandMessage.build do |m|
87
+ m.payload = TestCommand.new
88
+ end
89
+
90
+ exception = TypeError.new
91
+
92
+ mock(handler).handle(command, @unit) do
93
+ raise exception
94
+ end
95
+
96
+ rollback_policy = Object.new
97
+ mock(rollback_policy).should_rollback(exception) do
98
+ false
99
+ end
100
+ mock(@unit).commit
101
+
102
+ @command_bus.rollback_policy = rollback_policy
103
+ @command_bus.subscribe TestCommand, handler
104
+
105
+ callback = Object.new
106
+ mock(callback).on_failure(is_a(CommandExecutionError))
107
+
108
+ @command_bus.dispatch_with_callback command, callback
109
+ end
110
+
111
+ def test_subscribe
112
+ handler = Object.new
113
+
114
+ mock(@logger).debug(anything).ordered
115
+ mock(@logger).info(anything).ordered
116
+
117
+ @command_bus.subscribe TestCommand, handler
118
+ @command_bus.subscribe TestCommand, handler
119
+ end
120
+
121
+ def test_unsubscribe
122
+ handler_a = Object.new
123
+ handler_b = Object.new
124
+
125
+ mock(@logger).info(anything).ordered # not subscribed to anyone
126
+ mock(@logger).debug(anything).ordered # now subscribed
127
+ mock(@logger).info(anything).ordered # subscribed to different
128
+ mock(@logger).debug(anything).ordered # now unsubscribed
129
+
130
+ @command_bus.unsubscribe TestCommand, handler_a
131
+ @command_bus.subscribe TestCommand, handler_a
132
+ @command_bus.unsubscribe TestCommand, handler_b
133
+ @command_bus.unsubscribe TestCommand, handler_a
134
+ end
135
+ end
136
+
137
+ class TestCommand; end
138
+ class TestOtherCommand; end
139
+
140
+ end
141
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+ require 'active_model'
3
+
4
+ module Synapse
5
+ module Command
6
+
7
+ class ActiveModelValidationFilterTest < Test::Unit::TestCase
8
+ def test_filter
9
+ message = CommandMessage.build do |m|
10
+ m.payload = CreatePersonCommand.new 'River'
11
+ end
12
+
13
+ filter = ActiveModelValidationFilter.new
14
+ filter.filter message
15
+ end
16
+
17
+ def test_filter_fails
18
+ message = CommandMessage.build do |m|
19
+ m.payload = CreatePersonCommand.new nil
20
+ end
21
+
22
+ filter = ActiveModelValidationFilter.new
23
+ assert_raise ActiveModelValidationError do
24
+ filter.filter message
25
+ end
26
+ end
27
+ end
28
+
29
+ class CreatePersonCommand
30
+ include ActiveModel::Validations
31
+
32
+ attr_reader :name
33
+
34
+ validates :name, :presence => true
35
+
36
+ def initialize(name)
37
+ @name = name
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,73 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Command
5
+
6
+ class WiringCommandHandlerTest < Test::Unit::TestCase
7
+ def test_handle
8
+ handler = ExampleWiringCommandHandler.new
9
+ unit = Object.new
10
+
11
+ command = CommandMessage.build do |builder|
12
+ builder.payload = TestCommand.new
13
+ end
14
+
15
+ handler.handle command, unit
16
+ assert handler.handled
17
+
18
+ command = CommandMessage.build do |builder|
19
+ builder.payload = TestSubCommand.new
20
+ end
21
+
22
+ handler.handle command, unit
23
+ assert handler.sub_handled
24
+
25
+ command = CommandMessage.build do |builder|
26
+ builder.payload = 5
27
+ end
28
+
29
+ assert_raise ArgumentError do
30
+ handler.handle command, unit
31
+ end
32
+ end
33
+
34
+ def test_subscribe
35
+ handler = ExampleWiringCommandHandler.new
36
+ bus = Object.new
37
+
38
+ mock(bus).subscribe(TestSubCommand, handler)
39
+ mock(bus).subscribe(TestCommand, handler)
40
+
41
+ handler.subscribe bus
42
+ end
43
+
44
+ def test_unsubscribe
45
+ handler = ExampleWiringCommandHandler.new
46
+ bus = Object.new
47
+
48
+ mock(bus).unsubscribe(TestSubCommand, handler)
49
+ mock(bus).unsubscribe(TestCommand, handler)
50
+
51
+ handler.unsubscribe bus
52
+ end
53
+ end
54
+
55
+ class TestCommand; end
56
+ class TestSubCommand; end
57
+
58
+ class ExampleWiringCommandHandler
59
+ include WiringCommandHandler
60
+
61
+ attr_accessor :handled, :sub_handled
62
+
63
+ wire TestCommand do |command|
64
+ @handled = true
65
+ end
66
+
67
+ wire TestSubCommand do |command|
68
+ @sub_handled = true
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+ require 'domain/fixtures'
3
+
4
+ module Synapse
5
+ module Domain
6
+ class AggregateRootTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @person = Person.new 123, 'Fry'
10
+ end
11
+
12
+ def test_publish_events
13
+ assert_equal 0, @person.uncommitted_event_count
14
+
15
+ @person.change_name 'Leela'
16
+
17
+ events = Array.new
18
+
19
+ @person.add_registration_listener do |event|
20
+ events.push event
21
+ event
22
+ end
23
+
24
+ @person.change_name 'Bender'
25
+
26
+ assert_equal 2, @person.uncommitted_event_count
27
+ assert_equal events, @person.uncommitted_events.to_a
28
+ end
29
+
30
+ def test_mark_committed
31
+ @person.change_name 'Bender'
32
+ @person.mark_committed
33
+
34
+ assert_equal 0, @person.uncommitted_event_count
35
+ end
36
+
37
+ def test_mark_deleted
38
+ @person.delete
39
+
40
+ assert @person.deleted?
41
+ end
42
+
43
+ def test_identifier_not_initialized
44
+ p = Person.new nil, nil
45
+
46
+ assert_raise AggregateIdentifierNotInitializedError do
47
+ p.change_name 'Zoidberg'
48
+ end
49
+ end
50
+
51
+ def test_empty_uncommitted_events
52
+ assert @person.uncommitted_events.end?
53
+ end
54
+
55
+ end
56
+ end
57
+ end