aggro 0.0.1 → 0.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.travis.yml +15 -0
- data/Gemfile +9 -0
- data/README.md +5 -1
- data/Rakefile +10 -0
- data/aggro.gemspec +8 -1
- data/lib/aggro.rb +191 -7
- data/lib/aggro/abstract_store.rb +12 -0
- data/lib/aggro/aggregate.rb +98 -0
- data/lib/aggro/aggregate_ref.rb +68 -6
- data/lib/aggro/attribute_dsl.rb +96 -0
- data/lib/aggro/binding_dsl.rb +45 -0
- data/lib/aggro/block_helper.rb +14 -0
- data/lib/aggro/channel.rb +37 -0
- data/lib/aggro/client.rb +12 -0
- data/lib/aggro/cluster_config.rb +57 -0
- data/lib/aggro/command.rb +16 -0
- data/lib/aggro/concurrent_actor.rb +26 -0
- data/lib/aggro/event_bus.rb +94 -0
- data/lib/aggro/event_dsl.rb +53 -0
- data/lib/aggro/event_proxy.rb +23 -0
- data/lib/aggro/event_serializer.rb +14 -0
- data/lib/aggro/file_store.rb +97 -0
- data/lib/aggro/file_store/reader.rb +21 -0
- data/lib/aggro/file_store/writer.rb +27 -0
- data/lib/aggro/handler/command.rb +60 -0
- data/lib/aggro/handler/create_aggregate.rb +42 -0
- data/lib/aggro/handler/get_events.rb +30 -0
- data/lib/aggro/handler/query.rb +60 -0
- data/lib/aggro/handler/start_saga.rb +56 -0
- data/lib/aggro/local_node.rb +28 -0
- data/lib/aggro/locator.rb +32 -0
- data/lib/aggro/message/ask.rb +16 -0
- data/lib/aggro/message/command.rb +36 -0
- data/lib/aggro/message/create_aggregate.rb +16 -0
- data/lib/aggro/message/endpoint.rb +16 -0
- data/lib/aggro/message/events.rb +24 -0
- data/lib/aggro/message/get_events.rb +16 -0
- data/lib/aggro/message/heartbeat.rb +16 -0
- data/lib/aggro/message/invalid_target.rb +20 -0
- data/lib/aggro/message/ok.rb +20 -0
- data/lib/aggro/message/publisher_endpoint_inquiry.rb +16 -0
- data/lib/aggro/message/query.rb +36 -0
- data/lib/aggro/message/result.rb +16 -0
- data/lib/aggro/message/start_saga.rb +28 -0
- data/lib/aggro/message/unhandled_operation.rb +20 -0
- data/lib/aggro/message/unknown_operation.rb +20 -0
- data/lib/aggro/message_parser.rb +10 -0
- data/lib/aggro/message_router.rb +26 -0
- data/lib/aggro/nanomsg_transport.rb +31 -0
- data/lib/aggro/nanomsg_transport/client.rb +35 -0
- data/lib/aggro/nanomsg_transport/connection.rb +98 -0
- data/lib/aggro/nanomsg_transport/publish.rb +17 -0
- data/lib/aggro/nanomsg_transport/publisher.rb +37 -0
- data/lib/aggro/nanomsg_transport/raw_reply.rb +18 -0
- data/lib/aggro/nanomsg_transport/raw_request.rb +18 -0
- data/lib/aggro/nanomsg_transport/reply.rb +17 -0
- data/lib/aggro/nanomsg_transport/request.rb +17 -0
- data/lib/aggro/nanomsg_transport/server.rb +84 -0
- data/lib/aggro/nanomsg_transport/socket_error.rb +20 -0
- data/lib/aggro/nanomsg_transport/subscribe.rb +27 -0
- data/lib/aggro/nanomsg_transport/subscriber.rb +82 -0
- data/lib/aggro/node.rb +29 -0
- data/lib/aggro/node_list.rb +39 -0
- data/lib/aggro/projection.rb +13 -0
- data/lib/aggro/query.rb +11 -0
- data/lib/aggro/saga.rb +94 -0
- data/lib/aggro/saga_runner.rb +87 -0
- data/lib/aggro/saga_runner/start_saga.rb +12 -0
- data/lib/aggro/saga_status.rb +29 -0
- data/lib/aggro/server.rb +88 -0
- data/lib/aggro/subscriber.rb +48 -0
- data/lib/aggro/subscription.rb +41 -0
- data/lib/aggro/transform/boolean.rb +16 -0
- data/lib/aggro/transform/email.rb +26 -0
- data/lib/aggro/transform/id.rb +34 -0
- data/lib/aggro/transform/integer.rb +22 -0
- data/lib/aggro/transform/money.rb +22 -0
- data/lib/aggro/transform/noop.rb +16 -0
- data/lib/aggro/transform/string.rb +16 -0
- data/lib/aggro/transform/time_interval.rb +24 -0
- data/lib/aggro/version.rb +1 -1
- data/spec/lib/aggro/abstract_store_spec.rb +15 -0
- data/spec/lib/aggro/aggregate_ref_spec.rb +63 -12
- data/spec/lib/aggro/aggregate_spec.rb +207 -0
- data/spec/lib/aggro/channel_spec.rb +87 -0
- data/spec/lib/aggro/client_spec.rb +26 -0
- data/spec/lib/aggro/cluster_config_spec.rb +33 -0
- data/spec/lib/aggro/command_spec.rb +52 -0
- data/spec/lib/aggro/concurrent_actor_spec.rb +44 -0
- data/spec/lib/aggro/event_bus_spec.rb +20 -0
- data/spec/lib/aggro/event_serializer_spec.rb +28 -0
- data/spec/lib/aggro/file_store/reader_spec.rb +32 -0
- data/spec/lib/aggro/file_store/writer_spec.rb +67 -0
- data/spec/lib/aggro/file_store_spec.rb +51 -0
- data/spec/lib/aggro/handler/command_spec.rb +78 -0
- data/spec/lib/aggro/handler/create_aggregate_spec.rb +64 -0
- data/spec/lib/aggro/handler/get_events_handler_spec.rb +45 -0
- data/spec/lib/aggro/handler/query_spec.rb +78 -0
- data/spec/lib/aggro/handler/start_saga_spec.rb +64 -0
- data/spec/lib/aggro/local_node_spec.rb +52 -0
- data/spec/lib/aggro/locator_spec.rb +61 -0
- data/spec/lib/aggro/message/ask_spec.rb +23 -0
- data/spec/lib/aggro/message/command_spec.rb +50 -0
- data/spec/lib/aggro/message/create_aggregate_spec.rb +28 -0
- data/spec/lib/aggro/message/endpoint_spec.rb +23 -0
- data/spec/lib/aggro/message/events_spec.rb +37 -0
- data/spec/lib/aggro/message/get_events_spec.rb +33 -0
- data/spec/lib/aggro/message/heartbeat_spec.rb +23 -0
- data/spec/lib/aggro/message/invalid_target_spec.rb +28 -0
- data/spec/lib/aggro/message/ok_spec.rb +27 -0
- data/spec/lib/aggro/message/publisher_endpoint_inquiry_spec.rb +23 -0
- data/spec/lib/aggro/message/query_spec.rb +50 -0
- data/spec/lib/aggro/message/start_saga_spec.rb +37 -0
- data/spec/lib/aggro/message/unhandled_operation_spec.rb +28 -0
- data/spec/lib/aggro/message/unknown_operation_spec.rb +28 -0
- data/spec/lib/aggro/message_parser_spec.rb +16 -0
- data/spec/lib/aggro/message_router_spec.rb +35 -0
- data/spec/lib/aggro/nanomsg_transport/socket_error_spec.rb +21 -0
- data/spec/lib/aggro/nanomsg_transport_spec.rb +37 -0
- data/spec/lib/aggro/node_list_spec.rb +38 -0
- data/spec/lib/aggro/node_spec.rb +44 -0
- data/spec/lib/aggro/projection_spec.rb +22 -0
- data/spec/lib/aggro/query_spec.rb +47 -0
- data/spec/lib/aggro/saga_runner_spec.rb +84 -0
- data/spec/lib/aggro/saga_spec.rb +126 -0
- data/spec/lib/aggro/saga_status_spec.rb +56 -0
- data/spec/lib/aggro/server_spec.rb +118 -0
- data/spec/lib/aggro/subscriber_spec.rb +59 -0
- data/spec/lib/aggro/subscription_spec.rb +50 -0
- data/spec/lib/aggro/transform/boolean_spec.rb +23 -0
- data/spec/lib/aggro/transform/email_spec.rb +13 -0
- data/spec/lib/aggro/transform/id_spec.rb +70 -0
- data/spec/lib/aggro/transform/integer_spec.rb +30 -0
- data/spec/lib/aggro/transform/money_spec.rb +34 -0
- data/spec/lib/aggro/transform/string_spec.rb +15 -0
- data/spec/lib/aggro/transform/time_interval_spec.rb +29 -0
- data/spec/lib/aggro_spec.rb +63 -19
- data/spec/spec_helper.rb +21 -2
- metadata +283 -3
@@ -0,0 +1,32 @@
|
|
1
|
+
module Aggro
|
2
|
+
# Public: Locates the nodes responsible for a given entity ID.
|
3
|
+
class Locator
|
4
|
+
def initialize(id)
|
5
|
+
@id = id
|
6
|
+
end
|
7
|
+
|
8
|
+
def local?
|
9
|
+
primary_node.is_a? LocalNode
|
10
|
+
end
|
11
|
+
|
12
|
+
def nodes
|
13
|
+
current_node_list_state = Aggro.node_list.state
|
14
|
+
|
15
|
+
if @last_node_list_state == current_node_list_state
|
16
|
+
@nodes ||= Aggro.node_list.nodes_for(@id)
|
17
|
+
else
|
18
|
+
@last_node_list_state = current_node_list_state
|
19
|
+
|
20
|
+
@nodes = Aggro.node_list.nodes_for(@id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def primary_node
|
25
|
+
nodes.first
|
26
|
+
end
|
27
|
+
|
28
|
+
def secondary_nodes
|
29
|
+
nodes[1..-1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Command message.
|
4
|
+
class Command < Struct.new(:sender, :commandee_id, :details)
|
5
|
+
TYPE_CODE = '03'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], string[38..73], parse_details(string[74..-1])
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_details(details)
|
12
|
+
Marshal.load details
|
13
|
+
end
|
14
|
+
|
15
|
+
def args
|
16
|
+
details[:args]
|
17
|
+
end
|
18
|
+
|
19
|
+
def command_class
|
20
|
+
ActiveSupport::Inflector.safe_constantize name
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
details[:name]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_command
|
28
|
+
command_class.new args if command_class
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"#{TYPE_CODE}#{sender}#{commandee_id}#{Marshal.dump details}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Create aggregate message.
|
4
|
+
class CreateAggregate < Struct.new(:sender, :id, :type)
|
5
|
+
TYPE_CODE = '08'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], string[38..73], string[74..-1]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{sender}#{id}#{type}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Endpoint message.
|
4
|
+
class Endpoint < Struct.new(:endpoint)
|
5
|
+
TYPE_CODE = '12'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..-1]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{endpoint}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Get events message.
|
4
|
+
class Events < Struct.new(:id, :events)
|
5
|
+
TYPE_CODE = '10'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], parse_events(string[38..-1])
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_events(string)
|
12
|
+
ObjectStream.new(StringIO.new(string), type: 'marshal')
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize_events
|
16
|
+
events.map { |event| EventSerializer.serialize event }.join
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{TYPE_CODE}#{id}#{serialize_events}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Get events message.
|
4
|
+
class GetEvents < Struct.new(:sender, :id, :from_version)
|
5
|
+
TYPE_CODE = '09'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], string[38..73], string[74..-1].to_i
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{sender}#{id}#{from_version || 0}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Heartbeat message.
|
4
|
+
class Heartbeat < Struct.new(:sender)
|
5
|
+
TYPE_CODE = '02'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{sender}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Invalid target message.
|
4
|
+
class InvalidTarget
|
5
|
+
TYPE_CODE = '06'.freeze
|
6
|
+
|
7
|
+
def self.parse(_string)
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new
|
12
|
+
@singleton ||= super
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{TYPE_CODE}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: OK message.
|
4
|
+
class OK
|
5
|
+
TYPE_CODE = '01'.freeze
|
6
|
+
|
7
|
+
def self.parse(_string)
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new
|
12
|
+
@singleton ||= super
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{TYPE_CODE}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Publisher endpoint inquiry message.
|
4
|
+
class PublisherEndpointInquiry < Struct.new(:sender)
|
5
|
+
TYPE_CODE = '11'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{sender}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Query message.
|
4
|
+
class Query < Struct.new(:sender, :queryable_id, :details)
|
5
|
+
TYPE_CODE = '15'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], string[38..73], parse_details(string[74..-1])
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_details(details)
|
12
|
+
Marshal.load details
|
13
|
+
end
|
14
|
+
|
15
|
+
def args
|
16
|
+
details[:args]
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
details[:name]
|
21
|
+
end
|
22
|
+
|
23
|
+
def query_class
|
24
|
+
ActiveSupport::Inflector.safe_constantize name
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_query
|
28
|
+
query_class.new args if query_class
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"#{TYPE_CODE}#{sender}#{queryable_id}#{Marshal.dump details}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Result message.
|
4
|
+
class Result < Struct.new(:result)
|
5
|
+
TYPE_CODE = '14'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new Marshal.load(string[2..-1])
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{TYPE_CODE}#{Marshal.dump result}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Start saga message.
|
4
|
+
class StartSaga < Struct.new(:sender, :id, :details)
|
5
|
+
TYPE_CODE = '13'.freeze
|
6
|
+
|
7
|
+
def self.parse(string)
|
8
|
+
new string[2..37], string[38..73], parse_details(string[74..-1])
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_details(details)
|
12
|
+
Marshal.load details
|
13
|
+
end
|
14
|
+
|
15
|
+
def args
|
16
|
+
details[:args]
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
details[:name]
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{TYPE_CODE}#{sender}#{id}#{Marshal.dump details}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Unhandled operation message.
|
4
|
+
class UnhandledOperation
|
5
|
+
TYPE_CODE = '07'.freeze
|
6
|
+
|
7
|
+
def self.parse(_string)
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new
|
12
|
+
@singleton ||= super
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{TYPE_CODE}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Aggro
|
2
|
+
module Message
|
3
|
+
# Public: Unknown operation message.
|
4
|
+
class UnknownOperation
|
5
|
+
TYPE_CODE = '04'.freeze
|
6
|
+
|
7
|
+
def self.parse(_string)
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.new
|
12
|
+
@singleton ||= super
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{TYPE_CODE}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Aggro
|
2
|
+
# Public: Routes inter-node messages to attached message handlers.
|
3
|
+
class MessageRouter
|
4
|
+
def initialize
|
5
|
+
@handlers = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def attach_handler(message_class, callable = nil, &block)
|
9
|
+
if callable
|
10
|
+
@handlers[message_class] = callable
|
11
|
+
elsif block_given?
|
12
|
+
@handlers[message_class] = block
|
13
|
+
else
|
14
|
+
fail ArgumentError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def handles?(message_class)
|
19
|
+
@handlers[message_class]
|
20
|
+
end
|
21
|
+
|
22
|
+
def route(message)
|
23
|
+
@handlers[message.class].call message if handles?(message.class)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'aggro/nanomsg_transport/client'
|
2
|
+
require 'aggro/nanomsg_transport/publisher'
|
3
|
+
require 'aggro/nanomsg_transport/server'
|
4
|
+
require 'aggro/nanomsg_transport/subscriber'
|
5
|
+
|
6
|
+
module Aggro
|
7
|
+
# Public: Transport layer over nanomsg sockets.
|
8
|
+
module NanomsgTransport
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def client(endpoint)
|
12
|
+
Client.new endpoint
|
13
|
+
end
|
14
|
+
|
15
|
+
def publisher(endpoint)
|
16
|
+
Publisher.new endpoint
|
17
|
+
end
|
18
|
+
|
19
|
+
def server(endpoint, callable = nil, &block)
|
20
|
+
Server.new endpoint, callable, &block
|
21
|
+
end
|
22
|
+
|
23
|
+
def subscriber(endpoint, callable = nil, &block)
|
24
|
+
Subscriber.new endpoint, callable, &block
|
25
|
+
end
|
26
|
+
|
27
|
+
def teardown
|
28
|
+
NNCore::LibNanomsg.nn_term
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|