synapse-core 0.2.0 → 0.4.0
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.rb +3 -0
- data/lib/synapse/command/simple_command_bus.rb +2 -2
- data/lib/synapse/common/concurrency/identifier_lock.rb +71 -0
- data/lib/synapse/common/concurrency/public_lock.rb +96 -0
- data/lib/synapse/event_bus/simple_event_bus.rb +1 -1
- data/lib/synapse/event_bus/wiring.rb +0 -4
- data/lib/synapse/event_sourcing/member.rb +0 -4
- data/lib/synapse/event_sourcing/snapshot/count_trigger.rb +2 -2
- data/lib/synapse/event_store.rb +1 -9
- data/lib/synapse/partitioning.rb +0 -2
- data/lib/synapse/process_manager.rb +12 -0
- data/lib/synapse/process_manager/lock_manager.rb +22 -0
- data/lib/synapse/process_manager/pessimistic_lock_manager.rb +23 -0
- data/lib/synapse/process_manager/process.rb +2 -0
- data/lib/synapse/process_manager/process_factory.rb +52 -0
- data/lib/synapse/process_manager/process_manager.rb +170 -0
- data/lib/synapse/process_manager/process_repository.rb +53 -0
- data/lib/synapse/process_manager/repository/in_memory.rb +63 -0
- data/lib/synapse/process_manager/resource_injector.rb +12 -0
- data/lib/synapse/process_manager/simple_process_manager.rb +48 -0
- data/lib/synapse/process_manager/wiring/process.rb +27 -0
- data/lib/synapse/process_manager/wiring/process_manager.rb +72 -0
- data/lib/synapse/repository.rb +1 -0
- data/lib/synapse/repository/locking.rb +1 -1
- data/lib/synapse/repository/optimistic_lock_manager.rb +128 -0
- data/lib/synapse/repository/pessimistic_lock_manager.rb +4 -37
- data/lib/synapse/serialization.rb +1 -1
- data/lib/synapse/serialization/{converter/factory.rb → converter_factory.rb} +0 -0
- data/lib/synapse/serialization/serializer.rb +5 -3
- data/lib/synapse/uow/listener_collection.rb +59 -1
- data/lib/synapse/version.rb +1 -1
- data/lib/synapse/wiring/message_wiring.rb +7 -3
- data/lib/synapse/wiring/wire.rb +7 -2
- data/test/common/concurrency/identifier_lock_test.rb +36 -0
- data/test/common/concurrency/public_lock_test.rb +83 -0
- data/test/partitioning/packing/json_test.rb +2 -1
- data/test/process_manager/in_memory_test.rb +57 -0
- data/test/process_manager/process_factory_test.rb +31 -0
- data/test/process_manager/simple_process_manager_test.rb +130 -0
- data/test/process_manager/wiring/fixtures.rb +42 -0
- data/test/process_manager/wiring/process_manager_test.rb +73 -0
- data/test/process_manager/wiring/process_test.rb +35 -0
- data/test/repository/optimistic_test.rb +41 -0
- data/test/repository/pessimistic_test.rb +20 -0
- data/test/serialization/converter/chain_test.rb +31 -0
- data/test/serialization/lazy_object_test.rb +1 -1
- data/test/serialization/message/serialization_aware_message_test.rb +4 -2
- data/test/serialization/message/serialized_message_builder_test.rb +1 -1
- data/test/serialization/message/serialized_message_test.rb +3 -2
- data/test/serialization/serializer/marshal_test.rb +1 -1
- data/test/serialization/serializer/oj_test.rb +1 -1
- data/test/serialization/serializer/ox_test.rb +1 -1
- data/test/serialization/serializer_test.rb +1 -1
- data/test/test_ext.rb +5 -2
- data/test/wiring/wire_registry_test.rb +10 -10
- data/test/wiring/wire_test.rb +5 -5
- metadata +29 -16
- data/lib/synapse/event_store/mongo.rb +0 -8
- data/lib/synapse/event_store/mongo/cursor_event_stream.rb +0 -63
- data/lib/synapse/event_store/mongo/event_store.rb +0 -86
- data/lib/synapse/event_store/mongo/per_commit_strategy.rb +0 -253
- data/lib/synapse/event_store/mongo/per_event_strategy.rb +0 -143
- data/lib/synapse/event_store/mongo/storage_strategy.rb +0 -113
- data/lib/synapse/event_store/mongo/template.rb +0 -73
- data/lib/synapse/partitioning/amqp.rb +0 -3
- data/lib/synapse/partitioning/amqp/amqp_queue_reader.rb +0 -50
- data/lib/synapse/partitioning/amqp/amqp_queue_writer.rb +0 -31
- data/lib/synapse/partitioning/amqp/key_resolver.rb +0 -26
- data/lib/synapse/serialization/converter/bson.rb +0 -28
@@ -1,113 +0,0 @@
|
|
1
|
-
module Synapse
|
2
|
-
module EventStore
|
3
|
-
module Mongo
|
4
|
-
# Represents a mechanism used to structure how events are stored in the database
|
5
|
-
# @abstract
|
6
|
-
class StorageStrategy
|
7
|
-
# @param [MongoTemplate] template
|
8
|
-
# @param [Serializer] serializer
|
9
|
-
# @param [UpcasterChain] upcaster_chain
|
10
|
-
# @return [undefined]
|
11
|
-
def initialize(template, serializer, upcaster_chain)
|
12
|
-
@template = template
|
13
|
-
@serializer = Serialization::MessageSerializer.new serializer
|
14
|
-
@upcaster_chain = upcaster_chain
|
15
|
-
end
|
16
|
-
|
17
|
-
# Creates documents that will represent the events being committed to the event store
|
18
|
-
#
|
19
|
-
# @abstract
|
20
|
-
# @param [String] type_identifier Type identifier for the aggregate
|
21
|
-
# @param [Array] events Domain events to be committed
|
22
|
-
# @return [Array]
|
23
|
-
def create_documents(type_identifier, events); end
|
24
|
-
|
25
|
-
# Extracts individual event messages from the given document
|
26
|
-
#
|
27
|
-
# The given aggregate identifier is passed so that event messages can have the actual
|
28
|
-
# identifier object instead of the serialized aggregate identifier.
|
29
|
-
#
|
30
|
-
# @abstract
|
31
|
-
# @param [Hash] document
|
32
|
-
# @param [Object] aggregate_id
|
33
|
-
# @return [Array]
|
34
|
-
def extract_events(document, aggregate_id); end
|
35
|
-
|
36
|
-
# Aliases of the Mongo constants for ascending and descending
|
37
|
-
ASCENDING = ::Mongo::ASCENDING
|
38
|
-
DESCENDING = ::Mongo::DESCENDING
|
39
|
-
|
40
|
-
# Provides a cursor for accessing all events for an aggregate with the given identifier
|
41
|
-
# and type identifier, with a sequence number equal to or greater than the given first
|
42
|
-
# sequence number
|
43
|
-
#
|
44
|
-
# The returned documents should be ordered chronologically, typically by using the
|
45
|
-
# sequence number.
|
46
|
-
#
|
47
|
-
# @param [String] type_identifier
|
48
|
-
# @param [Object] aggregate_id
|
49
|
-
# @param [Integer] first_sequence_number
|
50
|
-
# @return [Mongo::Cursor]
|
51
|
-
def fetch_events(type_identifier, aggregate_id, first_sequence_number)
|
52
|
-
filter = {
|
53
|
-
aggregate_id: aggregate_id,
|
54
|
-
aggregate_type: type_identifier,
|
55
|
-
sequence_number: {
|
56
|
-
'$gte' => first_sequence_number
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
sort = {
|
61
|
-
sequence_number: ASCENDING
|
62
|
-
}
|
63
|
-
|
64
|
-
@template.event_collection.find(filter).sort(sort)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Finds the document containing the most recent snapshot event for an aggregate with the
|
68
|
-
# given identifier and type identifier
|
69
|
-
#
|
70
|
-
# @param [String] type_identifier
|
71
|
-
# @param [Object] aggregate_id
|
72
|
-
# @return [Mongo::Cursor]
|
73
|
-
def fetch_last_snapshot(type_identifier, aggregate_id)
|
74
|
-
filter = {
|
75
|
-
aggregate_id: aggregate_id,
|
76
|
-
aggregate_type: type_identifier
|
77
|
-
}
|
78
|
-
|
79
|
-
sort = {
|
80
|
-
sequence_number: DESCENDING
|
81
|
-
}
|
82
|
-
|
83
|
-
@template.snapshot_collection.find(filter).sort(sort).limit(1)
|
84
|
-
end
|
85
|
-
|
86
|
-
# Ensures that the correct indexes are in place
|
87
|
-
# @return [undefined]
|
88
|
-
def ensure_indexes
|
89
|
-
options = {
|
90
|
-
name: 'unique_aggregate_index',
|
91
|
-
unique: true
|
92
|
-
}
|
93
|
-
|
94
|
-
spec = {
|
95
|
-
aggregate_id: ASCENDING,
|
96
|
-
aggregate_type: ASCENDING,
|
97
|
-
sequence_number: ASCENDING
|
98
|
-
}
|
99
|
-
|
100
|
-
@template.event_collection.ensure_index spec, options
|
101
|
-
|
102
|
-
spec = {
|
103
|
-
aggregate_id: ASCENDING,
|
104
|
-
aggregate_type: ASCENDING,
|
105
|
-
sequence_number: DESCENDING
|
106
|
-
}
|
107
|
-
|
108
|
-
@template.snapshot_collection.ensure_index spec, options
|
109
|
-
end
|
110
|
-
end # StorageStrategy
|
111
|
-
end # Mongo
|
112
|
-
end # EventStore
|
113
|
-
end # Synapse
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module Synapse
|
2
|
-
module EventStore
|
3
|
-
module Mongo
|
4
|
-
# Represents a mechanism for accessing collections required by the Mongo event store
|
5
|
-
# @abstract
|
6
|
-
class MongoTemplate
|
7
|
-
# Returns a reference to the collection containing domain events
|
8
|
-
#
|
9
|
-
# @abstract
|
10
|
-
# @return [Mongo::Collection]
|
11
|
-
def event_collection; end
|
12
|
-
|
13
|
-
# Returns a reference to the collection containing snapshot events
|
14
|
-
#
|
15
|
-
# @abstract
|
16
|
-
# @return [Mongo::Collection]
|
17
|
-
def snapshot_collection; end
|
18
|
-
end
|
19
|
-
|
20
|
-
class DefaultMongoTemplate
|
21
|
-
# @return [String] Name of the database to use
|
22
|
-
attr_accessor :database_name
|
23
|
-
|
24
|
-
# @return [String] Username to authenticate with (optional)
|
25
|
-
attr_accessor :username
|
26
|
-
|
27
|
-
# @return [String] Password to authenticate with (optional)
|
28
|
-
attr_accessor :password
|
29
|
-
|
30
|
-
# @return [String] Name of the collection containing domain events
|
31
|
-
attr_accessor :event_collection
|
32
|
-
|
33
|
-
# @return [String] Name of the collection containing snapshot events
|
34
|
-
attr_accessor :snapshot_collection
|
35
|
-
|
36
|
-
# @param [Mongo::MongoClient] client
|
37
|
-
# @return [undefined]
|
38
|
-
def initialize(client)
|
39
|
-
@client = client
|
40
|
-
|
41
|
-
@database_name = 'synapse'
|
42
|
-
@event_collection_name = 'domain_events'
|
43
|
-
@snapshot_collection_name = 'snapshot_events'
|
44
|
-
end
|
45
|
-
|
46
|
-
# @return [Mongo::Collection]
|
47
|
-
def event_collection
|
48
|
-
database.collection @event_collection_name
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [Mongo::Collection]
|
52
|
-
def snapshot_collection
|
53
|
-
database.collection @snapshot_collection_name
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
# @return [Mongo::DB]
|
59
|
-
def database
|
60
|
-
unless @database
|
61
|
-
@database = @client.db @database_name
|
62
|
-
|
63
|
-
if @username and @password
|
64
|
-
@database.authenticate @username, @password
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
@database
|
69
|
-
end
|
70
|
-
end # DefaultMongoTemplate
|
71
|
-
end # Mongo
|
72
|
-
end # EventStore
|
73
|
-
end # Synapse
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Synapse
|
2
|
-
module Partitioning
|
3
|
-
module AMQP
|
4
|
-
# Implementation of a queue reader that subscribes to an AMQP queue
|
5
|
-
class AMQPQueueReader < QueueReader
|
6
|
-
# The behavior when a message is not acknowledged by a message handler
|
7
|
-
#
|
8
|
-
# When a message is explicitly rejected, this usually indicates that there was an
|
9
|
-
# error while processing the message. When the message is rejected, it can either be
|
10
|
-
# put back on the queue so that it can be retried later, or it can be routed as a dead
|
11
|
-
# letter if using RabbitMQ.
|
12
|
-
#
|
13
|
-
# @see http://www.rabbitmq.com/dlx.html
|
14
|
-
# @return [Boolean] Default value is true
|
15
|
-
attr_accessor :requeue_on_nack
|
16
|
-
|
17
|
-
# @param [AMQP::Queue] queue
|
18
|
-
# @param [AMQP::Channel] channel
|
19
|
-
# @param [MessageUnpacker] unpacker
|
20
|
-
# @return [undefined]
|
21
|
-
def initialize(queue, channel, unpacker)
|
22
|
-
@queue = queue
|
23
|
-
@channel = channel
|
24
|
-
@requeue_on_nack = true
|
25
|
-
end
|
26
|
-
|
27
|
-
# @yield [MessageReceipt] Receipt of the message taken off the queue
|
28
|
-
# @return [undefined]
|
29
|
-
def subscribe(&handler)
|
30
|
-
@queue.subscribe do |headers, packed|
|
31
|
-
receipt = MessageReceipt.new headers.delivery_tag, packed, @queue.name
|
32
|
-
handler.call receipt
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# @param [MessageReceipt] receipt
|
37
|
-
# @return [undefined]
|
38
|
-
def ack_message(receipt)
|
39
|
-
@channel.acknowledge receipt.tag
|
40
|
-
end
|
41
|
-
|
42
|
-
# @param [MessageReceipt] receipt
|
43
|
-
# @return [undefined]
|
44
|
-
def nack_message(receipt)
|
45
|
-
@channel.reject receipt.tag, @requeue_on_nack
|
46
|
-
end
|
47
|
-
end # AMQPQueueReader
|
48
|
-
end # AMQP
|
49
|
-
end # Partitioning
|
50
|
-
end # Synapse
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Synapse
|
2
|
-
module Partitioning
|
3
|
-
module AMQP
|
4
|
-
# Implementation of a queue writer that publishes packed messages to an AMQP exchange
|
5
|
-
class AMQPQueueWriter < QueueWriter
|
6
|
-
# @return [Hash] Additional options that will be used when publishing messages
|
7
|
-
attr_accessor :publish_options
|
8
|
-
|
9
|
-
# @param [AMQP::Exchange] exchange
|
10
|
-
# @param [RoutingKeyResolver] key_resolver
|
11
|
-
# @return [undefined]
|
12
|
-
def initialize(exchange, key_resolver)
|
13
|
-
@exchange = exchange
|
14
|
-
@key_resolver = key_resolver
|
15
|
-
@publish_options = Hash.new
|
16
|
-
end
|
17
|
-
|
18
|
-
# @param [Object] packed
|
19
|
-
# @param [Message] unpacked
|
20
|
-
# @return [undefined]
|
21
|
-
def put_message(packed, unpacked)
|
22
|
-
publish_options = {
|
23
|
-
routing_key: @key_resolver.resolve_key(unpacked)
|
24
|
-
}
|
25
|
-
|
26
|
-
@exchange.publish(packed, @publish_options.merge(publish_options))
|
27
|
-
end
|
28
|
-
end # AMQPQueueWriter
|
29
|
-
end # AMQP
|
30
|
-
end # Partitioning
|
31
|
-
end # Synapse
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Synapse
|
2
|
-
module Partitioning
|
3
|
-
module AMQP
|
4
|
-
# Represents a mechanism for determining the routing key to use when publishing a message
|
5
|
-
class RoutingKeyResolver
|
6
|
-
# Returns the routing key to use when publishing the given message
|
7
|
-
#
|
8
|
-
# @param [Message] message
|
9
|
-
# @return [String]
|
10
|
-
def resolve_key(message); end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Implementation of a routing key resolver that uses the message payload's module name
|
14
|
-
class ModuleRoutingKeyResolver
|
15
|
-
# @param [Message] message
|
16
|
-
# @return [String]
|
17
|
-
def resolve_key(message)
|
18
|
-
type = message.payload_type.to_s
|
19
|
-
type.deconstantize.underscore.tap do |key|
|
20
|
-
key.tr! '/', '.'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end # AMQP
|
25
|
-
end # Partitioning
|
26
|
-
end # Synapse
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'bson'
|
2
|
-
|
3
|
-
module Synapse
|
4
|
-
module Serialization
|
5
|
-
# Converter that converts an ordered hash from BSON into a regular Ruby hash
|
6
|
-
class OrderedHashToHashConverter
|
7
|
-
include Converter
|
8
|
-
|
9
|
-
converts BSON::OrderedHash, Hash
|
10
|
-
|
11
|
-
# @param [Object] original
|
12
|
-
# @return [Object]
|
13
|
-
def convert_content(original)
|
14
|
-
converted = Hash.new
|
15
|
-
|
16
|
-
original.each do |key, value|
|
17
|
-
if value.is_a? BSON::OrderedHash
|
18
|
-
value = convert_content value
|
19
|
-
end
|
20
|
-
|
21
|
-
converted[key] = value
|
22
|
-
end
|
23
|
-
|
24
|
-
converted
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|