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.
- data/lib/synapse/command/async_command_bus.rb +41 -0
- data/lib/synapse/command/command_callback.rb +49 -2
- data/lib/synapse/command/command_handler.rb +2 -0
- data/lib/synapse/command/filters/validation.rb +2 -2
- data/lib/synapse/command/gateway/interval_retry_scheduler.rb +75 -0
- data/lib/synapse/command/gateway/retry_scheduler.rb +26 -0
- data/lib/synapse/command/gateway/retrying_callback.rb +46 -0
- data/lib/synapse/command/gateway.rb +56 -11
- data/lib/synapse/command/interceptor_chain.rb +2 -2
- data/lib/synapse/command/interceptors/serialization.rb +2 -2
- data/lib/synapse/command/message.rb +16 -0
- data/lib/synapse/command/simple_command_bus.rb +6 -2
- data/lib/synapse/command/wiring.rb +3 -3
- data/lib/synapse/command.rb +7 -1
- data/lib/synapse/common/concurrency/identifier_lock.rb +2 -17
- data/lib/synapse/common/concurrency/public_lock.rb +8 -9
- data/lib/synapse/common/errors.rb +1 -1
- data/lib/synapse/common/message.rb +2 -6
- data/lib/synapse/common.rb +9 -0
- data/lib/synapse/configuration/component/command_bus/async_command_bus.rb +41 -0
- data/lib/synapse/configuration/component/command_bus/gateway.rb +38 -0
- data/lib/synapse/configuration/component/command_bus/simple_command_bus.rb +81 -0
- data/lib/synapse/configuration/component/command_bus.rb +35 -0
- data/lib/synapse/configuration/component/event_bus/simple_event_bus.rb +41 -0
- data/lib/synapse/configuration/component/event_bus.rb +15 -0
- data/lib/synapse/configuration/component/event_sourcing/repository.rb +62 -0
- data/lib/synapse/configuration/component/event_sourcing.rb +15 -0
- data/lib/synapse/configuration/component/repository/locking_repository.rb +85 -0
- data/lib/synapse/configuration/component/repository/simple_repository.rb +31 -0
- data/lib/synapse/configuration/component/repository.rb +15 -0
- data/lib/synapse/configuration/component/serialization/converter_factory.rb +50 -0
- data/lib/synapse/configuration/component/serialization/serializer.rb +90 -0
- data/lib/synapse/configuration/component/serialization.rb +25 -0
- data/lib/synapse/configuration/component/uow/unit_factory.rb +51 -0
- data/lib/synapse/configuration/component/uow.rb +22 -0
- data/lib/synapse/configuration/component/upcasting/upcaster_chain.rb +61 -0
- data/lib/synapse/configuration/component/upcasting.rb +15 -0
- data/lib/synapse/configuration/container.rb +80 -0
- data/lib/synapse/configuration/container_builder.rb +108 -0
- data/lib/synapse/configuration/definition.rb +31 -0
- data/lib/synapse/configuration/definition_builder.rb +138 -0
- data/lib/synapse/configuration/dependent.rb +31 -0
- data/lib/synapse/configuration/ext.rb +35 -0
- data/lib/synapse/configuration.rb +32 -0
- data/lib/synapse/domain/aggregate_root.rb +25 -26
- data/lib/synapse/domain/event_container.rb +5 -5
- data/lib/synapse/domain/message.rb +16 -0
- data/lib/synapse/event_bus/event_listener.rb +2 -0
- data/lib/synapse/event_bus/event_publisher.rb +19 -0
- data/lib/synapse/event_bus/simple_event_bus.rb +21 -30
- data/lib/synapse/event_bus/wiring.rb +5 -4
- data/lib/synapse/event_bus.rb +1 -1
- data/lib/synapse/event_sourcing/aggregate_root.rb +6 -4
- data/lib/synapse/process_manager/container_resource_injector.rb +18 -0
- data/lib/synapse/process_manager/pessimistic_lock_manager.rb +1 -1
- data/lib/synapse/process_manager/process.rb +4 -0
- data/lib/synapse/process_manager/process_factory.rb +3 -3
- data/lib/synapse/process_manager/repository/in_memory.rb +1 -1
- data/lib/synapse/process_manager/wiring/process.rb +6 -6
- data/lib/synapse/process_manager/wiring/process_manager.rb +8 -8
- data/lib/synapse/process_manager.rb +2 -0
- data/lib/synapse/repository/locking.rb +5 -3
- data/lib/synapse/repository/optimistic_lock_manager.rb +2 -7
- data/lib/synapse/repository/pessimistic_lock_manager.rb +3 -3
- data/lib/synapse/repository/repository.rb +2 -2
- data/lib/synapse/repository/simple_repository.rb +69 -0
- data/lib/synapse/repository.rb +1 -0
- data/lib/synapse/serialization/converter/chain.rb +2 -2
- data/lib/synapse/serialization/converter_factory.rb +2 -2
- data/lib/synapse/serialization/lazy_object.rb +2 -2
- data/lib/synapse/serialization/message/serialization_aware_message.rb +3 -3
- data/lib/synapse/serialization/message/serialized_message.rb +6 -10
- data/lib/synapse/serialization/message/serialized_message_builder.rb +4 -4
- data/lib/synapse/serialization/message/serialized_object_cache.rb +2 -2
- data/lib/synapse/serialization/message/serializer.rb +2 -2
- data/lib/synapse/serialization/revision_resolver.rb +3 -3
- data/lib/synapse/serialization/serialized_object.rb +2 -2
- data/lib/synapse/serialization/serialized_type.rb +2 -2
- data/lib/synapse/serialization/serializer/attribute.rb +2 -2
- data/lib/synapse/serialization/serializer/marshal.rb +2 -2
- data/lib/synapse/serialization/serializer/oj.rb +2 -2
- data/lib/synapse/serialization/serializer/ox.rb +2 -2
- data/lib/synapse/serialization/serializer.rb +2 -2
- data/lib/synapse/uow/factory.rb +2 -2
- data/lib/synapse/uow/listener_collection.rb +2 -2
- data/lib/synapse/uow/nesting.rb +9 -2
- data/lib/synapse/uow/provider.rb +2 -2
- data/lib/synapse/uow/uow.rb +8 -2
- data/lib/synapse/upcasting/{chain.rb → upcaster_chain.rb} +0 -0
- data/lib/synapse/upcasting.rb +1 -1
- data/lib/synapse/version.rb +1 -1
- data/lib/synapse/wiring/message_wiring.rb +31 -0
- data/lib/synapse.rb +2 -14
- data/test/auditing/data_provider_test.rb +2 -2
- data/test/auditing/dispatch_interceptor_test.rb +1 -1
- data/test/auditing/unit_listener_test.rb +3 -3
- data/test/command/async_command_bus_test.rb +49 -0
- data/test/command/duplication_test.rb +2 -2
- data/test/command/gateway/interval_retry_scheduler_test.rb +42 -0
- data/test/command/gateway/retrying_callback_test.rb +57 -0
- data/test/command/gateway_test.rb +41 -7
- data/test/command/interceptor_chain_test.rb +1 -1
- data/test/command/message_test.rb +17 -0
- data/test/command/serialization_test.rb +2 -2
- data/test/command/simple_command_bus_test.rb +7 -7
- data/test/command/validation_test.rb +3 -3
- data/test/command/wiring_test.rb +3 -3
- data/test/common/concurrency/identifier_lock_test.rb +2 -13
- data/test/common/concurrency/public_lock_test.rb +6 -6
- data/test/{duplication_test.rb → common/duplication_test.rb} +3 -3
- data/test/configuration/component/command_bus/async_command_bus_test.rb +36 -0
- data/test/configuration/component/command_bus/simple_command_bus_test.rb +57 -0
- data/test/configuration/component/event_bus/simple_event_bus_test.rb +58 -0
- data/test/configuration/component/serialization/converter_factory_test.rb +48 -0
- data/test/configuration/component/serialization/serializer_test.rb +78 -0
- data/test/configuration/component/uow/unit_factory_test.rb +46 -0
- data/test/configuration/container_builder_test.rb +47 -0
- data/test/configuration/container_test.rb +88 -0
- data/test/configuration/definition_builder_test.rb +126 -0
- data/test/configuration/definition_test.rb +41 -0
- data/test/configuration/dependent_test.rb +30 -0
- data/test/configuration/ext_test.rb +19 -0
- data/test/configuration/fixtures/dependent.rb +10 -0
- data/test/domain/aggregate_root_test.rb +5 -5
- data/test/domain/message_test.rb +15 -3
- data/test/domain/stream_test.rb +2 -2
- data/test/event_bus/publisher_test.rb +29 -0
- data/test/event_bus/wiring_test.rb +1 -1
- data/test/event_sourcing/aggregate_factory_test.rb +12 -6
- data/test/event_sourcing/aggregate_root_test.rb +4 -4
- data/test/event_sourcing/entity_test.rb +10 -9
- data/test/event_sourcing/repository_test.rb +6 -6
- data/test/event_sourcing/storage_listener_test.rb +8 -4
- data/test/event_store/in_memory_test.rb +3 -3
- data/test/process_manager/container_resource_injector_test.rb +19 -0
- data/test/process_manager/correlation_set_test.rb +2 -2
- data/test/process_manager/correlation_test.rb +2 -2
- data/test/process_manager/in_memory_test.rb +3 -3
- data/test/process_manager/process_factory_test.rb +2 -2
- data/test/process_manager/process_test.rb +3 -3
- data/test/process_manager/simple_process_manager_test.rb +5 -5
- data/test/process_manager/wiring/process_manager_test.rb +4 -4
- data/test/process_manager/wiring/process_test.rb +2 -2
- data/test/repository/locking_test.rb +4 -4
- data/test/repository/optimistic_test.rb +2 -2
- data/test/repository/pessimistic_test.rb +1 -1
- data/test/repository/simple_repository_test.rb +79 -0
- data/test/support/countdown_latch.rb +18 -0
- data/test/test_helper.rb +6 -3
- data/test/upcasting/data_test.rb +31 -0
- metadata +84 -25
- data/lib/synapse/event_bus/event_listener_proxy.rb +0 -12
- data/lib/synapse/partitioning/memory_queue_reader.rb +0 -31
- data/lib/synapse/partitioning/memory_queue_writer.rb +0 -19
- data/lib/synapse/partitioning/message_receipt.rb +0 -25
- data/lib/synapse/partitioning/packing/json_packer.rb +0 -93
- data/lib/synapse/partitioning/packing/json_unpacker.rb +0 -83
- data/lib/synapse/partitioning/packing.rb +0 -27
- data/lib/synapse/partitioning/queue_reader.rb +0 -32
- data/lib/synapse/partitioning/queue_writer.rb +0 -17
- data/lib/synapse/partitioning.rb +0 -18
- data/test/partitioning/memory_test.rb +0 -34
- 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
|
-
|
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
|
-
#
|
61
|
-
#
|
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 [
|
64
|
-
#
|
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
|
105
|
+
unless id
|
107
106
|
raise AggregateIdentifierNotInitializedError
|
108
107
|
end
|
109
108
|
|
110
|
-
@event_container = EventContainer.new
|
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 |
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|