synapse-core 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. data/lib/synapse/command/async_command_bus.rb +41 -0
  2. data/lib/synapse/command/command_callback.rb +49 -2
  3. data/lib/synapse/command/command_handler.rb +2 -0
  4. data/lib/synapse/command/filters/validation.rb +2 -2
  5. data/lib/synapse/command/gateway/interval_retry_scheduler.rb +75 -0
  6. data/lib/synapse/command/gateway/retry_scheduler.rb +26 -0
  7. data/lib/synapse/command/gateway/retrying_callback.rb +46 -0
  8. data/lib/synapse/command/gateway.rb +56 -11
  9. data/lib/synapse/command/interceptor_chain.rb +2 -2
  10. data/lib/synapse/command/interceptors/serialization.rb +2 -2
  11. data/lib/synapse/command/message.rb +16 -0
  12. data/lib/synapse/command/simple_command_bus.rb +6 -2
  13. data/lib/synapse/command/wiring.rb +3 -3
  14. data/lib/synapse/command.rb +7 -1
  15. data/lib/synapse/common/concurrency/identifier_lock.rb +2 -17
  16. data/lib/synapse/common/concurrency/public_lock.rb +8 -9
  17. data/lib/synapse/common/errors.rb +1 -1
  18. data/lib/synapse/common/message.rb +2 -6
  19. data/lib/synapse/common.rb +9 -0
  20. data/lib/synapse/configuration/component/command_bus/async_command_bus.rb +41 -0
  21. data/lib/synapse/configuration/component/command_bus/gateway.rb +38 -0
  22. data/lib/synapse/configuration/component/command_bus/simple_command_bus.rb +81 -0
  23. data/lib/synapse/configuration/component/command_bus.rb +35 -0
  24. data/lib/synapse/configuration/component/event_bus/simple_event_bus.rb +41 -0
  25. data/lib/synapse/configuration/component/event_bus.rb +15 -0
  26. data/lib/synapse/configuration/component/event_sourcing/repository.rb +62 -0
  27. data/lib/synapse/configuration/component/event_sourcing.rb +15 -0
  28. data/lib/synapse/configuration/component/repository/locking_repository.rb +85 -0
  29. data/lib/synapse/configuration/component/repository/simple_repository.rb +31 -0
  30. data/lib/synapse/configuration/component/repository.rb +15 -0
  31. data/lib/synapse/configuration/component/serialization/converter_factory.rb +50 -0
  32. data/lib/synapse/configuration/component/serialization/serializer.rb +90 -0
  33. data/lib/synapse/configuration/component/serialization.rb +25 -0
  34. data/lib/synapse/configuration/component/uow/unit_factory.rb +51 -0
  35. data/lib/synapse/configuration/component/uow.rb +22 -0
  36. data/lib/synapse/configuration/component/upcasting/upcaster_chain.rb +61 -0
  37. data/lib/synapse/configuration/component/upcasting.rb +15 -0
  38. data/lib/synapse/configuration/container.rb +80 -0
  39. data/lib/synapse/configuration/container_builder.rb +108 -0
  40. data/lib/synapse/configuration/definition.rb +31 -0
  41. data/lib/synapse/configuration/definition_builder.rb +138 -0
  42. data/lib/synapse/configuration/dependent.rb +31 -0
  43. data/lib/synapse/configuration/ext.rb +35 -0
  44. data/lib/synapse/configuration.rb +32 -0
  45. data/lib/synapse/domain/aggregate_root.rb +25 -26
  46. data/lib/synapse/domain/event_container.rb +5 -5
  47. data/lib/synapse/domain/message.rb +16 -0
  48. data/lib/synapse/event_bus/event_listener.rb +2 -0
  49. data/lib/synapse/event_bus/event_publisher.rb +19 -0
  50. data/lib/synapse/event_bus/simple_event_bus.rb +21 -30
  51. data/lib/synapse/event_bus/wiring.rb +5 -4
  52. data/lib/synapse/event_bus.rb +1 -1
  53. data/lib/synapse/event_sourcing/aggregate_root.rb +6 -4
  54. data/lib/synapse/process_manager/container_resource_injector.rb +18 -0
  55. data/lib/synapse/process_manager/pessimistic_lock_manager.rb +1 -1
  56. data/lib/synapse/process_manager/process.rb +4 -0
  57. data/lib/synapse/process_manager/process_factory.rb +3 -3
  58. data/lib/synapse/process_manager/repository/in_memory.rb +1 -1
  59. data/lib/synapse/process_manager/wiring/process.rb +6 -6
  60. data/lib/synapse/process_manager/wiring/process_manager.rb +8 -8
  61. data/lib/synapse/process_manager.rb +2 -0
  62. data/lib/synapse/repository/locking.rb +5 -3
  63. data/lib/synapse/repository/optimistic_lock_manager.rb +2 -7
  64. data/lib/synapse/repository/pessimistic_lock_manager.rb +3 -3
  65. data/lib/synapse/repository/repository.rb +2 -2
  66. data/lib/synapse/repository/simple_repository.rb +69 -0
  67. data/lib/synapse/repository.rb +1 -0
  68. data/lib/synapse/serialization/converter/chain.rb +2 -2
  69. data/lib/synapse/serialization/converter_factory.rb +2 -2
  70. data/lib/synapse/serialization/lazy_object.rb +2 -2
  71. data/lib/synapse/serialization/message/serialization_aware_message.rb +3 -3
  72. data/lib/synapse/serialization/message/serialized_message.rb +6 -10
  73. data/lib/synapse/serialization/message/serialized_message_builder.rb +4 -4
  74. data/lib/synapse/serialization/message/serialized_object_cache.rb +2 -2
  75. data/lib/synapse/serialization/message/serializer.rb +2 -2
  76. data/lib/synapse/serialization/revision_resolver.rb +3 -3
  77. data/lib/synapse/serialization/serialized_object.rb +2 -2
  78. data/lib/synapse/serialization/serialized_type.rb +2 -2
  79. data/lib/synapse/serialization/serializer/attribute.rb +2 -2
  80. data/lib/synapse/serialization/serializer/marshal.rb +2 -2
  81. data/lib/synapse/serialization/serializer/oj.rb +2 -2
  82. data/lib/synapse/serialization/serializer/ox.rb +2 -2
  83. data/lib/synapse/serialization/serializer.rb +2 -2
  84. data/lib/synapse/uow/factory.rb +2 -2
  85. data/lib/synapse/uow/listener_collection.rb +2 -2
  86. data/lib/synapse/uow/nesting.rb +9 -2
  87. data/lib/synapse/uow/provider.rb +2 -2
  88. data/lib/synapse/uow/uow.rb +8 -2
  89. data/lib/synapse/upcasting/{chain.rb → upcaster_chain.rb} +0 -0
  90. data/lib/synapse/upcasting.rb +1 -1
  91. data/lib/synapse/version.rb +1 -1
  92. data/lib/synapse/wiring/message_wiring.rb +31 -0
  93. data/lib/synapse.rb +2 -14
  94. data/test/auditing/data_provider_test.rb +2 -2
  95. data/test/auditing/dispatch_interceptor_test.rb +1 -1
  96. data/test/auditing/unit_listener_test.rb +3 -3
  97. data/test/command/async_command_bus_test.rb +49 -0
  98. data/test/command/duplication_test.rb +2 -2
  99. data/test/command/gateway/interval_retry_scheduler_test.rb +42 -0
  100. data/test/command/gateway/retrying_callback_test.rb +57 -0
  101. data/test/command/gateway_test.rb +41 -7
  102. data/test/command/interceptor_chain_test.rb +1 -1
  103. data/test/command/message_test.rb +17 -0
  104. data/test/command/serialization_test.rb +2 -2
  105. data/test/command/simple_command_bus_test.rb +7 -7
  106. data/test/command/validation_test.rb +3 -3
  107. data/test/command/wiring_test.rb +3 -3
  108. data/test/common/concurrency/identifier_lock_test.rb +2 -13
  109. data/test/common/concurrency/public_lock_test.rb +6 -6
  110. data/test/{duplication_test.rb → common/duplication_test.rb} +3 -3
  111. data/test/configuration/component/command_bus/async_command_bus_test.rb +36 -0
  112. data/test/configuration/component/command_bus/simple_command_bus_test.rb +57 -0
  113. data/test/configuration/component/event_bus/simple_event_bus_test.rb +58 -0
  114. data/test/configuration/component/serialization/converter_factory_test.rb +48 -0
  115. data/test/configuration/component/serialization/serializer_test.rb +78 -0
  116. data/test/configuration/component/uow/unit_factory_test.rb +46 -0
  117. data/test/configuration/container_builder_test.rb +47 -0
  118. data/test/configuration/container_test.rb +88 -0
  119. data/test/configuration/definition_builder_test.rb +126 -0
  120. data/test/configuration/definition_test.rb +41 -0
  121. data/test/configuration/dependent_test.rb +30 -0
  122. data/test/configuration/ext_test.rb +19 -0
  123. data/test/configuration/fixtures/dependent.rb +10 -0
  124. data/test/domain/aggregate_root_test.rb +5 -5
  125. data/test/domain/message_test.rb +15 -3
  126. data/test/domain/stream_test.rb +2 -2
  127. data/test/event_bus/publisher_test.rb +29 -0
  128. data/test/event_bus/wiring_test.rb +1 -1
  129. data/test/event_sourcing/aggregate_factory_test.rb +12 -6
  130. data/test/event_sourcing/aggregate_root_test.rb +4 -4
  131. data/test/event_sourcing/entity_test.rb +10 -9
  132. data/test/event_sourcing/repository_test.rb +6 -6
  133. data/test/event_sourcing/storage_listener_test.rb +8 -4
  134. data/test/event_store/in_memory_test.rb +3 -3
  135. data/test/process_manager/container_resource_injector_test.rb +19 -0
  136. data/test/process_manager/correlation_set_test.rb +2 -2
  137. data/test/process_manager/correlation_test.rb +2 -2
  138. data/test/process_manager/in_memory_test.rb +3 -3
  139. data/test/process_manager/process_factory_test.rb +2 -2
  140. data/test/process_manager/process_test.rb +3 -3
  141. data/test/process_manager/simple_process_manager_test.rb +5 -5
  142. data/test/process_manager/wiring/process_manager_test.rb +4 -4
  143. data/test/process_manager/wiring/process_test.rb +2 -2
  144. data/test/repository/locking_test.rb +4 -4
  145. data/test/repository/optimistic_test.rb +2 -2
  146. data/test/repository/pessimistic_test.rb +1 -1
  147. data/test/repository/simple_repository_test.rb +79 -0
  148. data/test/support/countdown_latch.rb +18 -0
  149. data/test/test_helper.rb +6 -3
  150. data/test/upcasting/data_test.rb +31 -0
  151. metadata +84 -25
  152. data/lib/synapse/event_bus/event_listener_proxy.rb +0 -12
  153. data/lib/synapse/partitioning/memory_queue_reader.rb +0 -31
  154. data/lib/synapse/partitioning/memory_queue_writer.rb +0 -19
  155. data/lib/synapse/partitioning/message_receipt.rb +0 -25
  156. data/lib/synapse/partitioning/packing/json_packer.rb +0 -93
  157. data/lib/synapse/partitioning/packing/json_unpacker.rb +0 -83
  158. data/lib/synapse/partitioning/packing.rb +0 -27
  159. data/lib/synapse/partitioning/queue_reader.rb +0 -32
  160. data/lib/synapse/partitioning/queue_writer.rb +0 -17
  161. data/lib/synapse/partitioning.rb +0 -18
  162. data/test/partitioning/memory_test.rb +0 -34
  163. data/test/partitioning/packing/json_test.rb +0 -62
