fluent-plugin-droonga 0.9.0 → 0.9.9
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/.travis.yml +3 -0
- data/Gemfile +8 -1
- data/fluent-plugin-droonga.gemspec +2 -2
- data/lib/droonga/adapter.rb +39 -0
- data/lib/droonga/adapter_runner.rb +99 -0
- data/lib/droonga/catalog/base.rb +11 -11
- data/lib/droonga/catalog/dataset.rb +54 -0
- data/lib/droonga/catalog/version1.rb +1 -1
- data/lib/droonga/collector.rb +5 -7
- data/lib/droonga/collector_plugin.rb +7 -7
- data/lib/droonga/command.rb +36 -0
- data/lib/droonga/{plugin/input_adapter/crud.rb → command_repository.rb} +14 -8
- data/lib/droonga/dispatcher.rb +86 -54
- data/lib/droonga/distributed_command_planner.rb +183 -0
- data/lib/droonga/distributor.rb +43 -17
- data/lib/droonga/handler.rb +13 -72
- data/lib/droonga/handler_message.rb +5 -5
- data/lib/droonga/handler_messenger.rb +4 -1
- data/lib/droonga/handler_plugin.rb +2 -2
- data/lib/droonga/handler_runner.rb +104 -0
- data/lib/droonga/input_message.rb +4 -4
- data/lib/droonga/legacy_pluggable.rb +66 -0
- data/lib/droonga/{input_adapter.rb → legacy_plugin.rb} +27 -22
- data/lib/droonga/{plugin_repository.rb → legacy_plugin_repository.rb} +2 -4
- data/lib/droonga/message_matcher.rb +101 -0
- data/lib/droonga/{input_adapter_plugin.rb → planner.rb} +14 -10
- data/lib/droonga/planner_plugin.rb +54 -0
- data/lib/droonga/pluggable.rb +9 -45
- data/lib/droonga/plugin.rb +9 -33
- data/lib/droonga/plugin/collector/basic.rb +2 -0
- data/lib/droonga/plugin/collector/search.rb +31 -37
- data/lib/droonga/plugin/{handler/groonga/table_remove.rb → metadata/adapter_message.rb} +23 -18
- data/lib/droonga/plugin/{handler/search.rb → metadata/handler_action.rb} +19 -15
- data/lib/droonga/plugin/metadata/input_message.rb +39 -0
- data/lib/droonga/plugin/planner/crud.rb +49 -0
- data/lib/droonga/plugin/{distributor → planner}/distributed_search_planner.rb +62 -70
- data/lib/droonga/plugin/{distributor → planner}/groonga.rb +11 -32
- data/lib/droonga/plugin/{distributor → planner}/search.rb +5 -5
- data/lib/droonga/plugin/{distributor → planner}/watch.rb +15 -6
- data/lib/droonga/plugin_loader.rb +10 -0
- data/lib/droonga/plugin_registerable.rb +34 -10
- data/lib/droonga/plugin_registry.rb +58 -0
- data/lib/droonga/plugins/crud.rb +124 -0
- data/lib/droonga/plugins/error.rb +50 -0
- data/lib/droonga/{output_adapter_plugin.rb → plugins/groonga.rb} +9 -13
- data/lib/droonga/plugins/groonga/column_create.rb +123 -0
- data/lib/droonga/plugins/groonga/generic_command.rb +65 -0
- data/lib/droonga/{plugin/output_adapter/groonga.rb → plugins/groonga/generic_response.rb} +16 -15
- data/lib/droonga/plugins/groonga/select.rb +124 -0
- data/lib/droonga/plugins/groonga/table_create.rb +106 -0
- data/lib/droonga/plugins/groonga/table_remove.rb +57 -0
- data/lib/droonga/plugins/search.rb +40 -0
- data/lib/droonga/plugins/watch.rb +156 -0
- data/lib/droonga/processor.rb +8 -10
- data/lib/droonga/searcher.rb +14 -4
- data/lib/droonga/searcher/mecab_filter.rb +67 -0
- data/lib/droonga/session.rb +5 -5
- data/lib/droonga/test.rb +1 -1
- data/lib/droonga/test/stub_handler_message.rb +1 -1
- data/lib/droonga/test/{stub_distributor.rb → stub_planner.rb} +1 -1
- data/lib/droonga/worker.rb +7 -8
- data/lib/fluent/plugin/out_droonga.rb +0 -1
- data/sample/cluster/catalog.json +2 -4
- data/sample/mecab_filter/data.grn +7 -0
- data/sample/mecab_filter/ddl.grn +7 -0
- data/sample/mecab_filter/search_with_mecab_filter.json +21 -0
- data/sample/mecab_filter/search_without_mecab_filter.json +21 -0
- data/test/command/config/default/catalog.json +2 -5
- data/test/command/suite/search/error/no-query.expected +13 -0
- data/test/command/suite/search/error/no-query.test +7 -0
- data/test/command/suite/search/error/unknown-source.expected +26 -0
- data/test/command/suite/watch/subscribe.expected +3 -3
- data/test/command/suite/watch/unsubscribe.expected +3 -3
- data/test/unit/catalog/test_dataset.rb +385 -0
- data/test/unit/catalog/test_version1.rb +111 -45
- data/test/unit/fixtures/catalog/version1.json +0 -3
- data/test/unit/helper.rb +2 -1
- data/test/unit/helper/distributed_search_planner_helper.rb +83 -0
- data/test/unit/plugin/collector/test_basic.rb +233 -376
- data/test/unit/plugin/collector/test_search.rb +8 -17
- data/test/unit/plugin/planner/search_planner/test_basic.rb +120 -0
- data/test/unit/plugin/planner/search_planner/test_group_by.rb +573 -0
- data/test/unit/plugin/planner/search_planner/test_output.rb +388 -0
- data/test/unit/plugin/planner/search_planner/test_sort_by.rb +938 -0
- data/test/unit/plugin/{distributor → planner}/test_search.rb +20 -75
- data/test/unit/{plugin/handler → plugins/crud}/test_add.rb +11 -11
- data/test/unit/plugins/groonga/select/test_adapter_input.rb +213 -0
- data/test/unit/{plugin/output_adapter/groonga/test_select.rb → plugins/groonga/select/test_adapter_output.rb} +12 -13
- data/test/unit/{plugin/handler → plugins}/groonga/test_column_create.rb +20 -5
- data/test/unit/{plugin/handler → plugins}/groonga/test_table_create.rb +5 -0
- data/test/unit/{plugin/handler → plugins}/groonga/test_table_remove.rb +8 -1
- data/test/unit/{plugin/handler → plugins}/test_groonga.rb +5 -5
- data/test/unit/{plugin/handler → plugins}/test_search.rb +21 -5
- data/test/unit/{plugin/handler → plugins}/test_watch.rb +29 -10
- data/{lib/droonga/command_mapper.rb → test/unit/test_command_repository.rb} +16 -22
- data/test/unit/{test_plugin.rb → test_legacy_plugin.rb} +3 -3
- data/test/unit/{test_plugin_repository.rb → test_legacy_plugin_repository.rb} +3 -3
- data/test/unit/test_message_matcher.rb +137 -0
- metadata +86 -66
- data/bin/grn2jsons +0 -82
- data/lib/droonga/distribution_planner.rb +0 -76
- data/lib/droonga/distributor_plugin.rb +0 -95
- data/lib/droonga/output_adapter.rb +0 -53
- data/lib/droonga/plugin/collector/groonga.rb +0 -83
- data/lib/droonga/plugin/distributor/crud.rb +0 -84
- data/lib/droonga/plugin/handler/add.rb +0 -109
- data/lib/droonga/plugin/handler/forward.rb +0 -75
- data/lib/droonga/plugin/handler/groonga.rb +0 -99
- data/lib/droonga/plugin/handler/groonga/column_create.rb +0 -106
- data/lib/droonga/plugin/handler/groonga/table_create.rb +0 -91
- data/lib/droonga/plugin/handler/watch.rb +0 -108
- data/lib/droonga/plugin/input_adapter/groonga.rb +0 -49
- data/lib/droonga/plugin/input_adapter/groonga/select.rb +0 -63
- data/lib/droonga/plugin/output_adapter/crud.rb +0 -51
- data/lib/droonga/plugin/output_adapter/groonga/select.rb +0 -54
- data/lib/groonga_command_converter.rb +0 -143
- data/sample/fluentd.conf +0 -8
- data/test/unit/plugin/distributor/test_search_planner.rb +0 -1102
- data/test/unit/plugin/input_adapter/groonga/test_select.rb +0 -248
- data/test/unit/test_command_mapper.rb +0 -44
- data/test/unit/test_groonga_command_converter.rb +0 -242
data/lib/droonga/dispatcher.rb
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Copyright (C) 2013 Droonga Project
|
|
1
|
+
# Copyright (C) 2013-2014 Droonga Project
|
|
4
2
|
#
|
|
5
3
|
# This library is free software; you can redistribute it and/or
|
|
6
4
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -18,9 +16,8 @@
|
|
|
18
16
|
require "English"
|
|
19
17
|
require "tsort"
|
|
20
18
|
|
|
21
|
-
require "droonga/
|
|
22
|
-
require "droonga/
|
|
23
|
-
require "droonga/distributor"
|
|
19
|
+
require "droonga/adapter_runner"
|
|
20
|
+
require "droonga/planner"
|
|
24
21
|
require "droonga/catalog"
|
|
25
22
|
require "droonga/collector"
|
|
26
23
|
require "droonga/farm"
|
|
@@ -28,6 +25,7 @@ require "droonga/session"
|
|
|
28
25
|
require "droonga/replier"
|
|
29
26
|
require "droonga/message_processing_error"
|
|
30
27
|
require "droonga/catalog_observer"
|
|
28
|
+
require "droonga/distributor"
|
|
31
29
|
|
|
32
30
|
module Droonga
|
|
33
31
|
class Dispatcher
|
|
@@ -39,6 +37,12 @@ module Droonga
|
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
40
|
+
class UnknownDataset < NotFound
|
|
41
|
+
def initialize(dataset)
|
|
42
|
+
super("The dataset #{dataset.inspect} does not exist.")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
42
46
|
class UnknownCommand < BadRequest
|
|
43
47
|
def initialize(command, dataset)
|
|
44
48
|
super("The command #{command.inspect} is not available " +
|
|
@@ -54,15 +58,14 @@ module Droonga
|
|
|
54
58
|
@sessions = {}
|
|
55
59
|
@current_id = 0
|
|
56
60
|
@local = Regexp.new("^#{@name}")
|
|
57
|
-
@
|
|
58
|
-
InputAdapter.new(self, :plugins => Droonga.catalog.option("plugins"))
|
|
59
|
-
@output_adapter =
|
|
60
|
-
OutputAdapter.new(self, :plugins => Droonga.catalog.option("plugins"))
|
|
61
|
+
@adapter_runners = create_adapter_runners
|
|
61
62
|
@farm = Farm.new(name, @loop, :dispatcher => self)
|
|
62
63
|
@forwarder = Forwarder.new(@loop)
|
|
63
64
|
@replier = Replier.new(@forwarder)
|
|
64
|
-
|
|
65
|
-
@
|
|
65
|
+
# TODO: make customizable
|
|
66
|
+
@planner = Planner.new(self, ["search", "crud", "groonga", "watch"])
|
|
67
|
+
# TODO: make customizable
|
|
68
|
+
@collector = Collector.new(["basic", "search"])
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
def start
|
|
@@ -75,10 +78,11 @@ module Droonga
|
|
|
75
78
|
|
|
76
79
|
def shutdown
|
|
77
80
|
@forwarder.shutdown
|
|
78
|
-
@
|
|
81
|
+
@planner.shutdown
|
|
79
82
|
@collector.shutdown
|
|
80
|
-
@
|
|
81
|
-
|
|
83
|
+
@adapter_runners.each_value do |adapter_runner|
|
|
84
|
+
adapter_runner.shutdown
|
|
85
|
+
end
|
|
82
86
|
@farm.shutdown
|
|
83
87
|
@loop.stop
|
|
84
88
|
@loop_thread.join
|
|
@@ -90,11 +94,17 @@ module Droonga
|
|
|
90
94
|
process_internal_message(message["body"])
|
|
91
95
|
else
|
|
92
96
|
begin
|
|
93
|
-
assert_valid_message
|
|
97
|
+
assert_valid_message(message)
|
|
94
98
|
process_input_message(message)
|
|
95
99
|
rescue MessageProcessingError => error
|
|
96
100
|
reply("statusCode" => error.status_code,
|
|
97
101
|
"body" => error.response_body)
|
|
102
|
+
rescue => error
|
|
103
|
+
Logger.error("failed to process input message", error)
|
|
104
|
+
formatted_error = MessageProcessingError.new("Unknown internal error")
|
|
105
|
+
reply("statusCode" => formatted_error.status_code,
|
|
106
|
+
"body" => formatted_error.response_body)
|
|
107
|
+
raise error
|
|
98
108
|
end
|
|
99
109
|
end
|
|
100
110
|
end
|
|
@@ -118,7 +128,11 @@ module Droonga
|
|
|
118
128
|
#
|
|
119
129
|
# @see Replier#reply
|
|
120
130
|
def reply(message)
|
|
121
|
-
adapted_message = @
|
|
131
|
+
adapted_message = @message.merge(message)
|
|
132
|
+
adapter_runner = @adapter_runners[adapted_message["dataset"]]
|
|
133
|
+
if adapter_runner
|
|
134
|
+
adapted_message = adapter_runner.adapt_output(adapted_message)
|
|
135
|
+
end
|
|
122
136
|
return if adapted_message["replyTo"].nil?
|
|
123
137
|
@replier.reply(adapted_message)
|
|
124
138
|
end
|
|
@@ -129,10 +143,10 @@ module Droonga
|
|
|
129
143
|
if session
|
|
130
144
|
session.receive(message["input"], message["value"])
|
|
131
145
|
else
|
|
132
|
-
|
|
133
|
-
if
|
|
134
|
-
|
|
135
|
-
session =
|
|
146
|
+
steps = message["steps"]
|
|
147
|
+
if steps
|
|
148
|
+
session_planner = SessionPlanner.new(self, steps)
|
|
149
|
+
session = session_planner.create_session(id, @collector)
|
|
136
150
|
@sessions[id] = session
|
|
137
151
|
else
|
|
138
152
|
#todo: take cases receiving result before its query into account
|
|
@@ -152,23 +166,23 @@ module Droonga
|
|
|
152
166
|
end
|
|
153
167
|
end
|
|
154
168
|
|
|
155
|
-
def
|
|
169
|
+
def dispatch_steps(steps)
|
|
156
170
|
id = generate_id
|
|
157
171
|
destinations = {}
|
|
158
|
-
|
|
159
|
-
dataset =
|
|
172
|
+
steps.each do |step|
|
|
173
|
+
dataset = step["dataset"]
|
|
160
174
|
if dataset
|
|
161
|
-
routes = Droonga.catalog.get_routes(dataset,
|
|
162
|
-
|
|
175
|
+
routes = Droonga.catalog.get_routes(dataset, step)
|
|
176
|
+
step["routes"] = routes
|
|
163
177
|
else
|
|
164
|
-
|
|
178
|
+
step["routes"] ||= [id]
|
|
165
179
|
end
|
|
166
|
-
routes =
|
|
180
|
+
routes = step["routes"]
|
|
167
181
|
routes.each do |route|
|
|
168
182
|
destinations[farm_path(route)] = true
|
|
169
183
|
end
|
|
170
184
|
end
|
|
171
|
-
dispatch_message = { "id" => id, "
|
|
185
|
+
dispatch_message = { "id" => id, "steps" => steps }
|
|
172
186
|
destinations.each_key do |destination|
|
|
173
187
|
dispatch(dispatch_message, destination)
|
|
174
188
|
end
|
|
@@ -177,10 +191,10 @@ module Droonga
|
|
|
177
191
|
def process_local_message(local_message)
|
|
178
192
|
task = local_message["task"]
|
|
179
193
|
partition_name = task["route"]
|
|
180
|
-
|
|
181
|
-
command =
|
|
194
|
+
step = task["step"]
|
|
195
|
+
command = step["command"]
|
|
182
196
|
descendants = {}
|
|
183
|
-
|
|
197
|
+
step["descendants"].each do |name, routes|
|
|
184
198
|
descendants[name] = routes.collect do |route|
|
|
185
199
|
farm_path(route)
|
|
186
200
|
end
|
|
@@ -211,43 +225,61 @@ module Droonga
|
|
|
211
225
|
end
|
|
212
226
|
|
|
213
227
|
def process_input_message(message)
|
|
214
|
-
|
|
215
|
-
@
|
|
216
|
-
|
|
228
|
+
dataset = message["dataset"]
|
|
229
|
+
adapter_runner = @adapter_runners[dataset]
|
|
230
|
+
adapted_message = adapter_runner.adapt_input(message)
|
|
231
|
+
plan = @planner.process(adapted_message["type"], adapted_message)
|
|
232
|
+
distributor = Distributor.new(self)
|
|
233
|
+
distributor.distribute(plan)
|
|
234
|
+
rescue Droonga::LegacyPluggable::UnknownPlugin => error
|
|
217
235
|
raise UnknownCommand.new(error.command, message["dataset"])
|
|
218
236
|
end
|
|
219
237
|
|
|
220
|
-
def assert_valid_message
|
|
221
|
-
|
|
238
|
+
def assert_valid_message(message)
|
|
239
|
+
unless message.key?("dataset")
|
|
240
|
+
raise MissingDatasetParameter.new
|
|
241
|
+
end
|
|
242
|
+
dataset = message["dataset"]
|
|
243
|
+
unless Droonga.catalog.have_dataset?(dataset)
|
|
244
|
+
raise UnknownDataset.new(dataset)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def create_adapter_runners
|
|
249
|
+
runners = {}
|
|
250
|
+
Droonga.catalog.datasets.each do |name, configuration|
|
|
251
|
+
runners[name] = AdapterRunner.new(self, configuration["plugins"] || [])
|
|
252
|
+
end
|
|
253
|
+
runners
|
|
222
254
|
end
|
|
223
255
|
|
|
224
256
|
def log_tag
|
|
225
257
|
"[#{Process.ppid}][#{Process.pid}] dispatcher"
|
|
226
258
|
end
|
|
227
259
|
|
|
228
|
-
class
|
|
229
|
-
attr_reader :
|
|
260
|
+
class SessionPlanner
|
|
261
|
+
attr_reader :steps
|
|
230
262
|
|
|
231
|
-
def initialize(dispatcher,
|
|
263
|
+
def initialize(dispatcher, steps)
|
|
232
264
|
@dispatcher = dispatcher
|
|
233
|
-
@
|
|
265
|
+
@steps = steps
|
|
234
266
|
end
|
|
235
267
|
|
|
236
268
|
def create_session(id, collector)
|
|
237
269
|
resolve_descendants
|
|
238
270
|
tasks = []
|
|
239
271
|
inputs = {}
|
|
240
|
-
@
|
|
241
|
-
|
|
272
|
+
@steps.each do |step|
|
|
273
|
+
step["routes"].each do |route|
|
|
242
274
|
next unless @dispatcher.local?(route)
|
|
243
275
|
task = {
|
|
244
276
|
"route" => route,
|
|
245
|
-
"
|
|
277
|
+
"step" => step,
|
|
246
278
|
"n_of_inputs" => 0,
|
|
247
279
|
"values" => {}
|
|
248
280
|
}
|
|
249
281
|
tasks << task
|
|
250
|
-
(
|
|
282
|
+
(step["inputs"] || [nil]).each do |input|
|
|
251
283
|
inputs[input] ||= []
|
|
252
284
|
inputs[input] << task
|
|
253
285
|
end
|
|
@@ -258,24 +290,24 @@ module Droonga
|
|
|
258
290
|
|
|
259
291
|
def resolve_descendants
|
|
260
292
|
@descendants = {}
|
|
261
|
-
@
|
|
262
|
-
|
|
263
|
-
(
|
|
293
|
+
@steps.size.times do |index|
|
|
294
|
+
step = @steps[index]
|
|
295
|
+
(step["inputs"] || []).each do |input|
|
|
264
296
|
@descendants[input] ||= []
|
|
265
297
|
@descendants[input] << index
|
|
266
298
|
end
|
|
267
|
-
|
|
299
|
+
step["n_of_expects"] = 0
|
|
268
300
|
end
|
|
269
|
-
@
|
|
301
|
+
@steps.each do |step|
|
|
270
302
|
descendants = {}
|
|
271
|
-
(
|
|
303
|
+
(step["outputs"] || []).each do |output|
|
|
272
304
|
descendants[output] = []
|
|
273
305
|
@descendants[output].each do |index|
|
|
274
|
-
@
|
|
275
|
-
descendants[output].concat(@
|
|
306
|
+
@steps[index]["n_of_expects"] += step["routes"].size
|
|
307
|
+
descendants[output].concat(@steps[index]["routes"])
|
|
276
308
|
end
|
|
277
309
|
end
|
|
278
|
-
|
|
310
|
+
step["descendants"] = descendants
|
|
279
311
|
end
|
|
280
312
|
end
|
|
281
313
|
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
|
|
18
|
+
module Droonga
|
|
19
|
+
class DistributedCommandPlanner
|
|
20
|
+
attr_accessor :key, :dataset
|
|
21
|
+
|
|
22
|
+
REDUCE_SUM = "sum"
|
|
23
|
+
|
|
24
|
+
DEFAULT_LIMIT = -1
|
|
25
|
+
|
|
26
|
+
def initialize(source_message)
|
|
27
|
+
@source_message = source_message
|
|
28
|
+
|
|
29
|
+
@key = nil
|
|
30
|
+
@dataset = nil
|
|
31
|
+
@outputs = []
|
|
32
|
+
|
|
33
|
+
@reducers = []
|
|
34
|
+
@gatherers = []
|
|
35
|
+
@processor = nil
|
|
36
|
+
|
|
37
|
+
plan_errors_handling
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def plan
|
|
41
|
+
unified_reducers + unified_gatherers + [fixed_processor]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reduce(params=nil)
|
|
45
|
+
return unless params
|
|
46
|
+
params.each do |name, reducer|
|
|
47
|
+
gatherer = nil
|
|
48
|
+
if reducer.is_a?(Hash) && reducer[:gather]
|
|
49
|
+
gatherer = reducer[:gather]
|
|
50
|
+
reducer = reducer[:reduce]
|
|
51
|
+
end
|
|
52
|
+
@reducers << reducer_message(reduce_command, name, reducer)
|
|
53
|
+
@gatherers << gatherer_message(gather_command, name, gatherer)
|
|
54
|
+
@outputs << name
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def scatter(options={})
|
|
59
|
+
@processor = {
|
|
60
|
+
"command" => @source_message["type"],
|
|
61
|
+
"dataset" => @dataset || @source_message["dataset"],
|
|
62
|
+
"body" => options[:body] || @source_message["body"],
|
|
63
|
+
"key" => nil,
|
|
64
|
+
"type" => "scatter",
|
|
65
|
+
"outputs" => [],
|
|
66
|
+
"replica" => "all",
|
|
67
|
+
"post" => true
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def broadcast(options={})
|
|
72
|
+
processor = {
|
|
73
|
+
"command" => @source_message["type"],
|
|
74
|
+
"dataset" => @dataset || @source_message["dataset"],
|
|
75
|
+
"body" => options[:body] || @source_message["body"],
|
|
76
|
+
"type" => "broadcast",
|
|
77
|
+
"outputs" => [],
|
|
78
|
+
"replica" => "random"
|
|
79
|
+
}
|
|
80
|
+
if options[:write]
|
|
81
|
+
processor["replica"] = "all"
|
|
82
|
+
processor["post"] = true
|
|
83
|
+
end
|
|
84
|
+
@processor = processor
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
def reduce_command
|
|
89
|
+
"reduce"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def gather_command
|
|
93
|
+
"gather"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def unified_reducers
|
|
97
|
+
unified_reducers = {}
|
|
98
|
+
@reducers.each do |reducer|
|
|
99
|
+
type = reducer["type"]
|
|
100
|
+
unified = unified_reducers[type]
|
|
101
|
+
if unified
|
|
102
|
+
unified["body"] = unified["body"].merge(reducer["body"])
|
|
103
|
+
unified["inputs"] = unified["inputs"] + reducer["inputs"]
|
|
104
|
+
unified["outputs"] = unified["outputs"] + reducer["outputs"]
|
|
105
|
+
else
|
|
106
|
+
unified_reducers[type] = Marshal.load(Marshal.dump(reducer))
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
unified_reducers.values
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def unified_gatherers
|
|
113
|
+
unified_gatherers = {}
|
|
114
|
+
@gatherers.each do |gatherer|
|
|
115
|
+
type = gatherer["type"]
|
|
116
|
+
unified = unified_gatherers[type]
|
|
117
|
+
if unified
|
|
118
|
+
unified["body"] = unified["body"].merge(gatherer["body"])
|
|
119
|
+
unified["inputs"] = unified["inputs"] + gatherer["inputs"]
|
|
120
|
+
else
|
|
121
|
+
unified_gatherers[type] = Marshal.load(Marshal.dump(gatherer))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
unified_gatherers.values
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def fixed_processor
|
|
128
|
+
@processor["outputs"] = @outputs
|
|
129
|
+
if @processor["type"] == "scatter"
|
|
130
|
+
raise MessageProcessingError.new("missing key") unless @key
|
|
131
|
+
@processor["key"] = @key
|
|
132
|
+
end
|
|
133
|
+
@processor
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def reducer_message(command, name, reducer)
|
|
137
|
+
if reducer.is_a?(String)
|
|
138
|
+
reducer = {
|
|
139
|
+
"type" => reducer,
|
|
140
|
+
}
|
|
141
|
+
if reducer["type"] == REDUCE_SUM
|
|
142
|
+
reducer["limit"] = DEFAULT_LIMIT
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
{
|
|
146
|
+
"type" => command,
|
|
147
|
+
"body" => {
|
|
148
|
+
name => {
|
|
149
|
+
output_name(name) => reducer,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
"inputs" => [name],
|
|
153
|
+
"outputs" => [output_name(name)],
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def gatherer_message(command, name, gatherer=nil)
|
|
158
|
+
gatherer ||= {}
|
|
159
|
+
{
|
|
160
|
+
"type" => command,
|
|
161
|
+
"body" => {
|
|
162
|
+
output_name(name) => {
|
|
163
|
+
"output" => name,
|
|
164
|
+
}.merge(gatherer),
|
|
165
|
+
},
|
|
166
|
+
"inputs" => [output_name(name)],
|
|
167
|
+
"post" => true,
|
|
168
|
+
}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def output_name(name)
|
|
172
|
+
"#{name}_reduced"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
#XXX Now, we include definitions to merge errors in the body.
|
|
176
|
+
# However, this makes the term "errors" reserved, so plugins
|
|
177
|
+
# cannot use their custom "errors" in the body.
|
|
178
|
+
# This must be rewritten.
|
|
179
|
+
def plan_errors_handling
|
|
180
|
+
reduce("errors"=> REDUCE_SUM)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|