synapse-core 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/lib/synapse/auditing/audit_logger.rb +28 -0
  2. data/lib/synapse/auditing/data_provider.rb +42 -0
  3. data/lib/synapse/auditing/dispatch_interceptor.rb +29 -0
  4. data/lib/synapse/auditing/unit_listener.rb +53 -0
  5. data/lib/synapse/auditing.rb +4 -0
  6. data/lib/synapse/command.rb +34 -0
  7. data/lib/synapse/{duplication.rb → common/duplication.rb} +0 -0
  8. data/lib/synapse/{errors.rb → common/errors.rb} +0 -0
  9. data/lib/synapse/{identifier.rb → common/identifier.rb} +2 -1
  10. data/lib/synapse/{message.rb → common/message.rb} +0 -0
  11. data/lib/synapse/{message_builder.rb → common/message_builder.rb} +0 -0
  12. data/lib/synapse/domain.rb +5 -0
  13. data/lib/synapse/event_bus.rb +5 -0
  14. data/lib/synapse/event_sourcing/conflict_resolver.rb +4 -6
  15. data/lib/synapse/event_sourcing/member.rb +11 -2
  16. data/lib/synapse/event_sourcing/snapshot/taker.rb +0 -18
  17. data/lib/synapse/event_sourcing.rb +13 -0
  18. data/lib/synapse/event_store/mongo/cursor_event_stream.rb +3 -3
  19. data/lib/synapse/event_store/mongo.rb +8 -0
  20. data/lib/synapse/event_store.rb +11 -0
  21. data/lib/synapse/partitioning/amqp/amqp_queue_reader.rb +50 -0
  22. data/lib/synapse/partitioning/amqp/amqp_queue_writer.rb +31 -0
  23. data/lib/synapse/partitioning/amqp/key_resolver.rb +26 -0
  24. data/lib/synapse/partitioning/amqp.rb +3 -0
  25. data/lib/synapse/partitioning/memory_queue_reader.rb +31 -0
  26. data/lib/synapse/partitioning/memory_queue_writer.rb +19 -0
  27. data/lib/synapse/partitioning/message_receipt.rb +25 -0
  28. data/lib/synapse/partitioning/packing/json_packer.rb +93 -0
  29. data/lib/synapse/partitioning/packing/json_unpacker.rb +83 -0
  30. data/lib/synapse/partitioning/packing.rb +27 -0
  31. data/lib/synapse/partitioning/queue_reader.rb +32 -0
  32. data/lib/synapse/partitioning/queue_writer.rb +17 -0
  33. data/lib/synapse/partitioning.rb +20 -0
  34. data/lib/synapse/process_manager.rb +4 -0
  35. data/lib/synapse/repository/locking.rb +3 -8
  36. data/lib/synapse/repository.rb +7 -0
  37. data/lib/synapse/serialization/converter/bson.rb +28 -0
  38. data/lib/synapse/serialization/serializer/attribute.rb +48 -0
  39. data/lib/synapse/serialization/serializer.rb +1 -1
  40. data/lib/synapse/serialization.rb +46 -0
  41. data/lib/synapse/uow/factory.rb +5 -5
  42. data/lib/synapse/uow/uow.rb +13 -13
  43. data/lib/synapse/uow.rb +8 -0
  44. data/lib/synapse/upcasting/chain.rb +1 -1
  45. data/lib/synapse/upcasting.rb +5 -0
  46. data/lib/synapse/version.rb +1 -1
  47. data/lib/synapse/wiring.rb +3 -0
  48. data/lib/synapse.rb +26 -338
  49. data/test/auditing/data_provider_test.rb +30 -0
  50. data/test/auditing/dispatch_interceptor_test.rb +25 -0
  51. data/test/auditing/unit_listener_test.rb +70 -0
  52. data/test/partitioning/memory_test.rb +34 -0
  53. data/test/partitioning/packing/json_test.rb +61 -0
  54. data/test/test_ext.rb +14 -0
  55. data/test/test_helper.rb +4 -0
  56. metadata +45 -24
  57. data/test/event_sourcing/snapshot/deferred_taker_test.rb +0 -19
