synapse-core 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/lib/synapse/auditing/command_metadata_provider.rb +12 -0
  2. data/lib/synapse/auditing/correlation_data_provider.rb +19 -0
  3. data/lib/synapse/auditing/data_provider.rb +2 -30
  4. data/lib/synapse/auditing/dispatch_interceptor.rb +6 -5
  5. data/lib/synapse/auditing/unit_listener.rb +7 -6
  6. data/lib/synapse/auditing.rb +2 -0
  7. data/lib/synapse/configuration/component/command_bus/gateway.rb +1 -0
  8. data/lib/synapse/configuration/component/command_bus/simple_command_bus.rb +9 -1
  9. data/lib/synapse/configuration/component/event_bus/simple_event_bus.rb +1 -0
  10. data/lib/synapse/configuration/component/event_sourcing/aggregate_snapshot_taker.rb +7 -0
  11. data/lib/synapse/configuration/component/event_sourcing/interval_snapshot_policy.rb +1 -1
  12. data/lib/synapse/configuration/component/event_sourcing/repository.rb +8 -0
  13. data/lib/synapse/configuration/component/process_manager/container_resource_injector.rb +22 -0
  14. data/lib/synapse/configuration/component/process_manager/generic_process_factory.rb +43 -0
  15. data/lib/synapse/configuration/component/process_manager/mapping_process_manager.rb +102 -0
  16. data/lib/synapse/configuration/component/process_manager.rb +18 -0
  17. data/lib/synapse/configuration/component/repository/locking_repository.rb +10 -1
  18. data/lib/synapse/configuration/component/repository/simple_repository.rb +1 -0
  19. data/lib/synapse/configuration/component/serialization/converter_factory.rb +2 -1
  20. data/lib/synapse/configuration/component/serialization/serializer.rb +10 -1
  21. data/lib/synapse/configuration/component/uow/unit_factory.rb +3 -1
  22. data/lib/synapse/configuration/component/upcasting/upcaster_chain.rb +3 -1
  23. data/lib/synapse/configuration/container.rb +17 -2
  24. data/lib/synapse/configuration/definition_builder.rb +14 -0
  25. data/lib/synapse/configuration.rb +1 -0
  26. data/lib/synapse/process_manager/process_manager.rb +9 -0
  27. data/lib/synapse/serialization/serializer/marshal.rb +4 -2
  28. data/lib/synapse/version.rb +1 -1
  29. data/lib/synapse.rb +1 -0
  30. data/test/auditing/data_provider_test.rb +1 -1
  31. data/test/auditing/unit_listener_test.rb +1 -1
  32. data/test/configuration/component/process_manager/container_resource_injector_test.rb +21 -0
  33. data/test/configuration/component/process_manager/mapping_process_manager_test.rb +37 -0
  34. data/test/configuration/container_test.rb +24 -0
  35. metadata +32 -9
  36. checksums.yaml +0 -7
@@ -0,0 +1,12 @@
1
+ module Synapse
2
+ module Auditing
3
+ # Implementation of an audit provider that simply audits a command's metadata
4
+ class CommandMetadataProvider < AuditDataProvider
5
+ # @param [CommandMessage] command
6
+ # @return [Hash]
7
+ def provide_data_for(command)
8
+ command.metadata
9
+ end
10
+ end # CommandMetadataProvider
11
+ end # Auditing
12
+ end
@@ -0,0 +1,19 @@
1
+ module Synapse
2
+ module Auditing
3
+ # Implementation of an audit provider that attaches a command's identifier to each event
4
+ # produced as a result of the execution of that command
5
+ class CorrelationDataProvider < AuditDataProvider
6
+ # @param [Symbol] correlation_key
7
+ # @return [undefined]
8
+ def initialize(correlation_key)
9
+ @correlation_key = correlation_key
10
+ end
11
+
12
+ # @param [CommandMessage] command
13
+ # @return [Hash]
14
+ def provide_data_for(command)
15
+ Hash[@correlation_key, command.id]
16
+ end
17
+ end # CorrelationDataProvider
18
+ end # Auditing
19
+ end
@@ -9,34 +9,6 @@ module Synapse
9
9
  # @param [CommandMessage] command
10
10
  # @return [Hash]
11
11
  def provide_data_for(command); end
12
- end
13
-
14
- # Implementation of an audit provider that simply audits a command's metadata
15
- class CommandMetadataProvider < AuditDataProvider
16
- # @param [CommandMessage] command
17
- # @return [Hash]
18
- def provide_data_for(command)
19
- command.metadata
20
- end
21
- end
22
-
23
- # Implementation of an audit provider that attaches a command's identifier to each event
24
- # produced as a result of the execution of that command
25
- class CorrelationDataProvider < AuditDataProvider
26
- # The default key to use when correlating events with commands
27
- DEFAULT_KEY = :command_id
28
-
29
- # @param [Symbol] correlation_key
30
- # @return [undefined]
31
- def initialize(correlation_key = DEFAULT_KEY)
32
- @correlation_key = correlation_key
33
- end
34
-
35
- # @param [CommandMessage] command
36
- # @return [Hash]
37
- def provide_data_for(command)
38
- Hash[@correlation_key, command.id]
39
- end
40
- end
41
- end
12
+ end # AuditDataProvider
13
+ end # Auditing
42
14
  end
