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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0a86dcceeca3a9a1fd14a21861d052541ad178c
|
4
|
+
data.tar.gz: e9bd46d0f4ea83a97e355df1b8ddc4dd9ddc2022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff83f579f3a4aae8abc6fda0b3f4f428b8b74266b11532c7ec4073d5299dde185f12c478a5a90b89c920befa29bd5e65d1d801fba30b5abd367ca4eb3d930fa7
|
7
|
+
data.tar.gz: f907f007f9cdb1b2a4fe7adb529cf2f37ee913a921c27f6337c7bfd2c599dcda4c122d08b883bda8197ac14065087f372fc696a79f4bc624515d61f6c80a92cc
|
data/.rubocop.yml
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2.0
|
4
|
+
- jruby-19mode
|
5
|
+
- ruby-head
|
6
|
+
- jruby-head
|
7
|
+
matrix:
|
8
|
+
allow_failures:
|
9
|
+
- rvm: jruby-19mode
|
10
|
+
- rvm: jruby-head
|
11
|
+
- rvm: ruby-head
|
12
|
+
script: bundle exec rspec
|
13
|
+
before_install:
|
14
|
+
- git clone git://github.com/nanomsg/nanomsg.git
|
15
|
+
- cd nanomsg && ./autogen.sh && ./configure && sudo make install && sudo ldconfig && cd ${TRAVIS_BUILD_DIR}
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Aggro
|
2
2
|
|
3
|
-
|
3
|
+
[](https://travis-ci.org/SebastianEdwards/aggro)
|
4
|
+
[](https://codeclimate.com/github/SebastianEdwards/aggro)
|
5
|
+
[](https://coveralls.io/r/SebastianEdwards/aggro)
|
6
|
+
|
7
|
+
Distributed in-memory event-store.
|
4
8
|
|
5
9
|
## Installation
|
6
10
|
|
data/Rakefile
CHANGED
data/aggro.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Aggro::VERSION
|
9
9
|
spec.authors = ['Sebastian Edwards']
|
10
10
|
spec.email = ['me@sebastianedwards.co.nz']
|
11
|
-
spec.summary = 'Distributed in-memory
|
11
|
+
spec.summary = 'Distributed in-memory event-store.'
|
12
12
|
spec.description = ''
|
13
13
|
spec.homepage = ''
|
14
14
|
spec.license = 'MIT'
|
@@ -24,5 +24,12 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'guard-rspec'
|
25
25
|
spec.add_development_dependency 'rubocop'
|
26
26
|
|
27
|
+
spec.add_runtime_dependency 'activemodel'
|
28
|
+
spec.add_runtime_dependency 'activesupport'
|
29
|
+
spec.add_runtime_dependency 'concurrent-ruby'
|
27
30
|
spec.add_runtime_dependency 'consistent-hashing'
|
31
|
+
spec.add_runtime_dependency 'invokr'
|
32
|
+
spec.add_runtime_dependency 'nio4r'
|
33
|
+
spec.add_runtime_dependency 'nn-core'
|
34
|
+
spec.add_runtime_dependency 'object-stream'
|
28
35
|
end
|
data/lib/aggro.rb
CHANGED
@@ -1,22 +1,206 @@
|
|
1
1
|
require 'aggro/version'
|
2
2
|
|
3
|
+
require 'active_model'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
require 'concurrent'
|
3
6
|
require 'consistent_hashing'
|
7
|
+
require 'invokr'
|
8
|
+
require 'fileutils'
|
9
|
+
require 'msgpack'
|
10
|
+
require 'object-stream'
|
11
|
+
require 'yaml'
|
4
12
|
|
13
|
+
# Private: Define methods to protect handlers from code reloading.
|
14
|
+
module Aggro
|
15
|
+
module_function
|
16
|
+
|
17
|
+
def class_attributes
|
18
|
+
@class_attributes ||= Hash.new { |hash, key| hash[key] = {} }
|
19
|
+
end
|
20
|
+
|
21
|
+
def command_handlers
|
22
|
+
@command_handlers ||= Hash.new { |hash, key| hash[key] = {} }
|
23
|
+
end
|
24
|
+
|
25
|
+
def query_handlers
|
26
|
+
@query_handlers ||= Hash.new { |hash, key| hash[key] = {} }
|
27
|
+
end
|
28
|
+
|
29
|
+
def step_handlers
|
30
|
+
@step_handlers ||= Hash.new { |hash, key| hash[key] = {} }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'aggro/abstract_store'
|
35
|
+
require 'aggro/attribute_dsl'
|
36
|
+
require 'aggro/event_dsl'
|
37
|
+
|
38
|
+
require 'aggro/message/ask'
|
39
|
+
require 'aggro/message/command'
|
40
|
+
require 'aggro/message/create_aggregate'
|
41
|
+
require 'aggro/message/endpoint'
|
42
|
+
require 'aggro/message/events'
|
43
|
+
require 'aggro/message/get_events'
|
44
|
+
require 'aggro/message/heartbeat'
|
45
|
+
require 'aggro/message/invalid_target'
|
46
|
+
require 'aggro/message/ok'
|
47
|
+
require 'aggro/message/publisher_endpoint_inquiry'
|
48
|
+
require 'aggro/message/query'
|
49
|
+
require 'aggro/message/result'
|
50
|
+
require 'aggro/message/start_saga'
|
51
|
+
require 'aggro/message/unhandled_operation'
|
52
|
+
require 'aggro/message/unknown_operation'
|
53
|
+
|
54
|
+
require 'aggro/handler/command'
|
55
|
+
require 'aggro/handler/create_aggregate'
|
56
|
+
require 'aggro/handler/get_events'
|
57
|
+
require 'aggro/handler/query'
|
58
|
+
require 'aggro/handler/start_saga'
|
59
|
+
|
60
|
+
require 'aggro/transform/boolean'
|
61
|
+
require 'aggro/transform/email'
|
62
|
+
require 'aggro/transform/id'
|
63
|
+
require 'aggro/transform/integer'
|
64
|
+
require 'aggro/transform/money'
|
65
|
+
require 'aggro/transform/noop'
|
66
|
+
require 'aggro/transform/string'
|
67
|
+
require 'aggro/transform/time_interval'
|
68
|
+
|
69
|
+
require 'aggro/aggregate'
|
5
70
|
require 'aggro/aggregate_ref'
|
71
|
+
require 'aggro/binding_dsl'
|
72
|
+
require 'aggro/block_helper'
|
73
|
+
require 'aggro/channel'
|
74
|
+
require 'aggro/client'
|
75
|
+
require 'aggro/cluster_config'
|
76
|
+
require 'aggro/command'
|
77
|
+
require 'aggro/concurrent_actor'
|
78
|
+
require 'aggro/event_bus'
|
79
|
+
require 'aggro/event_proxy'
|
80
|
+
require 'aggro/event_serializer'
|
81
|
+
require 'aggro/file_store'
|
82
|
+
require 'aggro/local_node'
|
83
|
+
require 'aggro/locator'
|
84
|
+
require 'aggro/message_parser'
|
85
|
+
require 'aggro/message_router'
|
86
|
+
require 'aggro/nanomsg_transport'
|
87
|
+
require 'aggro/node'
|
88
|
+
require 'aggro/node_list'
|
89
|
+
require 'aggro/projection'
|
90
|
+
require 'aggro/query'
|
91
|
+
require 'aggro/saga'
|
92
|
+
require 'aggro/saga_runner'
|
93
|
+
require 'aggro/saga_status'
|
94
|
+
require 'aggro/server'
|
95
|
+
require 'aggro/subscriber'
|
96
|
+
require 'aggro/subscription'
|
6
97
|
|
7
98
|
# Public: Module for namespacing and configuration methods.
|
8
99
|
module Aggro
|
9
|
-
|
10
|
-
|
11
|
-
|
100
|
+
ClientNode = Struct.new(:id)
|
101
|
+
Event = Struct.new(:name, :occured_at, :details)
|
102
|
+
EventArgument = Struct.new(:data, :type)
|
103
|
+
EventStream = Struct.new(:id, :type, :events)
|
104
|
+
QueryError = Struct.new(:cause)
|
105
|
+
|
106
|
+
MESSAGE_TYPES = Message
|
107
|
+
.constants
|
108
|
+
.map { |sym| Message.const_get sym }
|
109
|
+
.select { |m| m.const_defined? 'TYPE_CODE' }
|
110
|
+
.each_with_object({}) { |m, h| h.merge! m::TYPE_CODE => m }
|
111
|
+
.freeze
|
112
|
+
|
113
|
+
class << self
|
114
|
+
attr_writer :data_dir
|
115
|
+
attr_writer :port
|
116
|
+
attr_writer :publisher_port
|
117
|
+
attr_writer :transport
|
118
|
+
end
|
119
|
+
|
120
|
+
module_function
|
121
|
+
|
122
|
+
def channels
|
123
|
+
if cluster_config.server_node?
|
124
|
+
@channels ||= begin
|
125
|
+
Aggro.store.registry.reduce({}) do |channels, (id, type)|
|
126
|
+
channels.merge id => Channel.new(id, type)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
@channels ||= {}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def cluster_config
|
135
|
+
@cluster_config ||= ClusterConfig.new cluster_config_path
|
136
|
+
end
|
137
|
+
|
138
|
+
def cluster_config_path
|
139
|
+
[data_dir, 'cluster.yml'].join('/')
|
140
|
+
end
|
141
|
+
|
142
|
+
def data_dir
|
143
|
+
@data_dir ||= begin
|
144
|
+
ENV.fetch('AGGRO_DIR') { './tmp/aggro' }.tap do |dir|
|
145
|
+
FileUtils.mkdir_p dir
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def event_bus
|
151
|
+
@event_bus ||= EventBus.new
|
152
|
+
end
|
153
|
+
|
154
|
+
def local_node
|
155
|
+
if cluster_config.server_node?
|
156
|
+
@local_node ||= LocalNode.new(cluster_config.node_name)
|
157
|
+
else
|
158
|
+
@local_node ||= ClientNode.new(SecureRandom.uuid)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def node_list
|
163
|
+
@node_list ||= begin
|
164
|
+
NodeList.new.tap do |node_list|
|
165
|
+
nodes = cluster_config.nodes
|
166
|
+
nodes.each { |name, server| node_list.add Node.new(name, server) }
|
167
|
+
node_list.add local_node if cluster_config.server_node?
|
168
|
+
end
|
12
169
|
end
|
13
170
|
end
|
14
171
|
|
15
|
-
def
|
16
|
-
@
|
172
|
+
def port
|
173
|
+
@port ||= ENV.fetch('PORT') { 5000 }.to_i
|
174
|
+
end
|
175
|
+
|
176
|
+
def publisher_port
|
177
|
+
@publisher_port ||= ENV.fetch('PUBLISHER_PORT') { 6000 }.to_i
|
178
|
+
end
|
179
|
+
|
180
|
+
def reset
|
181
|
+
@cluster_config = nil
|
182
|
+
@event_bus.shutdown if @event_bus
|
183
|
+
@event_bus = nil
|
184
|
+
@local_node = nil
|
185
|
+
@node_list = nil
|
186
|
+
@port = nil
|
187
|
+
@publisher = nil
|
188
|
+
@publisher_port = nil
|
189
|
+
@server = nil
|
190
|
+
@store = nil
|
191
|
+
end
|
192
|
+
|
193
|
+
def server
|
194
|
+
return unless cluster_config.server_node?
|
195
|
+
|
196
|
+
@server ||= Server.new(local_node.endpoint, local_node.publisher_endpoint)
|
197
|
+
end
|
198
|
+
|
199
|
+
def store
|
200
|
+
@store ||= FileStore.new(data_dir)
|
17
201
|
end
|
18
202
|
|
19
|
-
def
|
20
|
-
|
203
|
+
def transport
|
204
|
+
@transport ||= NanomsgTransport
|
21
205
|
end
|
22
206
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Aggro
|
2
|
+
# Public: Mixin to turn a PORO into an Aggro aggregate.
|
3
|
+
module Aggregate
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include EventDSL
|
6
|
+
|
7
|
+
def initialize(id)
|
8
|
+
@id = id
|
9
|
+
|
10
|
+
@projections = self.class.projections.reduce({}) do |h, (name, klass)|
|
11
|
+
class_eval { define_method(name) { @projections[name] } }
|
12
|
+
h.merge name => klass.new(id)
|
13
|
+
end
|
14
|
+
|
15
|
+
Aggro.event_bus.subscribe(id, self)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def apply_command(command)
|
21
|
+
return unless self.class.allows? command
|
22
|
+
|
23
|
+
@_context = command.attributes
|
24
|
+
|
25
|
+
handler = self.class.handler_for_command(command.class)
|
26
|
+
instance_exec command, &handler
|
27
|
+
ensure
|
28
|
+
@_context = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def did
|
32
|
+
fail 'Must be called within a command handler' unless @_context
|
33
|
+
|
34
|
+
@event_caller ||= EventProxy.new(self, @id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_query(query)
|
38
|
+
return unless self.class.responds_to? query
|
39
|
+
|
40
|
+
handler = self.class.handler_for_query(query.class)
|
41
|
+
instance_exec query, &handler
|
42
|
+
rescue RuntimeError => e
|
43
|
+
QueryError.new(e)
|
44
|
+
end
|
45
|
+
|
46
|
+
class_methods do
|
47
|
+
def allows(command_class, &block)
|
48
|
+
command_handlers[command_class] = block if block
|
49
|
+
end
|
50
|
+
|
51
|
+
def allows?(command)
|
52
|
+
command_handlers.keys.include? command.class
|
53
|
+
end
|
54
|
+
|
55
|
+
def create(id = SecureRandom.uuid)
|
56
|
+
find(id).create
|
57
|
+
end
|
58
|
+
|
59
|
+
def find(id)
|
60
|
+
AggregateRef.new id, name
|
61
|
+
end
|
62
|
+
|
63
|
+
def handler_for_command(command_class)
|
64
|
+
command_handlers[command_class]
|
65
|
+
end
|
66
|
+
|
67
|
+
def handler_for_query(query_class)
|
68
|
+
query_handlers[query_class]
|
69
|
+
end
|
70
|
+
|
71
|
+
def projection(projection_name, via:)
|
72
|
+
projections[projection_name] = via
|
73
|
+
end
|
74
|
+
|
75
|
+
def projections
|
76
|
+
@projections ||= {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def responds_to(query_class, &block)
|
80
|
+
query_handlers[query_class] = block if block
|
81
|
+
end
|
82
|
+
|
83
|
+
def responds_to?(query)
|
84
|
+
query_handlers.keys.include? query.class
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def command_handlers
|
90
|
+
Aggro.command_handlers[name]
|
91
|
+
end
|
92
|
+
|
93
|
+
def query_handlers
|
94
|
+
Aggro.query_handlers[name]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/aggro/aggregate_ref.rb
CHANGED
@@ -1,14 +1,76 @@
|
|
1
1
|
module Aggro
|
2
2
|
# Public: Reference to an Aggregate which may be local or remote.
|
3
|
-
class AggregateRef
|
4
|
-
|
3
|
+
class AggregateRef < Struct.new(:id, :type)
|
4
|
+
def command(command)
|
5
|
+
response = send_command(command)
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
if response.is_a? Message::InvalidTarget
|
8
|
+
create
|
9
|
+
response = send_command(command)
|
10
|
+
end
|
11
|
+
|
12
|
+
fail 'Could not send command' unless response.is_a? Message::OK
|
13
|
+
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
response = client.post build_create_message
|
19
|
+
|
20
|
+
fail 'Could not create aggregate' unless response.is_a? Message::OK
|
21
|
+
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def query(query)
|
26
|
+
response = send_query(query)
|
27
|
+
|
28
|
+
if response.is_a? Message::InvalidTarget
|
29
|
+
create
|
30
|
+
response = send_query(query)
|
31
|
+
end
|
32
|
+
|
33
|
+
handle_query_response response
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def build_command_message(command)
|
39
|
+
Message::Command.new(Aggro.local_node.id, id, command.to_details)
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_create_message
|
43
|
+
Message::CreateAggregate.new(Aggro.local_node.id, id, type)
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_query_message(query)
|
47
|
+
Message::Query.new(Aggro.local_node.id, id, query.to_details)
|
48
|
+
end
|
49
|
+
|
50
|
+
def client
|
51
|
+
locator.primary_node.client
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_query_response(message)
|
55
|
+
fail 'Could not execute query' unless message.is_a? Message::Result
|
56
|
+
|
57
|
+
if message.result.is_a? Aggro::QueryError
|
58
|
+
fail message.result.cause
|
59
|
+
else
|
60
|
+
message.result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def locator
|
65
|
+
@locator ||= Locator.new(id)
|
66
|
+
end
|
67
|
+
|
68
|
+
def send_command(command)
|
69
|
+
client.post build_command_message(command)
|
8
70
|
end
|
9
71
|
|
10
|
-
def
|
11
|
-
|
72
|
+
def send_query(query)
|
73
|
+
client.post build_query_message(query)
|
12
74
|
end
|
13
75
|
end
|
14
76
|
end
|