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.
- 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
|