@@ -0,0 +1,61 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Definition builder used to create an upcaster chain
4
+ #
5
+ # Note that order is very important when building an upcaster chain; the container maintains
6
+ # order when upcasters are registered as service definitions.
7
+ #
8
+ # @example The minimum possible effort to build an upcaster chain
9
+ # upcaster_chain
10
+ #
11
+ # @example Create an upcaster chain using a different identifier and properties
12
+ # upcaster_chain :alt_upcaster_chain do
13
+ # use_converter_factory :alt_converter_factory
14
+ # use_upcaster_tag :alt_upcaster
15
+ # end
16
+ #
17
+ # @example Register an upcaster that will be picked up by an upcaster chain
18
+ # factory :administrative_details_upcaster, :tag => :upcaster do
19
+ # AdministrativeDetailsUpcaster.new
20
+ # end
21
+ class UpcasterChainDefinitionBuilder < DefinitionBuilder
22
+ # Changes the converter factory
23
+ #
24
+ # @param [Symbol] converter_factory
25
+ # @return [undefined]
26
+ def use_converter_factory(converter_factory)
27
+ @converter_factory = converter_factory
28
+ end
29
+
30
+ # Changes the tag to use to automatically register upcasters
31
+ #
32
+ # @param [Symbol] upcaster_tag
33
+ # @return [undefined]
34
+ def use_upcaster_tag(upcaster_tag)
35
+ @upcaster_tag = upcaster_tag
36
+ end
37
+
38
+ protected
39
+
40
+ # @return [undefined]
41
+ def populate_defaults
42
+ identified_by :upcaster_chain
43
+
44
+ use_converter_factory :converter_factory
45
+ use_upcaster_tag :upcaster
46
+
47
+ use_factory do
48
+ converter_factory = resolve @converter_factory
49
+
50
+ upcaster_chain = Upcasting::UpcasterChain.new converter_factory
51
+
52
+ with_tagged @upcaster_tag do |upcaster|
53
+ upcaster_chain.push upcaster
54
+ end
55
+
56
+ upcaster_chain
57
+ end
58
+ end
59
+ end # UpcasterChainDefinitionBuilder
60
+ end # Configuration
61
+ end
@@ -0,0 +1,15 @@
1
+ module Synapse
2
+ module Configuration
3
+ class ContainerBuilder
4
+ # Creates and configures an upcaster chain
5
+ #
6
+ # @see UpcasterChainDefinitionBuilder
7
+ # @param [Symbol] identifier
8
+ # @param [Proc] block
9
+ # @return [undefined]
10
+ def upcaster_chain(identifier = nil, &block)
11
+ with_definition_builder UpcasterChainDefinitionBuilder, identifier, &block
12
+ end
13
+ end # ContainerBuilder
14
+ end # Configuration
15
+ end
@@ -0,0 +1,80 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Container used for storing and resolving definitions of services
4
+ # @see ContainerBuilder
5
+ class Container
6
+ def initialize
7
+ @definitions = Hash.new
8
+ @logger = Logging.logger[self.class]
9
+ end
10
+
11
+ # Injects any configured dependencies into the given object
12
+ #
13
+ # @param [Dependent] object
14
+ # @return [undefined]
15
+ def inject_into(object)
16
+ return unless object.is_a? Dependent
17
+
18
+ dependencies = object.class.dependencies
19
+ dependencies.each_pair do |id, attribute|
20
+ resolved = resolve id
21
+ object.public_send "#{attribute}=", resolved
22
+ end
23
+ end
24
+
25
+ # Locates the definition for a service with the given identifier and resolves it to the
26
+ # object being provided
27
+ #
28
+ # @raise [ArgumentError] If definition could not be found and is required
29
+ # @param [Symbol] id
30
+ # @param [Boolean] optional Default is false
31
+ # @return [Object]
32
+ def resolve(id, optional = false)
33
+ if @definitions.has_key? id
34
+ @definitions[id].resolve
35
+ elsif not optional
36
+ raise ConfigurationError, 'Definition for service [%s] not found' % id
37
+ end
38
+ end
39
+
40
+ alias [] resolve
41
+
42
+ # Resolves any definitions that have the given tag
43
+ #
44
+ # @param [Symbol] tag
45
+ # @return [Array]
46
+ def resolve_tagged(tag)
47
+ resolved = Array.new
48
+
49
+ @definitions.each_value do |definition|
50
+ if definition.tags and definition.tags.include? tag
51
+ resolved.push definition.resolve
52
+ end
53
+ end
54
+
55
+ resolved
56
+ end
57
+
58
+ # Registers a service definition with this container
59
+ #
60
+ # @param [Symbol] id
61
+ # @param [Definition] definition
62
+ # @return [undefined]
63
+ def register(id, definition)
64
+ if @definitions.has_key? id
65
+ @logger.info 'Definition [%s] is being replaced' % id
66
+ end
67
+
68
+ @definitions.store id, definition
69
+ end
70
+
71
+ # Returns true if a service definition with the given identifier is registered
72
+ #
73
+ # @param [Symbol] id
74
+ # @return [Boolean]
75
+ def registered?(id)
76
+ @definitions.has_key? id
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,108 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Provides a DSL for end-users to easily configure the Synapse service container
4
+ # @see Synapse#build
5
+ class ContainerBuilder
6
+ # Registered initializers that will be executed upon instantiation
7
+ # @return [Array]
8
+ class_attribute :initializers
9
+
10
+ # Registers a block that will be executed upon instantiation of a container builder
11
+ #
12
+ # This is useful for defining common services that are likely to be depended upon by
13
+ # other services being built
14
+ #
15
+ # @param [Proc] initializer
16
+ # @return [undefined]
17
+ def self.initializer(&initializer)
18
+ self.initializers ||= Array.new
19
+ self.initializers.push initializer
20
+ end
21
+
22
+ # @return [Container]
23
+ attr_reader :container
24
+
25
+ # @param [Container] container
26
+ # @return [undefined]
27
+ def initialize(container)
28
+ @container = container
29
+
30
+ if initializers
31
+ initializers.each do |initializer|
32
+ build_with(&initializer)
33
+ end
34
+ end
35
+ end
36
+
37
+ # Executes the given block in the context of the container builder
38
+ #
39
+ # @param [Proc] block
40
+ # @return [undefined]
41
+ def build_with(&block)
42
+ instance_exec(&block)
43
+ end
44
+
45
+ # Executes the given block in the context of a new definition builder
46
+ #
47
+ # @example
48
+ # definition :account_projection do
49
+ # tag :event_listener, :projection
50
+ # use_factory do
51
+ # AccountProjection.new
52
+ # end
53
+ # end
54
+ #
55
+ # @see #factory If the definition being created is simple
56
+ # @see DefinitionBuilder
57
+ # @param [Symbol] id
58
+ # @param [Proc] block
59
+ # @return [undefined]
60
+ def definition(id = nil, &block)
61
+ with_definition_builder DefinitionBuilder, id, &block
62
+ end
63
+
64
+ # Simple usage of the definition builder
65
+ #
66
+ # The given block is used as a deferred factory and will be executed in the context of the
67
+ # definition builder. If a tag option is provided, the definition will be tagged with the
68
+ # given symbols.
69
+ #
70
+ # The definition that is created will be a singleton.
71
+ #
72
+ # @example
73
+ # factory :account_projection, :tag => [:event_listener, :projection] do
74
+ # AccountProjection.new
75
+ # end
76
+ #
77
+ # @see DefinitionBuilder#use_factory
78
+ # @param [Symbol] id
79
+ # @param [Object...] args
80
+ # @param [Proc] block
81
+ # @return [undefined]
82
+ def factory(id, *args, &block)
83
+ options = args.extract_options!
84
+
85
+ with_definition_builder DefinitionBuilder, id do
86
+ use_factory(&block)
87
+ if options.has_key? :tag
88
+ tag(*options.fetch(:tag))
89
+ end
90
+ end
91
+ end
92
+
93
+ protected
94
+
95
+ # Creates a definition builder of the given type, uses the identifier (if any is given),
96
+ # executes the block in the context of the definition builder, then finally builds and
97
+ # registers the definition with this builder's associate container.
98
+ #
99
+ # @param [Class] builder_type
100
+ # @param [Symbol] id
101
+ # @param [Proc] block
102
+ # @return [undefined]
103
+ def with_definition_builder(builder_type, id, &block)
104
+ builder_type.build @container, id, &block
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,31 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Represents a definition for a service being provided by the container
4
+ # @see DefinitionBuilder
5
+ class Definition
6
+ # @return [Set] Symbols that this definition is tagged with
7
+ attr_reader :tags
8
+
9
+ # @param [Set] tags
10
+ # @param [Boolean] prototype
11
+ # @param [Proc] factory
12
+ # @param [Object] instance
13
+ # @return [undefined]
14
+ def initialize(tags, prototype, factory, instance)
15
+ @tags = tags
16
+ @prototype = prototype
17
+ @factory = factory
18
+ @instance = instance
19
+ end
20
+
21
+ # @return [Object]
22
+ def resolve
23
+ if @prototype
24
+ @factory.call
25
+ else
26
+ @instance ||= @factory.call
27
+ end
28
+ end
29
+ end # Definition
30
+ end # Configuration
31
+ end
@@ -0,0 +1,138 @@
1
+ module Synapse
2
+ module Configuration
3
+ # DSL for building service definitions
4
+ class DefinitionBuilder
5
+ # @return [Symbol]
6
+ attr_reader :id
7
+
8
+ # @yield [DefinitionBuilder]
9
+ # @param [Container] container
10
+ # @param [Symbol] id
11
+ # @param [Proc] block
12
+ # @return [undefined]
13
+ def self.build(container, id = nil, &block)
14
+ builder = self.new container, id
15
+ builder.instance_exec(&block) if block
16
+ builder.register_definition
17
+
18
+ builder.id
19
+ end
20
+
21
+ # @param [Container] container
22
+ # @param [Symbol] id
23
+ # @return [undefined]
24
+ def initialize(container, id = nil)
25
+ @container = container
26
+ @prototype = false
27
+ @tags = Set.new
28
+
29
+ populate_defaults
30
+
31
+ @id = id.to_sym if id
32
+ end
33
+
34
+ # @param [Symbol] id
35
+ # @return [undefined]
36
+ def identified_by(id)
37
+ @id = id.to_sym
38
+ end
39
+
40
+ # @return [undefined]
41
+ def anonymous
42
+ identified_by SecureRandom.hex 8
43
+ end
44
+
45
+ # @param [Symbol...] tags
46
+ # @return [undefined]
47
+ def tag(*tags)
48
+ @tags.merge tags.flatten
49
+ end
50
+
51
+ # @return [undefined]
52
+ def as_prototype
53
+ @prototype = true
54
+ end
55
+
56
+ # @return [undefined]
57
+ def as_singleton
58
+ @prototype = false
59
+ end
60
+
61
+ # @param [Proc] factory
62
+ # @return [undefined]
63
+ def use_factory(&factory)
64
+ @factory = proc do
65
+ instance_exec(&factory)
66
+ end
67
+ end
68
+
69
+ # @param [Object] instance
70
+ # @return [undefined]
71
+ def use_instance(instance)
72
+ @instance = instance
73
+ end
74
+
75
+ # If the given value is a symbol, it will be resolved using the container. Otherwise, it
76
+ # will be passed through
77
+ #
78
+ # @param [Object] value
79
+ # @return [Object]
80
+ def resolve(value, optional = false)
81
+ if value.is_a? Symbol
82
+ @container.resolve value, optional
83
+ else
84
+ value
85
+ end
86
+ end
87
+
88
+ # Resolves all services that have the given tag
89
+ #
90
+ # @param [Symbol] tag
91
+ # @return [Array]
92
+ def resolve_tagged(tag)
93
+ @container.resolve_tagged tag
94
+ end
95
+
96
+ # Convenience method for building composite services
97
+ #
98
+ # The given block will be executed in the context of the definition builder
99
+ #
100
+ # @param [Class] builder_type Defaults to DefinitionBuilder
101
+ # @param [Proc] block
102
+ # @return [Symbol] The identifier of the newly created service
103
+ def build_composite(builder_type = DefinitionBuilder, &block)
104
+ builder_type.build @container, &block
105
+ end
106
+
107
+ # @return [Definition]
108
+ def build_definition
109
+ Definition.new @tags, @prototype, @factory, @instance
110
+ end
111
+
112
+ # @return [undefined]
113
+ def register_definition
114
+ unless @id
115
+ raise ConfigurationError, 'No identifier set for the definition'
116
+ end
117
+
118
+ @container.register @id, build_definition
119
+ end
120
+
121
+ protected
122
+
123
+ # Sets the default values for the definition being built
124
+ # @return [undefined]
125
+ def populate_defaults; end
126
+
127
+ # Resolves any services with the given tag and yields them
128
+ #
129
+ # @yield [Object]
130
+ # @param [Symbol] tag
131
+ # @return [undefined]
132
+ def with_tagged(tag, &block)
133
+ tagged = resolve_tagged tag
134
+ tagged.each &block
135
+ end
136
+ end # DefinitionBuilder
137
+ end # Configuration
138
+ end
@@ -0,0 +1,31 @@
1
+ module Synapse
2
+ module Configuration
3
+ # Mixin for an object defines its dependencies so that they can be auto-injected by the
4
+ # service container after it has been instantiated
5
+ #
6
+ # Note that this only supports setter injection
7
+ module Dependent
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ # @return [Hash]
12
+ class_attribute :dependencies, instance_accessor: false
13
+ self.dependencies = Hash.new
14
+ end
15
+
16
+ module ClassMethods
17
+ # @param [Symbol] service
18
+ # @param [Object...] args
19
+ # @return [undefined]
20
+ def depends_on(service, *args)
21
+ options = args.extract_options!
22
+
23
+ attribute = options[:attribute] || service
24
+ attr_accessor attribute
25
+
26
+ self.dependencies[service] = attribute
27
+ end
28
+ end
29
+ end # Dependent
30
+ end # Configuration
31
+ end
@@ -0,0 +1,35 @@
1
+ module Synapse
2
+ # @return [Configuration::Container]
3
+ mattr_accessor :container
4
+
5
+ # @return [Configuration::ContainerBuilder]
6
+ mattr_accessor :container_builder
7
+
8
+ # Initializes the service container and the container builder
9
+ #
10
+ # The given block is executed in the container of the container builder. Factory blocks are
11
+ # always deferred until the service is needed to build another service or is manually
12
+ # requested from the container.
13
+ #
14
+ # This method can be called multiple times without losing the state of the container.
15
+ #
16
+ # @example
17
+ # Synapse.build do
18
+ # definition :account_projection do
19
+ # tag :event_listener, :projection
20
+ # use_factory do
21
+ # Bank::Projections::AccountProjection.new
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ # @see Configuration::ContainerBuilder#build_with
27
+ # @param [Proc] block
28
+ # @return [undefined]
29
+ def self.build(&block)
30
+ self.container ||= Configuration::Container.new
31
+ self.container_builder ||= Configuration::ContainerBuilder.new self.container
32
+
33
+ self.container_builder.build_with(&block)
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ require 'synapse/configuration/container'
2
+ require 'synapse/configuration/container_builder'
3
+ require 'synapse/configuration/definition'
4
+ require 'synapse/configuration/definition_builder'
5
+ require 'synapse/configuration/dependent'
6
+ require 'synapse/configuration/ext'
7
+
8
+ require 'synapse/configuration/component/command_bus'
9
+ # Has to be loaded before asynchronous command bus definition builder
10
+ require 'synapse/configuration/component/command_bus/simple_command_bus'
11
+ require 'synapse/configuration/component/command_bus/async_command_bus'
12
+
13
+ require 'synapse/configuration/component/event_bus'
14
+ require 'synapse/configuration/component/event_bus/simple_event_bus'
15
+
16
+ require 'synapse/configuration/component/repository'
17
+ # Has to be loaded before event sourcing or simple repository definition builders
18
+ require 'synapse/configuration/component/repository/locking_repository'
19
+ require 'synapse/configuration/component/repository/simple_repository'
20
+
21
+ require 'synapse/configuration/component/event_sourcing'
22
+ require 'synapse/configuration/component/event_sourcing/repository'
23
+
24
+ require 'synapse/configuration/component/serialization'
25
+ require 'synapse/configuration/component/serialization/converter_factory'
26
+ require 'synapse/configuration/component/serialization/serializer'
27
+
28
+ require 'synapse/configuration/component/uow'
29
+ require 'synapse/configuration/component/uow/unit_factory'
30
+
31
+ require 'synapse/configuration/component/upcasting'
32
+ require 'synapse/configuration/component/upcasting/upcaster_chain'
@@ -13,17 +13,6 @@ module Synapse
13
13
  # @return [Integer] The version of this aggregate
