synapse-core 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. data/lib/synapse.rb +351 -0
  2. data/lib/synapse/command/command_bus.rb +45 -0
  3. data/lib/synapse/command/command_callback.rb +18 -0
  4. data/lib/synapse/command/command_filter.rb +17 -0
  5. data/lib/synapse/command/command_handler.rb +13 -0
  6. data/lib/synapse/command/dispatch_interceptor.rb +16 -0
  7. data/lib/synapse/command/duplication.rb +43 -0
  8. data/lib/synapse/command/errors.rb +27 -0
  9. data/lib/synapse/command/filters/validation.rb +32 -0
  10. data/lib/synapse/command/gateway.rb +34 -0
  11. data/lib/synapse/command/interceptor_chain.rb +31 -0
  12. data/lib/synapse/command/interceptors/serialization.rb +35 -0
  13. data/lib/synapse/command/message.rb +19 -0
  14. data/lib/synapse/command/rollback_policy.rb +22 -0
  15. data/lib/synapse/command/simple_command_bus.rb +138 -0
  16. data/lib/synapse/command/wiring.rb +47 -0
  17. data/lib/synapse/domain/aggregate_root.rb +121 -0
  18. data/lib/synapse/domain/event_container.rb +127 -0
  19. data/lib/synapse/domain/message.rb +82 -0
  20. data/lib/synapse/domain/message_builder.rb +34 -0
  21. data/lib/synapse/domain/stream.rb +108 -0
  22. data/lib/synapse/duplication.rb +60 -0
  23. data/lib/synapse/errors.rb +13 -0
  24. data/lib/synapse/event_bus/event_bus.rb +40 -0
  25. data/lib/synapse/event_bus/event_listener.rb +16 -0
  26. data/lib/synapse/event_bus/event_listener_proxy.rb +12 -0
  27. data/lib/synapse/event_bus/simple_event_bus.rb +69 -0
  28. data/lib/synapse/event_bus/wiring.rb +23 -0
  29. data/lib/synapse/event_sourcing/aggregate_factory.rb +69 -0
  30. data/lib/synapse/event_sourcing/aggregate_root.rb +104 -0
  31. data/lib/synapse/event_sourcing/conflict_resolver.rb +80 -0
  32. data/lib/synapse/event_sourcing/entity.rb +64 -0
  33. data/lib/synapse/event_sourcing/member.rb +72 -0
  34. data/lib/synapse/event_sourcing/repository.rb +119 -0
  35. data/lib/synapse/event_sourcing/snapshot/count_stream.rb +86 -0
  36. data/lib/synapse/event_sourcing/snapshot/count_trigger.rb +91 -0
  37. data/lib/synapse/event_sourcing/snapshot/taker.rb +73 -0
  38. data/lib/synapse/event_sourcing/storage_listener.rb +34 -0
  39. data/lib/synapse/event_sourcing/stream_decorator.rb +25 -0
  40. data/lib/synapse/event_store/errors.rb +16 -0
  41. data/lib/synapse/event_store/event_store.rb +43 -0
  42. data/lib/synapse/event_store/in_memory.rb +59 -0
  43. data/lib/synapse/event_store/mongo/cursor_event_stream.rb +63 -0
  44. data/lib/synapse/event_store/mongo/event_store.rb +86 -0
  45. data/lib/synapse/event_store/mongo/per_commit_strategy.rb +253 -0
  46. data/lib/synapse/event_store/mongo/per_event_strategy.rb +143 -0
  47. data/lib/synapse/event_store/mongo/storage_strategy.rb +113 -0
  48. data/lib/synapse/event_store/mongo/template.rb +73 -0
  49. data/lib/synapse/identifier.rb +23 -0
  50. data/lib/synapse/message.rb +101 -0
  51. data/lib/synapse/message_builder.rb +38 -0
  52. data/lib/synapse/process_manager/correlation.rb +32 -0
  53. data/lib/synapse/process_manager/correlation_resolver.rb +14 -0
  54. data/lib/synapse/process_manager/correlation_set.rb +58 -0
  55. data/lib/synapse/process_manager/process.rb +71 -0
  56. data/lib/synapse/repository/errors.rb +26 -0
  57. data/lib/synapse/repository/lock_manager.rb +40 -0
  58. data/lib/synapse/repository/locking.rb +97 -0
  59. data/lib/synapse/repository/pessimistic_lock_manager.rb +61 -0
  60. data/lib/synapse/repository/repository.rb +109 -0
  61. data/lib/synapse/serialization/converter.rb +39 -0
  62. data/lib/synapse/serialization/converter/chain.rb +45 -0
  63. data/lib/synapse/serialization/converter/factory.rb +68 -0
  64. data/lib/synapse/serialization/converter/identity.rb +29 -0
  65. data/lib/synapse/serialization/converter/json.rb +31 -0
  66. data/lib/synapse/serialization/converter/ox.rb +31 -0
  67. data/lib/synapse/serialization/errors.rb +12 -0
  68. data/lib/synapse/serialization/lazy_object.rb +61 -0
  69. data/lib/synapse/serialization/message/data.rb +25 -0
  70. data/lib/synapse/serialization/message/metadata.rb +13 -0
  71. data/lib/synapse/serialization/message/serialization_aware.rb +17 -0
  72. data/lib/synapse/serialization/message/serialization_aware_message.rb +66 -0
  73. data/lib/synapse/serialization/message/serialized_message.rb +201 -0
  74. data/lib/synapse/serialization/message/serialized_message_builder.rb +64 -0
  75. data/lib/synapse/serialization/message/serialized_object_cache.rb +50 -0
  76. data/lib/synapse/serialization/message/serializer.rb +47 -0
  77. data/lib/synapse/serialization/revision_resolver.rb +30 -0
  78. data/lib/synapse/serialization/serialized_object.rb +37 -0
  79. data/lib/synapse/serialization/serialized_type.rb +31 -0
  80. data/lib/synapse/serialization/serializer.rb +98 -0
  81. data/lib/synapse/serialization/serializer/marshal.rb +32 -0
  82. data/lib/synapse/serialization/serializer/oj.rb +34 -0
  83. data/lib/synapse/serialization/serializer/ox.rb +31 -0
  84. data/lib/synapse/uow/factory.rb +28 -0
  85. data/lib/synapse/uow/listener.rb +79 -0
  86. data/lib/synapse/uow/listener_collection.rb +93 -0
  87. data/lib/synapse/uow/nesting.rb +262 -0
  88. data/lib/synapse/uow/provider.rb +71 -0
  89. data/lib/synapse/uow/storage_listener.rb +14 -0
  90. data/lib/synapse/uow/transaction_manager.rb +27 -0
  91. data/lib/synapse/uow/uow.rb +178 -0
  92. data/lib/synapse/upcasting/chain.rb +78 -0
  93. data/lib/synapse/upcasting/context.rb +58 -0
  94. data/lib/synapse/upcasting/data.rb +30 -0
  95. data/lib/synapse/upcasting/single_upcaster.rb +57 -0
  96. data/lib/synapse/upcasting/upcaster.rb +55 -0
  97. data/lib/synapse/version.rb +3 -0
  98. data/lib/synapse/wiring/message_wiring.rb +41 -0
  99. data/lib/synapse/wiring/wire.rb +55 -0
  100. data/lib/synapse/wiring/wire_registry.rb +61 -0
  101. data/test/command/duplication_test.rb +54 -0
  102. data/test/command/gateway_test.rb +25 -0
  103. data/test/command/interceptor_chain_test.rb +26 -0
  104. data/test/command/serialization_test.rb +37 -0
  105. data/test/command/simple_command_bus_test.rb +141 -0
  106. data/test/command/validation_test.rb +42 -0
  107. data/test/command/wiring_test.rb +73 -0
  108. data/test/domain/aggregate_root_test.rb +57 -0
  109. data/test/domain/fixtures.rb +31 -0
  110. data/test/domain/message_test.rb +61 -0
  111. data/test/domain/stream_test.rb +35 -0
  112. data/test/duplication_test.rb +40 -0
  113. data/test/event_bus/wiring_test.rb +46 -0
  114. data/test/event_sourcing/aggregate_factory_test.rb +28 -0
  115. data/test/event_sourcing/aggregate_root_test.rb +76 -0
  116. data/test/event_sourcing/entity_test.rb +34 -0
  117. data/test/event_sourcing/fixtures.rb +85 -0
  118. data/test/event_sourcing/repository_test.rb +102 -0
  119. data/test/event_sourcing/snapshot/aggregate_taker_test.rb +39 -0
  120. data/test/event_sourcing/snapshot/deferred_taker_test.rb +19 -0
  121. data/test/event_sourcing/snapshot/integration_test.rb +65 -0
  122. data/test/event_sourcing/storage_listener_test.rb +77 -0
  123. data/test/event_store/in_memory_test.rb +47 -0
  124. data/test/process_manager/correlation_set_test.rb +49 -0
  125. data/test/process_manager/correlation_test.rb +24 -0
  126. data/test/process_manager/process_test.rb +52 -0
  127. data/test/repository/locking_test.rb +101 -0
  128. data/test/serialization/converter/factory_test.rb +33 -0
  129. data/test/serialization/converter/identity_test.rb +17 -0
  130. data/test/serialization/converter/json_test.rb +31 -0
  131. data/test/serialization/converter/ox_test.rb +40 -0
  132. data/test/serialization/fixtures.rb +17 -0
  133. data/test/serialization/lazy_object_test.rb +32 -0
  134. data/test/serialization/message/metadata_test.rb +19 -0
  135. data/test/serialization/message/serialization_aware_message_test.rb +88 -0
  136. data/test/serialization/message/serialized_message_builder_test.rb +41 -0
  137. data/test/serialization/message/serialized_message_test.rb +140 -0
  138. data/test/serialization/message/serializer_test.rb +50 -0
  139. data/test/serialization/revision_resolver_test.rb +12 -0
  140. data/test/serialization/serialized_object_test.rb +36 -0
  141. data/test/serialization/serialized_type_test.rb +27 -0
  142. data/test/serialization/serializer/marshal_test.rb +22 -0
  143. data/test/serialization/serializer/oj_test.rb +24 -0
  144. data/test/serialization/serializer/ox_test.rb +36 -0
  145. data/test/serialization/serializer_test.rb +20 -0
  146. data/test/test_helper.rb +19 -0
  147. data/test/uow/factory_test.rb +23 -0
  148. data/test/uow/outer_commit_listener_test.rb +50 -0
  149. data/test/uow/provider_test.rb +70 -0
  150. data/test/uow/uow_test.rb +337 -0
  151. data/test/upcasting/chain_test.rb +29 -0
  152. data/test/upcasting/fixtures.rb +66 -0
  153. data/test/wiring/wire_registry_test.rb +60 -0
  154. data/test/wiring/wire_test.rb +51 -0
  155. metadata +263 -0