@@ -20,10 +20,11 @@ module Synapse
20
20
  audit_listener = AuditingUnitOfWorkListener.new command, @data_providers, @loggers
21
21
  unit.register_listener audit_listener
22
22
 
23
- chain.proceed(command).tap do |result|
24
- audit_listener.return_value = result
25
- end
23
+ result = chain.proceed command
24
+ audit_listener.return_value = result
25
+
26
+ result
26
27
  end
27
- end
28
- end
28
+ end # AuditingDispatchInterceptor
29
+ end # Auditing
29
30
  end
@@ -27,9 +27,10 @@ module Synapse
27
27
  audit_data.merge! provider.provide_data_for @command
28
28
  end
29
29
 
30
- event.and_metadata(audit_data).tap do |e|
31
- @recorded_events.push e
32
- end
30
+ event = event.and_metadata audit_data
31
+ @recorded_events.push event
32
+
33
+ event
33
34
  end
34
35
 
35
36
  # @param [UnitOfWork] unit
@@ -45,9 +46,9 @@ module Synapse
45
46
  # @return [undefined]
46
47
  def on_rollback(unit, cause = nil)
47
48
  @loggers.each do |logger|
48
- logger.on_success @command, cause, @recorded_events
49
+ logger.on_failure @command, cause, @recorded_events
49
50
  end
50
51
  end
51
- end
52
- end
52
+ end # AuditingUnitOfWorkListener
53
+ end # Auditing
53
54
  end
@@ -1,4 +1,6 @@
1
1
  require 'synapse/auditing/audit_logger'
2
2
  require 'synapse/auditing/data_provider'
3
+ require 'synapse/auditing/command_metadata_provider'
4
+ require 'synapse/auditing/correlation_data_provider'
3
5
  require 'synapse/auditing/dispatch_interceptor'
4
6
  require 'synapse/auditing/unit_listener'
@@ -14,6 +14,7 @@ module Synapse
14
14
  class CommandGatewayDefinitionBuilder < DefinitionBuilder
15
15
  # Changes the command bus that commands are sent from the gateway
16
16
  #
17
+ # @see Command::CommandBus
17
18
  # @param [Symbol] command_bus
18
19
  # @return [undefined]
19
20
  def use_command_bus(command_bus)
@@ -17,6 +17,7 @@ module Synapse
17
17
  # Note that command handlers that are tagged must support self-subscription to the
18
18
  # command bus. An example of a handler capable of doing so is the wiring command handler.
19
19
  #
20
+ # @see Command::MappingCommandHandler
20
21
  # @param [Symbol] handler_tag
21
22
  # @return [undefined]
22
23
  def use_handler_tag(handler_tag)
@@ -25,6 +26,7 @@ module Synapse
25
26
 
26
27
  # Changes the tag to use to automatically register command filters
27
28
  #
29
+ # @see Command::CommandFilter
28
30
  # @param [Symbol] filter_tag
29
31
  # @return [undefined]
30
32
  def use_filter_tag(filter_tag)
@@ -33,6 +35,7 @@ module Synapse
33
35
 
34
36
  # Changes the tag to use to automatically register command filters
35
37
  #
38
+ # @see Command::DispatchInterceptor
36
39
  # @param [Symbol] interceptor_tag
37
40
  # @return [undefined]
38
41
  def use_interceptor_tag(interceptor_tag)
@@ -43,6 +46,7 @@ module Synapse
43
46
  #
44
47
  # By default, the command bus will always rollback on an exception
45
48
  #
49
+ # @see Command::RollbackPolicy
46
50
  # @param [Symbol] rollback_policy
47
51
  # @return [undefined]
48
52
  def use_rollback_policy(rollback_policy)
@@ -51,6 +55,7 @@ module Synapse
51
55
 
52
56
  # Changes the unit of work factory to use with this command bus
53
57
  #
58
+ # @see UnitOfWork::UnitOfWorkFactory
54
59
  # @param [Symbol] unit_factory
55
60
  # @return [undefined]
56
61
  def use_unit_factory(unit_factory)
@@ -73,7 +78,10 @@ module Synapse
73
78
  unit_factory = resolve @unit_factory
74
79
 
75
80
  command_bus = create_command_bus unit_factory
76
- command_bus.rollback_policy = resolve @rollback_policy, true
81
+
82
+ if @rollback_policy
83
+ command_bus.rollback_policy = resolve @rollback_policy
84
+ end
77
85
 
78
86
  with_tagged @handler_tag do |handler|
79
87
  handler.subscribe command_bus