data/lib/synapse.rb CHANGED
@@ -1,351 +1,39 @@
1
1
  require 'active_support'
2
2
  require 'active_support/core_ext'
3
- require 'eventmachine'
4
3
  require 'logging'
5
4
  require 'set'
6
5
 
7
6
  require 'synapse/version'
8
7
 
8
+ require 'synapse/common/errors'
9
+ require 'synapse/common/identifier'
10
+ require 'synapse/common/message'
11
+ require 'synapse/common/message_builder'
12
+
9
13
  module Synapse
10
14
  extend ActiveSupport::Autoload
11
15
 
12
- eager_autoload do
13
- autoload_at 'synapse/errors' do
14
- autoload :SynapseError
15
- autoload :ConfigurationError
16
- autoload :NonTransientError
17
- autoload :TransientError
18
- end
19
-
20
- autoload_at 'synapse/identifier' do
21
- autoload :IdentifierFactory
22
- autoload :GuidIdentifierFactory
23
- end
24
-
25
- autoload :Message
26
- autoload :MessageBuilder
27
-
28
- autoload_at 'synapse/duplication' do
29
- autoload :DuplicationError
30
- autoload :DuplicationRecorder
31
- end
32
- end
33
-
34
- module Command
35
- extend ActiveSupport::Autoload
36
-
37
- eager_autoload do
38
- autoload :CommandBus
39
- autoload :SimpleCommandBus
40
-
41
- autoload :CommandCallback
42
- autoload :CommandFilter
43
- autoload :CommandHandler
44
-
45
- autoload_at 'synapse/command/message' do
46
- autoload :CommandMessage
47
- autoload :CommandMessageBuilder
48
- end
49
-
50
- autoload :CommandGateway, 'synapse/command/gateway'
51
-
52
- autoload :DispatchInterceptor
53
- autoload :InterceptorChain
54
-
55
- autoload_at 'synapse/command/duplication' do
56
- autoload :DuplicationFilter
57
- autoload :DuplicationCleanupInterceptor
58
- end
59
-
60
- autoload_at 'synapse/command/errors' do
61
- autoload :CommandExecutionError
62
- autoload :CommandValidationError
63
- autoload :NoHandlerError
64
- end
65
-
66
- autoload_at 'synapse/command/filters/validation' do
67
- autoload :ActiveModelValidationFilter
68
- autoload :ActiveModelValidationError
69
- end
70
-
71
- autoload_at 'synapse/command/interceptors/serialization' do
72
- autoload :SerializationOptimizingInterceptor
73
- autoload :SerializationOptimizingListener
74
- end
75
-
76
- autoload_at 'synapse/command/rollback_policy' do
77
- autoload :RollbackPolicy
78
- autoload :RollbackOnAnyExceptionPolicy
79
- end
80
-
81
- autoload :WiringCommandHandler, 'synapse/command/wiring'
82
- end
16
+ autoload_at 'synapse/common/duplication' do
17
+ autoload :DuplicationError
18
+ autoload :DuplicationRecorder
83
19
  end
84
20
 