14
14
  attr_reader :version
15
15
 
16
- # Adds a listener that will be notified when this aggregate registers an event to be published
17
- #
18
- # If an event registration listener is added after events have already been registered, it
19
- # will still get a change to process the uncommitted events in this aggregate.
20
- #
21
- # @param [#call] listener
22
- # @return [undefined]
23
- def add_registration_listener(&listener)
24
- event_container.add_registration_listener listener
25
- end
26
-
27
16
  # Marks this aggregate as committed by a repository
28
17
  # @return [undefined]
29
18
  def mark_committed
@@ -53,21 +42,37 @@ module Synapse
53
42
  @event_container.to_stream
54
43
  end
55
44
 
56
- protected
57
-
58
- # Publishes a domain event with the given payload and metadata (optional)
45
+ # Adds a listener that will be notified when this aggregate registers an event to be published
59
46
  #
60
- # @param [Object] payload
61
- # Payload of the message; the actual event object
47
+ # If an event registration listener is added after events have already been registered, it
48
+ # will still get a change to process the uncommitted events in this aggregate.
62
49
  #
63
- # @param [Hash] metadata
64
- # Metadata associated with the event
50
+ # @param [#call] listener
51
+ # @return [undefined]
52
+ def add_registration_listener(&listener)
53
+ event_container.add_registration_listener listener
54
+ end
55
+
56
+ protected
57
+
58
+ # Publishes a domain event with the given payload and optional metadata
65
59
  #