@@ -12,6 +12,7 @@ module Synapse
12
12
  class SimpleEventBusDefinitionBuilder < DefinitionBuilder
13
13
  # Changes the tag to use to automatically subscribe event listeners
14
14
  #
15
+ # @see EventBus::EventListener
15
16
  # @param [Symbol] listener_tag
16
17
  # @return [undefined]
17
18
  def use_listener_tag(listener_tag)
@@ -11,12 +11,19 @@ module Synapse
11
11
  # use_event_store :alt_event_store
12
12
  # end
13
13
  class AggregateSnapshotTakerDefinitionBuilder < DefinitionBuilder
14
+ # Changes the tag used to find aggregate factories necessary for creating aggregates so that
15
+ # a snapshot can be taken of their current state
16
+ #
17
+ # @see EventSourcing::AggregateFactory
14
18
  # @param [Symbol] aggregate_factory_tag
15
19
  # @return [undefined]
16
20
  def use_aggregate_factory_tag(aggregate_factory_tag)
17
21
  @aggregate_factory_tag = aggregate_factory_tag
18
22
  end
19
23
 
24
+ # Changes the event store used to load and store aggregates
25
+ #
26
+ # @see EventStore::SnapshotEventStore
20
27
  # @param [Symbol] event_store
21
28
  # @return [undefined]
22
29
  def use_event_store(event_store)
@@ -25,7 +25,7 @@ module Synapse
25
25
  use_threshold 30
26
26
 
27
27
  use_factory do
28
- EventSourcing::AggregateSnapshotTaker.new @threshold
28
+ EventSourcing::IntervalSnapshotPolicy.new @threshold
29
29
  end
30
30
  end
31
31
  end # IntervalSnapshotPolicyDefinitionBuilder
@@ -36,30 +36,38 @@ module Synapse
36
36
  end
37
37
  end
38
38
 
39
+ # Changes the aggregate factory used to create aggregates that will have their state
40
+ # initialized from an event stream
41
+ #
42
+ # @see EventSourcing::AggregateFactory
39
43
  # @param [Symbol] aggregate_factory
40
44
  # @return [undefined]
41
45
  def use_aggregate_factory(aggregate_factory)
42
46
  @aggregate_factory = aggregate_factory
43
47
  end
44
48
 
49
+ # @see EventSourcing::ConflictResolver
45
50
  # @param [Symbol] conflict_resolver
46
51
  # @return [undefined]
47
52
  def use_conflict_resolver(conflict_resolver)
48
53
  @conflict_resolver = conflict_resolver
49
54
  end
50
55
 
56
+ # @see EventStore::EventStore
51
57
  # @param [Symbol] event_store
52
58
  # @return [undefined]
53
59
  def use_event_store(event_store)
54
60
  @event_store = event_store
55
61
  end
56
62
 
63
+ # @see EventSourcing::SnapshotPolicy
57
64
  # @param [Symbol] snapshot_policy
58
65
  # @return [undefined]
59
66
  def use_snapshot_policy(snapshot_policy)
60
67
  @snapshot_policy = snapshot_policy
61
68
  end
62
69
 
70
+ # @see EventSourcing::SnapshotTaker
63
71
  # @param [Symbol] snapshot_taker
64
72
  # @return [undefined]
65
73
  def use_snapshot_taker(snapshot_taker)
