synapse-core 0.4.0 → 0.5.1

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