60
+ # @api public
61
+ # @param [Object] payload Payload of the message; the actual event object
62
+ # @param [Hash] metadata Metadata associated with the event
66
63
  # @return [DomainEventMessage] The event that will be committed
67
64
  def publish_event(payload, metadata = nil)
68
65
  event_container.register_event payload, metadata
69
66
  end
70
67
 
68
+ # Marks this aggregate for deletion by its repository
69
+ #
70
+ # @api public
71
+ # @return [undefined]
72
+ def mark_deleted
73
+ @deleted = true
74
+ end
75
+
71
76
  # Initializes the event container with the given sequence number
72
77
  #
73
78
  # @param [Integer] last_sequence_number
@@ -89,12 +94,6 @@ module Synapse
89
94
  @event_container.last_committed_sequence_number
90
95
  end
91
96
 
92
- # Marks this aggregate for deletion by its repository
93
- # @return [undefined]
94
- def mark_deleted
95
- @deleted = true
96
- end
97
-
98
97
  private
99
98
 
100
99
  # Initializes the uncommitted event container for this aggregate, if not already
@@ -103,11 +102,11 @@ module Synapse
103
102
  # @return [EventContainer]
104
103
  def event_container
105
104
  unless @event_container
106
- unless @id
105
+ unless id
107
106
  raise AggregateIdentifierNotInitializedError