@@ -0,0 +1,22 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Definition builder used to create a resource injector that uses the service container
4
+ #
5
+ # @example The minimum possible effort to build a resource injector
6
+ # container_resource_injector
7
+ class ContainerResourceInjectorDefinitionBuilder < DefinitionBuilder
8
+ # No options available for this definition builder
9
+
10
+ protected
11
+
12
+ # @return [undefined]
13
+ def populate_defaults
14
+ identified_by :resource_injector
15
+
16
+ use_factory do
17
+ ProcessManager::ContainerResourceInjector.new @container
18
+ end
19
+ end
20
+ end # ContainerResourceInjectorDefinitionBuilder
21
+ end # Configuration
22
+ end
@@ -0,0 +1,43 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Definition builder used to create a generic process factory
4
+ #
5
+ # @example The minimum possible effort to build a process factory
6
+ # process_factory
7
+ #
8
+ # @example Use a custom resource injector
9
+ # process_factory :alt_process_factory do
10
+ # use_resource_injector :alt_resource_injector
11
+ # end
12
+ class GenericProcessFactoryDefinitionBuilder < DefinitionBuilder
13
+ # Changes the resource injector used by this process factory
14
+ #
15
+ # @see ProcessManager::ResourceInjector
16
+ # @param [Symbol] resource_injector
17
+ # @return [undefined]
18
+ def use_resource_injector(resource_injector)
19
+ @resource_injector = resource_injector
20
+ end
21
+
22
+ protected
23
+
24
+ # @return [undefined]
25
+ def populate_defaults
26
+ identified_by :process_factory
27
+
28
+ use_resource_injector :resource_injector
29
+
30
+ use_factory do
31
+ resource_injector = resolve @resource_injector, true
32
+
33
+ process_factory = ProcessManager::GenericProcessFactory.new
34
+ if resource_injector
35
+ process_factory.resource_injector = resource_injector
36
+ end
37
+
38
+ process_factory
39
+ end
40
+ end
41
+ end # GenericProcessFactoryDefinitionBuilder
42
+ end # Configuration
43
+ end
@@ -0,0 +1,102 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Definition builder used to create a mapping process manager
4
+ #
5
+ # Since process managers are effectively listeners on the event bus, definitions created by
6
+ # this builder will be tagged with `:event_listener`
7
+ #
8
+ # @example The minimum possible effort to build a process manager
9
+ # process_manager do
10
+ # use_process_types MoneyTransferProcess
11
+ # end
12
+ #
13
+ # @example Build a process manager with alternate components
14
+ # process_manager :alt_process_manager do
15
+ # use_process_types MoneyTransferProcess
16
+ #
17
+ # use_process_repository :alt_process_repository
18
+ # use_process_factory :alt_process_factory
19
+ #
20
+ # # Use a different tag for subscribing to an event bus
21
+ # replace_tags :alt_event_listener
22
+ # end
23
+ class MappingProcessManagerDefinitionBuilder < DefinitionBuilder
24
+ # Changes the lock manager to use with this process manager
25
+ #
26
+ # @see ProcessManager::LockManager
27
+ # @param [Symbol] lock_manager
28
+ # @return [undefined]
29
+ def use_lock_manager(lock_manager)
30
+ @lock_manager = lock_manager
31
+ end
32
+
33
+ # Changes the lock manager to a pessimistic lock manager
34
+ #
35
+ # @see ProcessManager::PessimisticLockManager
36
+ # @return [undefined]
37
+ def use_pessimistic_locking
38
+ @lock_manager_type = ProcessManager::PessimisticLockManager
39
+ end
40
+
41
+ # Changes the process factory to use with this process manager
42
+ #
43
+ # @see ProcessManager::ProcessFactory
44
+ # @param [Symbol] process_factory
45
+ # @return [undefined]
46
+ def use_process_factory(process_factory)
47
+ @process_factory = process_factory
48
+ end
49
+
50
+ # Changes the process repository to use with this process manager
51
+ #
52
+ # @see ProcessManager::ProcessRepository
53
+ # @param [Symbol] process_repository
54
+ # @return [undefined]
55
+ def use_process_repository(process_repository)
56
+ @process_repository = process_repository
57
+ end
58
+
59
+ # Changes the process types that are hosted by this process manager
60
+ #
61
+ # @see ProcessManager::Process
62
+ # @param [Class...] process_types
63
+ # @return [undefined]
64
+ def use_process_types(*process_types)
65
+ @process_types = process_types.flatten
66
+ end
67
+
68
+ protected
69
+
70
+ # @return [undefined]
71
+ def populate_defaults
72
+ identified_by :process_manager
73
+
74
+ tag :event_listener
75
+
76
+ use_pessimistic_locking
77
+ use_process_factory :process_factory
78
+ use_process_repository :process_repository
79
+
80
+ use_factory do
81
+ lock_manager = build_lock_manager
82
+ factory = resolve @process_factory
83
+ repository = resolve @process_repository
84
+
85
+ ProcessManager::MappingProcessManager.new repository, factory, lock_manager, @process_types
86
+ end
87
+ end
88
+
89
+ # @raise [RuntimeError] If no lock manager was configured
90
+ # @return [LockManager]
91
+ def build_lock_manager
92
+ if @lock_manager
93
+ resolve @lock_manager
94
+ elsif @lock_manager_type
95
+ @lock_manager_type.new
96
+ else
97
+ raise 'No lock manager was configured for this process manager'
98
+ end
99
+ end
100
+ end # MappingProcessManagerDefinitionBuilder
101
+ end # Configuration
102
+ end
@@ -0,0 +1,18 @@
1
+ require 'synapse/configuration/component/process_manager/container_resource_injector'
2
+ require 'synapse/configuration/component/process_manager/generic_process_factory'
3
+ require 'synapse/configuration/component/process_manager/mapping_process_manager'
4
+
5
+ module Synapse
6
+ module Configuration
7
+ class ContainerBuilder
8
+ # Creates and configures a resource injector that uses the service container
9
+ builder :container_resource_injector, ContainerResourceInjectorDefinitionBuilder
10
+
11
+ # Creates and configures a generic process factory
12
+ builder :process_factory, GenericProcessFactoryDefinitionBuilder
13
+
14
+ # Creates and configures a mapping process manager
15
+ builder :process_manager, MappingProcessManagerDefinitionBuilder
16
+ end # ContainerBuilder
17
+ end # Configuration
18
+ end
@@ -9,6 +9,7 @@ module Synapse
9
9
  class LockingRepositoryDefinitionBuilder < DefinitionBuilder