85
- module Domain
86
- extend ActiveSupport::Autoload
87
-
88
- eager_autoload do
89
- autoload_at 'synapse/domain/aggregate_root' do
90
- autoload :AggregateRoot
91
- autoload :AggregateIdentifierNotInitializedError
92
- end
93
-
94
- autoload :EventContainer
95
-
96
- autoload_at 'synapse/domain/message' do
97
- autoload :EventMessage
98
- autoload :DomainEventMessage
99
- end
100
-
101
- autoload_at 'synapse/domain/message_builder' do
102
- autoload :EventMessageBuilder
103
- autoload :DomainEventMessageBuilder
104
- end
105
-
106
- autoload_at 'synapse/domain/stream' do
107
- autoload :DomainEventStream
108
- autoload :EndOfStreamError
109
- autoload :SimpleDomainEventStream
110
- end
111
- end
112
- end
113
-
114
- module EventBus
115
- extend ActiveSupport::Autoload
116
-
117
- eager_autoload do
118
- autoload_at 'synapse/event_bus/event_bus' do
119
- autoload :EventBus
120
- autoload :SubscriptionFailedError
121
- end
122
-
123
- autoload :EventListener
124
- autoload :EventListenerProxy
125
- autoload :SimpleEventBus
126
- autoload :WiringEventListener, 'synapse/event_bus/wiring'
127
- end
128
- end
129
-
130
- module EventSourcing
131
- extend ActiveSupport::Autoload
132
-
133
- eager_autoload do
134
- autoload_at 'synapse/event_sourcing/aggregate_factory' do
135
- autoload :AggregateFactory
136
- autoload :GenericAggregateFactory
137
- end
138
-
139
- autoload :AggregateRoot
140
- autoload :Entity
141
- autoload :Member
142
-
143
- autoload :EventSourcingRepository, 'synapse/event_sourcing/repository'
144
- autoload :EventSourcedStorageListener, 'synapse/event_sourcing/storage_listener'
145
- autoload :EventStreamDecorator, 'synapse/event_sourcing/stream_decorator'
146
-
147
- autoload_at 'synapse/event_sourcing/conflict_resolver' do
148
- autoload :ConflictResolver
149
- autoload :ConflictResolvingUnitOfWorkListener
150
- autoload :CapturingEventStream
151
- end
152
-
153
- autoload_at 'synapse/event_sourcing/snapshot/taker' do
154
- autoload :AggregateSnapshotTaker
155
- autoload :DeferredSnapshotTaker
156
- autoload :SnapshotTaker
157
- end
158
-
159
- autoload_at 'synapse/event_sourcing/snapshot/count_stream' do
160
- autoload :CountingEventStream
161
- autoload :TriggeringEventStream
162
- autoload :SnapshotUnitOfWorkListener
163
- end
164
-
165
- autoload :EventCountSnapshotTrigger, 'synapse/event_sourcing/snapshot/count_trigger'
166
- end
167
- end
168
-
169
- module EventStore
170
- extend ActiveSupport::Autoload
171
-
172
- eager_autoload do
173
- autoload_at 'synapse/event_store/errors' do
174
- autoload :EventStoreError
175
- autoload :StreamNotFoundError
176
- end
177
-
178
- autoload_at 'synapse/event_store/event_store' do
179
- autoload :EventStore
180
- autoload :SnapshotEventStore
181
- end
182
- end
183
-
184
- autoload :InMemoryEventStore, 'synapse/event_store/in_memory'
185
-
186
- module Mongo
187
- extend ActiveSupport::Autoload
188
-
189
- autoload :CursorDomainEventStream, 'synapse/event_store/mongo/cursor_event_stream'
190
- autoload :MongoEventStore, 'synapse/event_store/mongo/event_store'
191
- autoload :DocumentPerEventStrategy, 'synapse/event_store/mongo/per_event_strategy'
192
- autoload :DocumentPerCommitStrategy, 'synapse/event_store/mongo/per_commit_strategy'
193
- autoload :StorageStrategy, 'synapse/event_store/mongo/storage_strategy'
194
-
195
- autoload_at 'synapse/event_store/mongo/template' do
196
- autoload :MongoTemplate
197
- autoload :DefaultMongoTemplate
198
- end
199
- end
200
- end
201
-
202
- module ProcessManager
203
- extend ActiveSupport::Autoload
204
-
205
- autoload :Correlation
206
- autoload :CorrelationResolver
207
- autoload :CorrelationSet
208
-
209
- autoload :Process
210
- end
211
-
212
- module Repository
213
- extend ActiveSupport::Autoload
214
-
215
- eager_autoload do
216
- autoload_at 'synapse/repository/errors' do
217
- autoload :AggregateNotFoundError
218
- autoload :ConcurrencyError
219
- autoload :ConflictingAggregateVersionError
220
- autoload :ConflictingModificationError
221
- end
222
-
223
- autoload :LockManager
224
- autoload :PessimisticLockManager
225
-
226
- autoload_at 'synapse/repository/locking' do
227
- autoload :LockingRepository
228
- autoload :LockCleaningUnitOfWorkListener
229
- end
230
-
231
- autoload :Repository
232
- end
233
- end
234
-
235
- module Serialization
236
- extend ActiveSupport::Autoload
237
-
238
- eager_autoload do
239
- autoload :Converter
240
- autoload :ConverterFactory, 'synapse/serialization/converter/factory'
241
- autoload :IdentityConverter, 'synapse/serialization/converter/identity'
242
-
243
- autoload_at 'synapse/serialization/errors' do
244
- autoload :ConversionError
245
- autoload :SerializationError
246
- autoload :UnknownSerializedTypeError
247
- end
248
-
249
- autoload_at 'synapse/serialization/lazy_object' do
250
- autoload :DeserializedObject
251
- autoload :LazyObject
252
- end
253
-
254
- autoload_at 'synapse/serialization/revision_resolver' do
255
- autoload :RevisionResolver
256
- autoload :FixedRevisionResolver
257
- end
258
-
259
- autoload :SerializedDomainEventData, 'synapse/serialization/message/data'
260
- autoload :MessageSerializer, 'synapse/serialization/message/serializer'
261
- autoload :SerializedMetadata, 'synapse/serialization/message/metadata'
262
- autoload :SerializationAware, 'synapse/serialization/message/serialization_aware'
263
- autoload :SerializedObjectCache, 'synapse/serialization/message/serialized_object_cache'
264
-
265
- autoload_at 'synapse/serialization/message/serialization_aware_message' do
266
- autoload :SerializationAwareEventMessage
267
- autoload :SerializationAwareDomainEventMessage
268
- end
269
-
270
- autoload_at 'synapse/serialization/message/serialized_message' do
271
- autoload :SerializedMessage
272
- autoload :SerializedEventMessage
273
- autoload :SerializedDomainEventMessage
274
- end
275
-
276
- autoload_at 'synapse/serialization/message/serialized_message_builder' do
277
- autoload :SerializedMessageBuilder
278
- autoload :SerializedEventMessageBuilder
279
- autoload :SerializedDomainEventMessageBuilder
280
- end
281
-
282
- autoload :Serializer
283
- autoload :SerializedObject
284
- autoload :SerializedType
285
- end
286
-
287
- autoload_at 'synapse/serialization/converter/json' do
288
- autoload :JsonToObjectConverter
289
- autoload :ObjectToJsonConverter
290
- end
291
-
292
- autoload_at 'synapse/serialization/converter/ox' do
293
- autoload :XmlToOxDocumentConverter
294
- autoload :OxDocumentToXmlConverter
295
- end
296
-
297
- autoload :OjSerializer, 'synapse/serialization/serializer/oj'
298
- autoload :OxSerializer, 'synapse/serialization/serializer/ox'
299
- autoload :MarshalSerializer, 'synapse/serialization/serializer/marshal'
300
- end
301
-
302
- module UnitOfWork
303
- extend ActiveSupport::Autoload
304
-
305
- eager_autoload do
306
- autoload_at 'synapse/uow/nesting' do
307
- autoload :NestableUnitOfWork
308
- autoload :OuterCommitUnitOfWorkListener
309
- end
310
-
311
- autoload :StorageListener, 'synapse/uow/storage_listener'
312
- autoload :TransactionManager, 'synapse/uow/transaction_manager'
313
- autoload :UnitOfWork, 'synapse/uow/uow'
314
- autoload :UnitOfWorkFactory, 'synapse/uow/factory'
315
- autoload :UnitOfWorkListener, 'synapse/uow/listener'
316
- autoload :UnitOfWorkListenerCollection, 'synapse/uow/listener_collection'
317
- autoload :UnitOfWorkProvider, 'synapse/uow/provider'
318
- end
319
- end
320
-
321
- module Upcasting
322
- extend ActiveSupport::Autoload
323
-
324
- autoload :SingleUpcaster
325
- autoload :Upcaster
326
- autoload :UpcasterChain, 'synapse/upcasting/chain'
327
-
328
- autoload_at 'synapse/upcasting/context' do
329
- autoload :UpcastingContext
330
- autoload :SerializedDomainEventUpcastingContext
331
- end
332
-
333
- autoload :UpcastSerializedDomainEventData, 'synapse/upcasting/data'
334
- end
335
-
336
- module Wiring
337
- extend ActiveSupport::Autoload
338
-
339
- autoload :MessageWiring
340
- autoload :Wire
341
- autoload :WireRegistry
342
- end
343
-
344
- # TODO this is more of an application call
345
- ActiveSupport::Autoload.eager_autoload!
346
-
347
- # Setup the default identifier factory
348
- ActiveSupport.on_load :identifier_factory do
349
- IdentifierFactory.instance = GuidIdentifierFactory.new
350
- end
21
+ eager_autoload do
22
+ # Common components
23
+ autoload :Command
24
+ autoload :Domain
25
+ autoload :EventBus
26
+ autoload :Repository
27
+ autoload :Serialization
28
+ autoload :UnitOfWork, 'synapse/uow'
29
+ autoload :Wiring
30
+ end
31
+
32
+ # Optional components
33
+ autoload :Auditing
34
+ autoload :EventSourcing
35
+ autoload :EventStore
36
+ autoload :Partitioning
37
+ autoload :ProcessManager
38
+ autoload :Upcasting
351
39
  end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Auditing