@@ -0,0 +1,78 @@
1
+ module Synapse
2
+ module Upcasting
3
+ class UpcasterChain
4
+ # @return [ConverterFactory]
5
+ attr_accessor :converter_factory
6
+
7
+ # @return [Array<Upcaster>]
8
+ attr_accessor :upcasters
9
+
10
+ # @param [ConverterFactory] converter_factory
11
+ # @return [undefined]
12
+ def initialize(converter_factory)
13
+ @converter_factory = converter_factory
14
+ @upcasters = Array.new
15
+ end
16
+
17
+ # Pushes the given upcaster onto the end of this upcaster chain
18
+ #
19
+ # @param [Upcaster] upcaster
20
+ # @return [undefined]
21
+ def push(upcaster)
22
+ @upcasters.push upcaster
23
+ end
24
+
25
+ alias << push
26
+
27
+ # @param [SerializedObject] serialized_object
28
+ # @param [UpcastingContext] upcast_context
29
+ # @return [Array<SerializedObject>]
30
+ def upcast(serialized_object, upcast_context)
31
+ serialized_objects = Array.new
32
+ serialized_objects.push serialized_object
33
+
34
+ @upcasters.each do |upcaster|
35
+ serialized_objects = upcast_objects(upcaster, serialized_objects, upcast_context)
36
+ end
37
+
38
+ serialized_objects
39
+ end
40
+
41
+ protected
42
+
43
+ # @param [Upcaster] upcaster
44
+ # @param [SerializedObject] representation
45
+ # @param [Array<SerializedType>] expected_types
46
+ # @param [UpcastingContent] upcast_context
47
+ # @return [Array<SerializedObject>]
48
+ def perform_upcast(upcaster, representation, expected_types, upcast_context)
49
+ upcaster.upcast(representation, expected_types, upcast_context)
50
+ end
51
+
52
+ private
53
+
54
+ # @param [Upcaster] upcaster
55
+ # @param [Array<SerializedObject>] serialized_objects
56
+ # @param [UpcastingContext] upcast_context
57
+ # @return [Array<SerializedObject>]
58
+ def upcast_objects(upcaster, serialized_objects, upcast_context)
59
+ upcast_objects = Array.new
60
+
61
+ serialized_objects.each do |serialized_object|
62
+ serialized_type = serialized_object.type
63
+
64
+ if upcaster.can_upcast? serialized_type
65
+ serialized_object = converter_factory.convert serialized_object, upcaster.expected_content_type
66
+ expected_types = upcaster.upcast_type(serialized_type)
67
+
68
+ upcast_objects.concat(perform_upcast(upcaster, serialized_object, expected_types, upcast_context))
69
+ else
70
+ upcast_objects.push serialized_object
71
+ end
72
+ end
73
+
74
+ upcast_objects
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ module Synapse
2
+ module Upcasting
3
+ # Provides contextual information about an object being upcast; generally this is information
4
+ # from the message containing the object to be upcast
5
+ #
6
+ # @abstract
7
+ class UpcastingContext
8
+ # @abstract
9
+ # @return [String]
10
+ def message_id; end
11
+
12
+ # @abstract
13
+ # @return [Hash]
14
+ def metadata; end
15
+
16
+ # @abstract
17
+ # @return [Time]
18
+ def timestamp; end
19
+
20
+ # @abstract
21
+ # @return [Object]
22
+ def aggregate_id; end
23
+
24
+ # @abstract
25
+ # @return [Integer]
26
+ def sequence_number; end
27
+ end
28
+
29
+ # Upcasting context that provides information from serialized domain event data
30
+ class SerializedDomainEventUpcastingContext < UpcastingContext
31
+ extend Forwardable
32
+
33
+ # @return [Object]
34
+ attr_reader :aggregate_id
35
+
36
+ # @return [LazyObject]
37
+ attr_reader :serialized_metadata
38
+
39
+ # @param [SerializedDomainEventData] event_data
40
+ # @param [Object] aggregate_id
41
+ # @param [Serializer] serializer
42
+ # @return [undefined]
43
+ def initialize(event_data, aggregate_id, serializer)
44
+ @aggregate_id = aggregate_id
45
+ @event_data = event_data
46
+ @serialized_metadata = Serialization::LazyObject.new @event_data.metadata, serializer
47
+ end
48
+
49
+ # @return [Hash]
50
+ def metadata
51
+ @serialized_metadata.deserialized
52
+ end
53
+
54
+ # Delegators for serialized domain event data
55
+ def_delegators :@event_data, :id, :timestamp, :sequence_number
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ module Synapse
2
+ module Upcasting
3
+ class UpcastSerializedDomainEventData < Serialization::SerializedDomainEventData
4
+ extend Forwardable
5
+
6
+ # @param [SerializedDomainEventData] original
7
+ # @param [Object] aggregate_id
8
+ # @param [SerializedObject] upcast_payload
9
+ # @return [undefined]
10
+ def initialize(original, aggregate_id, upcast_payload)
11
+ @original = original
12
+ @aggregate_id = aggregate_id
13
+ @upcast_payload = upcast_payload
14
+ end
15
+
16
+ # @return [SerializedObject]
17
+ def payload
18
+ @upcast_payload
19
+ end
20
+
21
+ # @return [Object]
22
+ def aggregate_id
23
+ @aggregate_id
24
+ end
25
+
26
+ # Delegators for serialized domain event data
27
+ def_delegators :@original, :id, :metadata, :timestamp, :sequence_number
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,57 @@
1
+ module Synapse
2
+ module Upcasting
3
+ # Specialized upcaster mixin for an upcaster that upcasts a serialized object into a single,
4
+ # newer serialized object.
5
+ #
6
+ # This mixin is not suitable if an upcaster needs to upcast a serialized object into multiple
7
+ # newer serialized objects, or when the output representation type is not the same as the
8
+ # expected representation type.
9
+ module SingleUpcaster
10
+ extend ActiveSupport::Concern
11
+ include Upcaster
12
+
13
+ # @param [SerialiedObject] intermediate
14
+ # @param [Array<SerializedType>] expected_types
15
+ # @param [UpcastingContext] upcast_context
16
+ # @return [Array<SerializedObject>]
17
+ def upcast(intermediate, expected_types, upcast_context)
18
+ upcast_content = perform_upcast(intermediate, upcast_context)
19
+ upcast_objects = Array.new
20
+
21
+ unless upcast_content
22
+ return upcast_objects
23
+ end
24
+
25
+ upcast_objects.push Serialization::SerializedObject.new(upcast_content, expected_content_type, expected_types.at(0))
26
+ upcast_objects
27
+ end
28
+
29
+ # @param [SerializedType] serialized_type
30
+ # @return [Array<SerializedType>]
31
+ def upcast_type(serialized_type)
32
+ upcast_type = perform_upcast_type(serialized_type)
33
+ upcast_types = Array.new
34
+
35
+ unless upcast_type
36
+ return upcast_types
37
+ end
38
+
39
+ upcast_types.push upcast_type
40
+ upcast_types
41
+ end
42
+
43
+ protected
44
+
45
+ # @abstract
46
+ # @param [SerializedObject] intermediate
47
+ # @param [UpcastingContext] upcast_context
48
+ # @return [Object] If nil is returned, the serialized object will be dropped
49
+ def perform_upcast(intermediate, upcast_context); end
50
+
51
+ # @abstract
52
+ # @param [SerializedType] serialized_type
53
+ # @return [SerializedType] If nil is returned, the serialized object will be dropped
54
+ def perform_upcast_type(serialized_type); end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,55 @@
1
+ module Synapse
2
+ module Upcasting
3
+ # Represents a mechanism for converting deprecated serialized objects into the current
4
+ # format used by the application. If the serializer itself is not able to cope with the changed
5
+ # formats, an upcaster provides flexibility for more complex structural transformations.
6
+ #
7
+ # Upcasters work on intermediate representations of the object to upcast. In most cases, this
8
+ # representation is an object structure of some kind. The serializer is responsible for
9
+ # converting the intermediate representation form to one that is compatible with the upcaster.
10
+ #
11
+ # For performance reasons, it is advisable to ensure that all upcasters in the same chain use
12
+ # the same intermediate representation type.
13
+ module Upcaster
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ class_attribute :expected_content_type
18
+ end
19
+
20
+ module ClassMethods
21
+ # @param [Class] type
22
+ # @return [undefined]
23
+ def expects_content_type(type)
24
+ self.expected_content_type = type
25
+ end
26
+ end
27
+
28
+ # Returns true if this upcaster is capable of upcasting the given type
29
+ #
30
+ # @abstract
31
+ # @param [SerializedType] serialized_type
32
+ # @return [Boolean]
33
+ def can_upcast?(serialized_type); end
34
+
35
+ # Upcasts a given serialized object to zero or more upcast objects
36
+ #
37
+ # The types of the upcast objects should match the same length and order of the given array
38
+ # of upcast types.
39
+ #
40
+ # @abstract
41
+ # @param [SerialiedObject] intermediate
42
+ # @param [Array<SerializedType>] expected_types
43
+ # @param [UpcastingContext] upcast_context
44
+ # @return [Array<SerializedObject>]
45
+ def upcast(intermediate, expected_types, upcast_context); end
46
+
47
+ # Upcasts a given serialized type to zero or more upcast types
48
+ #
49
+ # @abstract
50
+ # @param [SerializedType] serialized_type
51
+ # @return [Array<SerializedType>]
52
+ def upcast_type(serialized_type); end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module Synapse
2
+ VERSION = '0.1.2'
3
+ end
@@ -0,0 +1,41 @@
1
+ module Synapse
2
+ module Wiring
3
+ # Base mixin that make it easier to wire handlers to their respective types
4
+ # @abstract
5
+ module MessageWiring
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # @return [WireRegistry]
10
+ class_attribute :wire_registry
11
+ end
12
+
13
+ module ClassMethods
14
+ def wire(type, *args, &block)
15
+ options = args.extract_options!
16
+
17
+ unless options[:to]
18
+ unless block
19
+ raise ArgumentError, 'Expected block or option :to'
20
+ end
21
+
22
+ options[:to] = block
23
+ end
24
+
25
+ wire = Wire.new type, options[:to]
26
+
27
+ self.wire_registry.register wire
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ # @param [Message] message
34
+ # @param [Wire] wire
35
+ # @return [Object] Result of the handler invocation
36
+ def invoke_wire(message, wire)
37
+ wire.invoke self, message.payload
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,55 @@
1
+ module Synapse
2
+ module Wiring
3
+ # Represents a mapping between a payload type and a handler method or block
4
+ #
5
+ # Wires are ordered by the depth of the payload type that they handle. Wires that are
6
+ # for a more specific class are preferred over wires for an abstract class.
7
+ class Wire
8
+ # @return [Class] The type of payload that a handler is being wired to
9
+ attr_reader :type
10
+
11
+ # @return [Object] Either a method symbol or block
12
+ attr_reader :handler
13
+
14
+ # @param [Class] type
15
+ # @param [Object] handler Either a method symbol or block
16
+ # @return [undefined]]
17
+ def initialize(type, handler)
18
+ @type = type
19
+ @handler = handler
20
+ end
21
+
22
+ # @param [Object] target
23
+ # @param [Object...] args
24
+ # @return [Object] The result of the handler invocation
25
+ def invoke(target, *args)
26
+ if @handler.is_a? Symbol
27
+ target.send(@handler, *args)
28
+ else
29
+ target.instance_exec(*args, &@handler)
30
+ end
31
+ end
32
+
33
+ # @param [Wire] other
34
+ # @return [Integer]
35
+ def <=>(other)
36
+ (@type <=> other.type) or 0
37
+ end
38
+
39
+ # @param [Wire] other
40
+ # @return [Boolean]
41
+ def ==(other)
42
+ self.class === other and
43
+ @type == other.type
44
+ end
45
+
46
+ alias eql? ==
47
+
48
+ # TODO Is this a good hash function? Probs not
49
+ # @return [Integer]
50
+ def hash
51
+ @type.hash
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,61 @@
1
+ module Synapse
2
+ module Wiring
3
+ class WireRegistry
4
+ # @param [Boolean] duplicates_allowed
5
+ # @return [undefined]
6
+ def initialize(duplicates_allowed)
7
+ @duplicates_allowed = duplicates_allowed
8
+ @wires = Array.new
9
+ end
10
+
11
+ # Yields the type that each wire is registered for
12
+ #
13
+ # @yield [Class]
14
+ # @return [undefined]
15
+ def each_type
16
+ @wires.each do |wire|
17
+ yield wire.type
18
+ end
19
+ end
20
+
21
+ # @raise [DuplicateWireError] If duplicates aren't allowed and another wire exists that
22
+ # wires the exact same type as the given wire
23
+ # @param [Wire] wire
24
+ # @return [undefined]
25
+ def register(wire)
26
+ unless @duplicates_allowed
27
+ if @wires.include? wire
28
+ raise DuplicateWireError
29
+ end
30
+ end
31
+
32
+ @wires.push wire
33
+ @wires.sort!
34
+ end
35
+
36
+ # Retrieves the most specific wire for a given type, if any
37
+ #
38
+ # @param [Class] target_type
39
+ # @return [Wire]
40
+ def wire_for(target_type)
41
+ @wires.find do |wire|
42
+ wire.type >= target_type
43
+ end
44
+ end
45
+
46
+ # Retrieves any wires for a given type, regardless of specificity
47
+ #
48
+ # @param [Class] target_type
49
+ # @return [Array]
50
+ def wires_for(target_type)
51
+ @wires.find_all do |wire|
52
+ wire.type >= target_type
53
+ end
54
+ end
55
+ end
56
+
57
+ # Raised if a wire registry doesn't allow duplicates and an attempt is made to wire the same
58
+ # type to multiple handlers
59
+ class DuplicateWireError < NonTransientError; end
60
+ end
61
+ end