10
10
  # Changes the event bus used to publish aggregate events to
11
11
  #
12
+ # @see EventBus::EventBus
12
13
  # @param [Symbol] event_bus
13
14
  # @return [undefined]
14
15
  def use_event_bus(event_bus)
@@ -16,18 +17,24 @@ module Synapse
16
17
  end
17
18
 
18
19
  # Uses the lock manager with no locking
20
+ #
21
+ # @see Repository::NullLockManager
19
22
  # @return [undefined]
20
23
  def use_no_locking
21
24
  @lock_manager_type = Repository::NullLockManager
22
25
  end
23
26
 
24
27
  # Uses the lock manager with pessimistic locking
28
+ #
29
+ # @see Repository::PessimisticLockManager
25
30
  # @return [undefined]
26
31
  def use_pessimistic_locking
27
32
  @lock_manager_type = Repository::PessimisticLockManager
28
33
  end
29
34
 
30
35
  # Uses the lock manager with optimistic locking
36
+ #
37
+ # @see Repository::OptimisticLockManager
31
38
  # @return [undefined]
32
39
  def use_optimistic_locking
33
40
  @lock_manager_type = Repository::OptimisticLockManager
@@ -35,6 +42,7 @@ module Synapse
35
42
 
36
43
  # Changes the lock manager used to prevent concurrent aggregate modification
37
44
  #
45
+ # @see Repository::LockManager
38
46
  # @param [Symbol] lock_manager
39
47
  # @return [undefined]
40
48
  def use_lock_manager(lock_manager)
@@ -43,6 +51,7 @@ module Synapse
43
51
 
44
52
  # Changes the provider used to get the current unit of work
45
53
  #
54
+ # @see UnitOfWork::UnitOfWorkProvider
46
55
  # @param [Symbol] unit_provider
47
56
  # @return [undefined]
48
57
  def use_unit_provider(unit_provider)
@@ -58,7 +67,7 @@ module Synapse
58
67
  use_unit_provider :unit_provider
59
68
  end
60
69
 
61
- # @raise [RuntimeError] If no locking manager was configured
70
+ # @raise [RuntimeError] If no lock manager was configured
62
71
  # @return [LockManager]
63
72
  def build_lock_manager
64
73
  if @lock_manager
@@ -7,6 +7,7 @@ module Synapse
7
7
  # use_aggregate_type User
8
8
  # end
9
9
  class SimpleRepositoryDefinitionBuilder < LockingRepositoryDefinitionBuilder
10
+ # @see Domain::AggregateRoot
10
11
  # @param [Class] aggregate_type
11
12
  # @return [undefined]
12
13
  def use_aggregate_type(aggregate_type)
@@ -21,6 +21,7 @@ module Synapse
21
21
  class ConverterFactoryDefinitionBuilder < DefinitionBuilder
22
22
  # Changes the tag to use to automatically register converters
23
23
  #
24
+ # @see Serialization::Converter
24
25
  # @param [Symbol] converter_tag
25
26
  # @return [undefined]
26
27
  def use_converter_tag(converter_tag)
@@ -37,7 +38,7 @@ module Synapse
37
38
 
38
39
  use_factory do
39
40
  converter_factory = Serialization::ConverterFactory.new
40
-
41
+
41
42
  with_tagged @converter_tag do |converter|
42
43
  converter_factory.register converter
43
44
  end
@@ -12,24 +12,32 @@ module Synapse
12
12
  # end
13
13
  class SerializerDefinitionBuilder < DefinitionBuilder
14
14
  # Selects a serializer that uses attributes (ActiveModel, Virtus, etc.)
15
+ #
16
+ # @see Serialization::AttributeSerializer
15
17
  # @return [undefined]
16
18
  def use_attribute
17
19
  @serializer_type = Serialization::AttributeSerializer
18
20
  end
19
21
 
20
22
  # Selects a serializer that uses the Ruby marshaling library
23
+ #
24
+ # @see Serialization::MarshalSerializer
21
25
  # @return [undefined]
22
26
  def use_marshal
23
27
  @serializer_type = Serialization::MarshalSerializer
24
28
  end
25
29
 
26
30
  # Selects a serializer that uses the Optimized JSON (Oj) serialization library
31
+ #
32
+ # @see Serialization::OjSerializer
27
33
  # @return [undefined]
28
34
  def use_oj
29
35
  @serializer_type = Serialization::OjSerializer
30
36
  end
31
37
 
32
38
  # Selects a serializer that uses the Optimized XML (Ox) serialization library
39
+ #
40
+ # @see Serialization::OxSerializer
33
41
  # @return [undefined]
34
42
  def use_ox
35
43
  @serializer_type = Serialization::OxSerializer
@@ -37,6 +45,7 @@ module Synapse
37
45
 
38
46
  # Changes the converter factory
39
47
  #
48
+ # @see Serialization::ConverterFactory
40
49
  # @param [Symbol] converter_factory