5
+
6
+ class CommandMetadataProviderTest < Test::Unit::TestCase
7
+ def test_provide_data_for
8
+ data = { foo: 0 }
9
+
10
+ provider = CommandMetadataProvider.new
11
+ command = Command::CommandMessage.build do |builder|
12
+ builder.metadata = data
13
+ end
14
+
15
+ assert_equal data, provider.provide_data_for(command)
16
+ end
17
+ end
18
+
19
+ class CorrelationDataProviderTest < Test::Unit::TestCase
20
+ def test_provide_data_for
21
+ provider = CorrelationDataProvider.new
22
+ command = Command::CommandMessage.build
23
+
24
+ expected = { :command_id => command.id }
25
+ assert_equal expected, provider.provide_data_for(command)
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Auditing
5
+
6
+ class AuditingDispatchInterceptorTest < Test::Unit::TestCase
7
+ def test_intercept
8
+ return_value = Object.new
9
+ chain = Object.new
10
+ command = Object.new
11
+ unit = Object.new
12
+
13
+ interceptor = AuditingDispatchInterceptor.new
14
+
15
+ mock(unit).register_listener(is_a(AuditingUnitOfWorkListener))
16
+ mock(chain).proceed(command) do
17
+ return_value
18
+ end
19
+
20
+ assert_equal return_value, interceptor.intercept(command, unit, chain)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Auditing
5
+
6
+ class AuditingUnitOfWorkListenerTest < Test::Unit::TestCase
7
+ def test_on_event_registered
8
+ data_provider_a = Object.new
9
+ data_provider_b = Object.new
10
+
11
+ command = Object.new
12
+ data_providers = [data_provider_a, data_provider_b]
13
+ loggers = []
14
+
15
+ listener = AuditingUnitOfWorkListener.new command, data_providers, loggers
16
+
17
+ event = Object.new
18
+
19
+ data_a = { foo: 0 }
20
+ data_b = { bar: 1 }
21
+
22
+ mock(data_provider_a).provide_data_for(command) { data_a }
23
+ mock(data_provider_b).provide_data_for(command) { data_b }
24
+
25
+ mock(event).and_metadata(data_a.merge(data_b)) { event }
26
+
27
+ out = listener.on_event_registered(Object.new, event)
28
+
29
+ assert_same event, out
30
+ assert listener.recorded_events.include? event
31
+ end
32
+
33
+ def test_after_commit
34
+ logger = Object.new
35
+
36
+ command = Object.new
37
+ return_value = Object.new
38
+ data_providers = []
39
+ loggers = [logger]
40
+ event = Object.new
41
+
42
+ mock(logger).on_success(command, return_value, [event])
43
+
44
+ listener = AuditingUnitOfWorkListener.new command, data_providers, loggers
45
+ listener.return_value = return_value
46
+ listener.recorded_events.push event
47
+
48
+ listener.after_commit Object.new
49
+ end
50
+
51
+ def test_on_rollback
52
+ logger = Object.new
53
+
54
+ command = Object.new
55
+ exception = Exception.new
56
+ data_providers = []
57
+ loggers = [logger]
58
+ event = Object.new
59
+
60
+ mock(logger).on_success(command, exception, [event])
61
+
62
+ listener = AuditingUnitOfWorkListener.new command, data_providers, loggers
63
+ listener.recorded_events.push event
64
+
65
+ listener.on_rollback Object.new, exception
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Partitioning
5
+
6
+ class MemoryQueueTest < Test::Unit::TestCase
7
+ def test_queuing
8
+ message = MessageBuilder.build
9
+
10
+ queue = Queue.new
11
+
12
+ reader = MemoryQueueReader.new queue, :test
13
+ writer = MemoryQueueWriter.new queue
14
+
15
+ count = 0
16
+
17
+ Thread.new do
18
+ reader.subscribe do |receipt|
19
+ assert_equal message, receipt.packed
20
+ assert_equal :test, receipt.queue_name
21
+
22
+ count = count.next
23
+ end
24
+ end
25
+
26
+ writer.put_message message, message
27
+ writer.put_message message, message
28
+
29
+ wait_until { count == 2 }
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Partitioning
5
+
6
+ class JsonPackingTest < Test::Unit::TestCase
7
+ def setup
8
+ @serializer = Serialization::MarshalSerializer.new
9
+ @packer = JsonMessagePacker.new @serializer
10
+ @unpacker = JsonMessageUnpacker.new @serializer
11
+ end
12
+
13
+ def test_packing
14
+ message = Domain::DomainEventMessage.build do |builder|
15
+ builder.metadata = { foo: 0 }
16
+ builder.payload = { bar: 1 }
17
+ builder.aggregate_id = '123'
18
+ builder.sequence_number = 1
19
+ end
20
+
21
+ packed = @packer.pack_message message
22
+ unpacked = @unpacker.unpack_message packed
23
+
24
+ assert_equal message.id, unpacked.id
25
+ assert_equal message.metadata, unpacked.metadata
26
+ assert_equal message.payload, unpacked.payload
27
+ assert_equal message.timestamp.to_i, unpacked.timestamp.to_i
28
+ assert_equal message.aggregate_id, unpacked.aggregate_id
29
+ assert_equal message.sequence_number, unpacked.sequence_number
30
+ end
31
+
32
+ def test_type_packing
33
+ [Command::CommandMessage, Domain::EventMessage, Domain::DomainEventMessage].each do |type|
34
+ message = type.build
35
+ packed = @packer.pack_message message
36
+ unpacked = @unpacker.unpack_message packed
37
+
38
+ assert type === unpacked
39
+ end
40
+ end
41
+
42
+ def test_unknown_type
43
+ message = Message.build
44
+
45
+ assert_raise ArgumentError do
46
+ @packer.pack_message message
47
+ end
48
+
49
+ packed = {
50
+ message_type: :message
51
+ }
52
+ packed = JSON.dump packed
53
+
54
+ assert_raise ArgumentError do
55
+ @unpacker.unpack_message packed
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+ end
data/test/test_ext.rb ADDED
@@ -0,0 +1,14 @@
1
+ class Test::Unit::TestCase
2
+ # Blocks until a condition is met or a timeout occurs
3
+ #
4
+ # @param [Integer] timeout In seconds
5
+ # @param [Float] retry_interval In seconds
6
+ # @return [undefined]
7
+ def wait_until(timeout = 2, retry_interval = 0.1, &block)
8
+ start = Time.now
9
+ until !!block.call
10
+ raise if (Time.now - start).to_i >= timeout
11
+ sleep retry_interval
12
+ end
13
+ end
14
+ end
data/test/test_helper.rb CHANGED
@@ -14,6 +14,10 @@ require 'rr'
14
14
  require 'timecop'
15
15
  require 'synapse'
16
16
 
17
+ require 'test_ext'
18
+
17
19
  class Test::Unit::TestCase
18
20
  include RR::Adapters::TestUnit
19
21
  end
22
+
23
+ ActiveSupport::Autoload.eager_autoload!