108
107
  end
109
108
 
110
- @event_container = EventContainer.new @id
109
+ @event_container = EventContainer.new id
111
110
  @event_container.initialize_sequence_number @last_sequence_number
112
111
  end
113
112
 
@@ -34,11 +34,11 @@ module Synapse
34
34
  #
35
35
  # @return [DomainEventMessage] The event that will be committed
36
36
  def register_event(payload, metadata)
37
- event = DomainEventMessage.build do |b|
38
- b.aggregate_id = @aggregate_id
39
- b.sequence_number = next_sequence_number
40
- b.metadata = metadata
41
- b.payload = payload
37
+ event = DomainEventMessage.build do |builder|
38
+ builder.aggregate_id = @aggregate_id
39
+ builder.sequence_number = next_sequence_number
40
+ builder.metadata = metadata
41
+ builder.payload = payload
42
42
  end
43
43
 
44
44
  @listeners.each do |listener|
@@ -23,6 +23,22 @@ module Synapse
23
23
  EventMessageBuilder
24
24
  end
25
25
 
26
+ # Creates an event message using the given event object
27
+ #
28
+ # If the given object is an event message, it will be returned unchanged.
29
+ #
30
+ # @param [Object] event
31
+ # @return [EventMessage]
32
+ def self.as_message(event)
33
+ unless event.is_a? EventMessage
34
+ event = self.build do |builder|
35
+ builder.payload = event
36
+ end
37
+ end
38
+
39
+ event
40
+ end
41
+
26
42
  protected
27
43
 
28
44
  # @param [EventMessageBuilder] builder
@@ -3,6 +3,8 @@ module Synapse
3
3
  # Represents a listener that can be notified of events from an event bus. Implementations are
4
4
  # highly discouraged from throwing exceptions.
5
5
  #
6
+ # Consider using the event listener mixin that uses message wiring.
7
+ #
6
8
  # @abstract
7
9
  module EventListener
8
10
  # Called when an event is published to the event bus