41
50
  # @return [undefined]
42
51
  def use_converter_factory(converter_factory)
@@ -87,4 +96,4 @@ module Synapse
87
96
  end
88
97
  end # SerializerDefinitionBuilder
89
98
  end # Configuration
90
- end
99
+ end
@@ -13,6 +13,7 @@ module Synapse
13
13
  class UnitOfWorkFactoryDefinitionBuilder < DefinitionBuilder
14
14
  # Changes the transaction manager to use when creating units of work
15
15
  #
16
+ # @see UnitOfWork::TransactionManager
16
17
  # @param [Symbol] tx_manager
17
18
  # @return [undefined]
18
19
  def use_transaction_manager(tx_manager)
@@ -21,6 +22,7 @@ module Synapse
21
22
 
22
23
  # Changes the unit of work provider to use when creating units of work
23
24
  #
25
+ # @see UnitOfWork::UnitOfWorkProvider
24
26
  # @param [Symbol] unit_provider
25
27
  # @return [undefined]
26
28
  def use_unit_provider(unit_provider)
@@ -42,7 +44,7 @@ module Synapse
42
44
 
43
45
  unit_factory = UnitOfWork::UnitOfWorkFactory.new unit_provider
44
46
  unit_factory.transaction_manager = tx_manager
45
-
47
+
46
48
  unit_factory
47
49
  end
48
50
  end
@@ -21,6 +21,7 @@ module Synapse
21
21
  class UpcasterChainDefinitionBuilder < DefinitionBuilder
22
22
  # Changes the converter factory
23
23
  #
24
+ # @see Serialization::ConverterFactory
24
25
  # @param [Symbol] converter_factory
25
26
  # @return [undefined]
26
27
  def use_converter_factory(converter_factory)
@@ -29,6 +30,7 @@ module Synapse
29
30
 
30
31
  # Changes the tag to use to automatically register upcasters
31
32
  #
33
+ # @see Upcasting::Upcaster
32
34
  # @param [Symbol] upcaster_tag
33
35
  # @return [undefined]
34
36
  def use_upcaster_tag(upcaster_tag)
@@ -48,7 +50,7 @@ module Synapse
48
50
  converter_factory = resolve @converter_factory
49
51
 
50
52
  upcaster_chain = Upcasting::UpcasterChain.new converter_factory
51
-
53
+
52
54
  with_tagged @upcaster_tag do |upcaster|
53
55
  upcaster_chain.push upcaster
54
56
  end
@@ -17,6 +17,9 @@ module Synapse
17
17
 
18
18
  dependencies = object.class.dependencies
19
19
  dependencies.each_pair do |id, attribute|
20
+ # Don't replace existing attributes
21
+ next if object.public_send attribute
22
+
20
23
  resolved = resolve id
21
24
  object.public_send "#{attribute}=", resolved
22
25
  end
@@ -75,6 +78,18 @@ module Synapse
75
78
  def registered?(id)
76
79
  @definitions.has_key? id
77
80
  end
78
- end
79
- end
81
+
82
+ # @return [String]
83
+ def inspect
84
+ result = "#<#{self.class}\n"
85
+ @definitions.keys.sort.each do |key|
86
+ definition = @definitions[key]
87
+ result << "\t#{key} => #{definition.tags.inspect}\n"
88
+ end
89
+ result << ">"
90
+
91
+ result
92
+ end
93
+ end # Container
94
+ end # Configuration
80
95
  end
@@ -44,6 +44,20 @@ module Synapse
44
44
  identified_by SecureRandom.hex 8
45
45
  end
46
46
 
47
+ # @api public
48
+ # @return [undefined]
49
+ def clear_tags
50
+ @tags = Set.new
51
+ end
52
+
53
+ # @api public
54
+ # @param [Symbol...] tags
55
+ # @return [undefined]
56
+ def replace_tags(*tags)
57
+ clear_tags
58
+ tag *tags
59
+ end
60
+
47
61
  # @api public
48
62
  # @param [Symbol...] tags
49
63
  # @return [undefined]
@@ -10,6 +10,7 @@ require 'synapse/configuration/component/event_bus'
10
10
  # Has to be loaded before event sourcing
11
11
  require 'synapse/configuration/component/repository'
12
12
  require 'synapse/configuration/component/event_sourcing'
13
+ require 'synapse/configuration/component/process_manager'
13
14
  require 'synapse/configuration/component/serialization'
14
15
  require 'synapse/configuration/component/uow'
15
16
  require 'synapse/configuration/component/upcasting'
@@ -5,6 +5,15 @@ module Synapse
5
5
  class ProcessManager
6
6
  include EventBus::EventListener
7
7
 
8
+ # @return [LockManager]
9
+ attr_reader :lock_manager
10
+
11
+ # @return [ProcessFactory]
12
+ attr_reader :factory
13
+
14
+ # @return [ProcessRepository]
15
+ attr_reader :repository
16
+
8
17
  # @return [Boolean] Returns true if exceptions will be logged silently
9
18
  attr_accessor :suppress_exceptions
10
19
 
@@ -5,6 +5,8 @@ module Synapse
5
5
  # Note that this serializer is not necessarily the fastest serializer available, nor is it
6
6
  # flexible. Output is binary and difficult to modify, which means upcasting is not possible
7
7
  # when using this serializer.
8
+ #
9
+ # This serializer wraps the binary output of Marshal in Base64 encoding.
8
10
  class MarshalSerializer < Serializer
9
11
  # This serializer doesn't provide any configuration options
10
12
 
@@ -13,14 +15,14 @@ module Synapse
13
15
  # @param [Object] content
14
16
  # @return [Object]
15
17
  def perform_serialize(content)
16
- Marshal.dump content
18
+ Base64.encode64(Marshal.dump(content))
17
19
  end
18
20
 
19
21
  # @param [Object] content
20
22
  # @param [Class] type
21
23
  # @return [Object]
22
24
  def perform_deserialize(content, type)
23
- Marshal.load content
25
+ Marshal.load(Base64.decode64(content))
24
26
  end
25
27
 
26
28
  # @return [Class]
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = '0.5.2'
2
+ VERSION = '0.5.3'
3
3
  end
data/lib/synapse.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'active_support'
2
2
  require 'active_support/core_ext'
3
+ require 'forwardable'
3
4
  require 'logging'
4
5
  require 'set'
5
6
 
@@ -18,7 +18,7 @@ module Synapse
18
18
 
19
19
  class CorrelationDataProviderTest < Test::Unit::TestCase
20
20
  should 'provide the identifier of a command for auditing' do
21
- provider = CorrelationDataProvider.new
21
+ provider = CorrelationDataProvider.new :command_id
22
22
  command = Command::CommandMessage.build
23
23
 
24
24
  expected = { :command_id => command.id }
@@ -57,7 +57,7 @@ module Synapse
57
57
  loggers = [logger]
58
58
  event = Object.new
59
59
 
60
- mock(logger).on_success(command, exception, [event])
60
+ mock(logger).on_failure(command, exception, [event])
61
61
 
62
62
  listener = AuditingUnitOfWorkListener.new command, data_providers, loggers
63
63
  listener.recorded_events.push event
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Configuration
5
+ class ContainerResourceInjectorDefinitionBuilderTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @container = Container.new
9
+ @builder = ContainerBuilder.new @container
10
+ end
11
+
12
+ should 'build a resource injector' do
13
+ @builder.container_resource_injector
14
+
15
+ resource_injector = @container.resolve :resource_injector
16
+ assert_instance_of ProcessManager::ContainerResourceInjector, resource_injector
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+ require 'process_manager/mapping/fixtures'
3
+
4
+ module Synapse
5
+ module Configuration
6
+ class MappingProcessManagerDefinitionBuilderTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @container = Container.new
10
+ @builder = ContainerBuilder.new @container
11
+ end
12
+
13
+ should 'build with sensible defaults' do
14
+ @builder.factory :process_repository do
15
+ ProcessManager::InMemoryProcessRepository.new
16
+ end
17
+
18
+ @builder.process_factory
19
+ @builder.process_manager do
20
+ use_process_types ProcessManager::OrderProcess
21
+ end
22
+
23
+ process_manager = @container.resolve :process_manager
24
+
25
+ assert_equal [process_manager], @container.resolve_tagged(:event_listener)
26
+
27
+ factory = @container.resolve :process_factory
28
+ repository = @container.resolve :process_repository
29
+
30
+ assert_same factory, process_manager.factory
31
+ assert_same repository, process_manager.repository
32
+ assert_instance_of ProcessManager::PessimisticLockManager, process_manager.lock_manager
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -33,6 +33,30 @@ module Synapse
33
33
  container.inject_into object
34
34
  end
35
35
 
36
+ should 'not overwrite existing attributes when injecting into a Dependent object' do
37
+ container = Container.new
38
+
39
+ service_a = Object.new
40
+ service_b = Object.new
41
+
42
+ DefinitionBuilder.build container, :service_a do
43
+ use_instance service_a
44
+ end
45
+
46
+ DefinitionBuilder.build container, :service_b do
47
+ use_instance service_b
48
+ end
49
+
50
+ other_service_a = Object.new
51
+
52
+ dependent = ExampleDependent.new
53
+ dependent.service_a = other_service_a
54
+ container.inject_into dependent
55
+
56
+ assert_same other_service_a, dependent.service_a
57
+ assert_same service_b, dependent.some_service
58
+ end
59
+
36
60
  should 'resolve a service from a definition by its identifier' do
37
61
  reference = Object.new
38
62
  container = Container.new
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synapse-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Ian Unruh
@@ -13,6 +14,7 @@ dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ~>
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
@@ -27,6 +30,7 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: atomic
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ~>
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ~>
39
44
  - !ruby/object:Gem::Version
@@ -41,6 +46,7 @@ dependencies:
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: logging
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
51
  - - ~>
46
52
  - !ruby/object:Gem::Version
@@ -48,6 +54,7 @@ dependencies:
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
59
  - - ~>
53
60
  - !ruby/object:Gem::Version
@@ -55,15 +62,17 @@ dependencies:
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: thread
57
64
  requirement: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
- - - '>='
67
+ - - ! '>='
60
68
  - !ruby/object:Gem::Version
61
69
  version: '0'
62
70
  type: :runtime
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
- - - '>='
75
+ - - ! '>='
67
76
  - !ruby/object:Gem::Version
68
77
  version: '0'
69
78
  description: A versatile CQRS and event sourcing framework
@@ -143,6 +152,10 @@ files:
143
152
  - lib/synapse/configuration/component/event_sourcing/repository.rb
144
153
  - lib/synapse/configuration/component/event_sourcing/interval_snapshot_policy.rb
145
154
  - lib/synapse/configuration/component/upcasting/upcaster_chain.rb
155
+ - lib/synapse/configuration/component/process_manager.rb
156
+ - lib/synapse/configuration/component/process_manager/mapping_process_manager.rb
157
+ - lib/synapse/configuration/component/process_manager/generic_process_factory.rb
158
+ - lib/synapse/configuration/component/process_manager/container_resource_injector.rb
146
159
  - lib/synapse/configuration/component/upcasting.rb
147
160
  - lib/synapse/configuration/component/serialization.rb
148
161
  - lib/synapse/configuration/component/uow.rb
@@ -178,7 +191,9 @@ files:
178
191
  - lib/synapse/event_store/errors.rb
179
192
  - lib/synapse/event_store/in_memory.rb
180
193
  - lib/synapse/configuration.rb
194
+ - lib/synapse/auditing/correlation_data_provider.rb
181
195
  - lib/synapse/auditing/audit_logger.rb
196
+ - lib/synapse/auditing/command_metadata_provider.rb
182
197
  - lib/synapse/auditing/data_provider.rb
183
198
  - lib/synapse/auditing/dispatch_interceptor.rb
184
199
  - lib/synapse/auditing/unit_listener.rb
@@ -275,6 +290,8 @@ files:
275
290
  - test/configuration/component/repository/simple_repository_test.rb
276
291
  - test/configuration/component/event_sourcing/repository_test.rb
277
292
  - test/configuration/component/upcasting/upcaster_chain_test.rb
293
+ - test/configuration/component/process_manager/container_resource_injector_test.rb
294
+ - test/configuration/component/process_manager/mapping_process_manager_test.rb
278
295
  - test/configuration/component/event_bus/simple_event_bus_test.rb
279
296
  - test/configuration/component/serialization/serializer_test.rb
280
297
  - test/configuration/component/serialization/converter_factory_test.rb
@@ -324,26 +341,32 @@ files:
324
341
  homepage: https://github.com/ianunruh/synapse
325
342
  licenses:
326
343
  - Apache 2.0
327
- metadata: {}
328
344
  post_install_message:
329
345
  rdoc_options: []
330
346
  require_paths:
331
347
  - lib
332
348
  required_ruby_version: !ruby/object:Gem::Requirement
349
+ none: false
333
350
  requirements:
334
- - - '>='
351
+ - - ! '>='
335
352
  - !ruby/object:Gem::Version
336
353
  version: '0'
354
+ segments:
355
+ - 0
356
+ hash: -4187832660438552395
337
357
  required_rubygems_version: !ruby/object:Gem::Requirement
358
+ none: false
338
359
  requirements:
339
- - - '>='
360
+ - - ! '>='
340
361
  - !ruby/object:Gem::Version
341
362
  version: '0'
363
+ segments:
364
+ - 0
365
+ hash: -4187832660438552395
342
366
  requirements: []
343
367
  rubyforge_project:
344
- rubygems_version: 2.0.3
368
+ rubygems_version: 1.8.25
345
369
  signing_key:
346
- specification_version: 4
370
+ specification_version: 3
347
371
  summary: A versatile CQRS and event sourcing framework
348
372
  test_files: []
349
- has_rdoc:
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: baa532559d58992e62cae2cc5b843a9485bd10af
4
- data.tar.gz: 5d63dd14c2598d92034db8fb45d7e37958a45f98
5
- SHA512:
6
- metadata.gz: 5264e9b6b99b0da204d4c0dc9d28f4b1624c1ac28e6ae9e47b5f89d441a4b2a41fe2a4fcde4e25801d7f2aa676b615728881fb4656132f7ed2d5e9f42edcc7e7
7
- data.tar.gz: fe5bc48121cacff34fb1ef50a43159902de2d5bf93b34ee5504e440e5a0dd76ea5caa66b5a441d55f154259a271feea30cbe523d8d180f67f7983d1889cdff18